Posted about 1 month ago. Visible to the public.

How to use ActiveSupport Concerns with dynamic relations

The usual way to build a relation in a ActiveSupport::Concern is this:

Copy
module MyModule extend ActiveSupport::Concern included do scope :disabled, -> { where(disabled: true) } end end

However, if you have a association with a polymorphic model, where you have to select based on the kind of record, using included like this will not produce the wanted results:

Copy
module MyModule extend ActiveSupport::Concern included do has_many :tasks, -> { where concrete_mission_type: self.class.name }, foreign_key: :mission_id, inverse_of: :mission end end
Copy
> mission.tasks.to_sql "SELECT \"tasks\".* FROM \"tasks\" WHERE \"tasks\".\"mission_id\" = 735 AND \"tasks\".\"concrete_mission_type\" = 'ActiveRecord::Relation'"

You can fix that through using self.included(subclass) in your concern:

Copy
module MyModule extend ActiveSupport::Concern def self.included(subclass) subclass.class_eval do has_many :tasks, -> { where concrete_mission_type: subclass.name }, foreign_key: :mission_id, inverse_of: :mission end super end end
Copy
> mission.tasks.to_sql "SELECT \"tasks\".* FROM \"tasks\" WHERE \"tasks\".\"mission_id\" = 737 AND \"tasks\".\"concrete_mission_type\" = 'ConspirationFinder'"

If you want to know more about self.included, see this card.

makandra has been working exclusively with Ruby on Rails since 2007. Our laser focus on a single technology has made us a leader in this space.

Owner of this card:

Avatar
Judith Roth
Last edit:
about 1 month ago
by Judith Roth
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Judith Roth to makandra dev
This website uses short-lived cookies to improve usability.
Accept or learn more