Extending ActiveRecord association to cleanup your associations code

For some reason not many RoR developers know that they can extend ActiveRecord associations. This feature can be a great way to cleanup any relational code that is dependent on a parent resource (or to just add a simple functionalities to scopes). Here’s a really simple example how you can use it:

class User < ActiveRecord::Base
  module GroupActions
    # Here you work on a scope
    def reactivate!
      # I know we could use update_all - this is not the case ;)

  belongs_to :group

  def reactivate!
    update!(active: true)

class Group < ActiveRecord::Base
  has_many :users, extend: User::GroupActions

That way you can perform actions like this one:

# Looks much better than any method like current_group.reactivate_users!

Dynamic pagination (changeable per page on a parent resource)

You can also use a small trick to access parent model and it’s data. It can be useful for example when implementing a dynamic pagination model (based on a parent key value) or any other functionality that somehow depends on a relation owning model. Instead of doing something like this in your controllers:

def index
  @pictures = current_gallery.pictures.per(current_gallery.per_page).page(current_page)

you can leave the implementation details out of it (which in general is a good idea):

def index
  @pictures = current_gallery.pictures.paginated(current_page)

And this is how you can achieve such a behavior:

class Gallery < ActiveRecord::Base
  has_many :pictures,
    extend: Picture::RelationExtensions

  validates :per_page,
    numericality: { only_integer: true },
    inclusion: { in: (1..100).to_a }

class Picture < ActiveRecord::Base
  module RelationExtensions
    def paginated(current_page)
      # We create a picture instance that has a gallery reference already
      # because in the controller - gallery is a current scope starting point

  belongs_to :gallery, inverse_of:  :pictures

It’s a really great idea to use approach like this also because you can use it with any standard scope:

# or if you return an active record association you can chain methods


If you want to hide implementation details of any association related action (especially when it uses owning model fields data), using ActiveRecord association can be a really good idea.

Empty? vs blank? vs any? – why you should not use any? to test if there’s anything in the array

I often work with junior programmers and somehow they tend to use syntax like this:

return unless array_data.any?
# or
do something if array_data.any?

And there’s almost nothing wrong with it, as long as you don’t work with huge arrays.

Here’s a difference in speed between empty?, blank? and any? with different array sizes (worse scenario):


Why any? is so slow with bigger arrays? Well, basically because it iterates through the whole the collection and checks if there’s at least one non-false and non-nil element (when no block given). Of course it will stop with the first non-false value, but we were pessimistic and we assumed that there are no elements like that. Many developers assume that any? answers the: “is there anything in the array” question, when it really answers: “is there at least one non-false and non-nil element in the array”. And this can make huge difference with bigger arrays.

Of course if we decide to have a true-like value in a random place of an array, things look a bit different:

randomMore or less it looks randomly, but you can see a general pattern – the more elements there are, the longer it can get.

Conclusion: Using any? to determine, if there’s anything in the array can have a huge impact on your code performance if you work with bigger arrays. And even if you don’t, having bad habits is not a good idea.

Jun 2015
POSTED IN Ruby Software