Tag: ActiveRecord::Relation

[ActiveRecord] Get a polymorphic owner class out of the owned object

The question is: how can we retrieve a owners class of a polymorphic association without loading the owner object into memory?

class Source < ApplicationRecord
  self.has_one :state,
    dependent: :delete,
    as: :stateable

class State < ApplicationRecord
  belongs_to :stateable,
    polymorphic: true


There are (at least) two ways to do this. First one is not recommended (as it might fail with multiple namespaces with same class names, etc:

State.last.stateable_type.constantize #=> Source

or a better one that will work out of any scope:

State.last.association(:stateable).klass #=> Source

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.

Copyright © 2023 Closer to Code

Theme by Anders NorenUp ↑