Today I Learned Notes to self about software development

    Ruby Refinements

    Whenever I’ve had a predifined class and wanted to add/modify a method to it, I’ve always patched it or seen people make a Concern or something.

    Apparently, Ruby has a built in thing for this exactly that is better called Refinements.

    # Instead of a monkey patch
    
    class String
      def to_a
        return [] if blank?
    
        str = dup
        str.slice!("[")
        str.slice!("]")
        str.split(",")
      end
    end
    
    # Do this instead
    
    
    module StringToArray
      refine String do
        def to_a
          return [] if blank?
    
          str = dup
          str.slice!("[")
          str.slice!("]")
          str.split(",")
        end
      end
    end
    
    # Then in module or class that you use it
    module ResourceCreator
      using StringToArray
    end
    

    Git Bisect

    Binary search through your git log to find where you hecked up and introduced a bug.

    This command saved my life. I was trying to debug a really silly error that I couldn’t debug with error messages because the issue happened because a method was added to a core class and the stacktrace was not helpful. git bisect was the ONLY thing that worked.

    Video I watched:

    Notes

    git bisect start
    git bisect bad          # marks current commit doesn't work
    git bisect good d0bf3f6 # specify latest commit that *does* work
    
    # for each commit given, mark bad or good with
    git bisect bad
    git bisect good
    # when done,
    git bisect reset
    

    Aside: embed videos in markdown with: https://markdown-videos.jorgenkh.no/

    Bootstrap Modal with Dynamic Content

    For context, I was working on a feature to to allow users to preview the associated thread (in a modal) of each notification from the notifications index page. While the notifications were paginated, the post threads could be very large. The naive approach of just having a modal for each notification was very ineffecient when threads were large and made the page load slow.

    To increase the performace, I wanted to render just one modal and have the content change depending on which notification was clicked.

    This was a little tricky to get timings right for when and what content to load, but this article helped me a lot.

    https://philonrails.substack.com/p/loading-dynamic-content-on-opening

    Eventually I added an auto-scroll to the exact part of the thread that was related to the notification to.

    Truncate HTML without cutting off HTML tags

    I ran into an issue trying to truncate a users post in a notification email. Posts can contain markdown and thus HTML so it was difficult to style the truncated text because if the post contained HTML I could cut off a closing tag which would mess up the formatting of the rest of the email.

    I wanted a way to truncate just the text part of the String and not the HTML tags.

    The only gem I found that worked was Truncato. See this SO question.

    In the end, I created a view helper that also sanitized the HTML so I could create an “allowlist” of tags that I could keep in the output. Truncato has effectively a “denylist” option, but it felt like that could get too large.

    It looked like this:

    def truncated_sanitized_html(html, **options)
      sanitized_html  = sanitize(html, tags: options[:tags])
      Truncato.truncate(sanitized_html, max_length: options[:max_length]).html_safe
    end
    
    
    truncated_sanitized_html(post.to_html, tags: %w(p div span code table td tbody tr pre), max_length: 1000)
    

    Skip Git Commit Hooks

    Occasionally I find myself in situations where I want to make a commit, but I don’t want git commit hooks to run because it will format the code and I don’t want it to.

    (I plan to eventually format the code, but sometimes, especially when the commit is a work in progress, I don’t want to format anything since I haven’t solidified what I want to do yet)

    The easiest way to do this is to use the --no-verify flag.

    git commit -m "WIP" --no-verify
    

    Soure