Arjan
Arjan

Reputation: 6274

Single table inheritance scopes

Is it possible to set-up a scope on a single table inheritance that returns the subclass?

For example:

class Post < ActiveRecord::Base
  scope :sticky, -> { where(type: 'StickyPost') }
end

class StickyPost < Post
end

Now, when I call sticky on a collection of posts I get a collection of StickyPost instances.

But when I call posts.sticky.build, the type is set to StickyPost, but the class still is Post.

posts.sticky.build
=> #<Post id: nil, message: nil, type: "StickyPost", created_at: nil, updated_at: nil>

Update

Apparently this works.

posts.sticky.build type: 'StickyPost'
=> #<StickyPost id: nil, message: nil, type: "StickyPost", created_at: nil, updated_at: nil>

Which is strange, since the scope already sets the type, it seems a bit redundant. Any way to set this behaviour in the scope?

Upvotes: 9

Views: 2512

Answers (1)

You can make the sticky scope return the correct class by using becomes method in the scope:

class Post < ActiveRecord::Base
  scope :sticky, -> { where(type: 'StickyPost').becomes(StickyPost) }
end

The becomes method maps an instance of one class to another class in the single-table inheritance hierarchy. In this case, it maps each instance of Post returned by the sticky scope to StickyPost. With this change, calling posts.sticky.build will now return an instance of StickyPost:

posts.sticky.build
=> #<StickyPost id: nil, message: nil, type: "StickyPost", created_at: nil, updated_at: nil>

Upvotes: -1

Related Questions