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 ;) map(&:reactivate!) end end belongs_to :group def reactivate! update!(active: true) end end class Group < ActiveRecord::Base has_many :users, extend: User::GroupActions end
That way you can perform actions like this one:
# Looks much better than any method like current_group.reactivate_users! current_group.users.reactivate!
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) end
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) end
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 } end 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 page(current_page).per(self.new.gallery.per_page) end end belongs_to :gallery, inverse_of: :pictures end
It's a really great idea to use approach like this also because you can use it with any standard scope:
current_gallery.active.paginated(current_page) # or if you return an active record association you can chain methods current_gallery.active.paginated(current_page).reactivate!
Conclusion
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.