Thursday, February 26, 2015

Touch objects in a has_and_belongs_to_many association

On has_many relations, there is a simple way to update all associated objects - just add touch: true and the updated_at field on all associated objects will get updated. This is a major issue with Russian Doll caching, because this is was expires the cache and makes sure the page shows the most recent changes. However has_and_belongs_to_many (HABTM) does not have a :touch option. It must be done manually. So, here's a quick and easy way to do this:

  class Category
    before_save :touch_videos

    def touch_videos
      videos.touch
    end
  end

  class Video
    def self.touch
      update_all(updated_at: Time.now)
      # or, if you need validations to run for some reason
      find_each { |video| video.touch }
    end
  end

Wednesday, February 25, 2015

Handling nil values with #to_s

Occasionally, I have run into 500 server errors because there is an object attribute that is nil and I try to run a method on it. This tended to happen in my jbuilder files for returning API responses where the mobile app needed data in a certain format. Here's the simplest way to fix this:

nil.to_s 
#=> Outputs “”

Even if I wasn't getting server errors, in jbuilder files, often returning a null value in the response can be problematic for whatever app is using that response, so if there’s a chance an object attribute is nil, instead of doing an if/else, simple run #to_s on the attribute. I’m guessing this might be a slight performance hit, but probably not much more than an if/else statement would be.

Thursday, February 12, 2015

Enumerate in reverse with true indexes in Ruby

I had a problem one day where I had a list that I wanted to enumerate over, but I wanted to do it in reverse order. Easy peasy by just calling #reverse on the collection, right? Sure, except that I wanted the index as well. Oh, and I wanted the index to start with the last one instead of zero.

Now it's getting good.

I found this beauty on StackOverflow (thanks Bue Grønlund, whoever you are). To do a reverse each_with_index with the true index:

['Seriously', 'Chunky', 'Bacon'].to_enum.with_index.reverse_each do |word, index| 
  puts "index #{index}: #{word}" 
end

Output:

index 2: Bacon 
index 1: Chunky 
index 0: Seriously

Pretty nifty!

Monday, February 2, 2015

Make an array of sequential numbers in Ruby

There are lots of ways to do this, but this one is the most fun and most terse I've found:

  [*1..7]
  # => [1,2,3,4,5,6,7]

And that's Jenga.