Posted 17 days 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.

By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.

Owner of this card:

Avatar
Judith Roth
Last edit:
12 days 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