Module: ActiveRecord::HasSomeOfMany::Associations
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/activerecord/has_some_of_many/associations.rb
Class Method Summary collapse
- .build(klass, association_type, name, scope = nil, **options) ⇒ Object
- .build_scope(klass, relation, primary_key:, foreign_key:, foreign_key_alias:, limit: nil) ⇒ Object
Class Method Details
.build(klass, association_type, name, scope = nil, **options) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/activerecord/has_some_of_many/associations.rb', line 13 def self.build(klass, association_type, name, scope = nil, **) primary_key = [:primary_key] || klass.primary_key foreign_key = [:foreign_key] || ActiveSupport::Inflector.foreign_key(klass, true) foreign_key_alias = [:foreign_key_alias] || "#{foreign_key}_alias" lateral_subselection_scope = lambda do relation = scope ? instance_exec(&scope) : self limit = association_type == :has_one ? 1 : nil ActiveRecord::HasSomeOfMany::Associations.build_scope(klass, relation, primary_key: primary_key, foreign_key: foreign_key, foreign_key_alias: foreign_key_alias, limit: limit) end [:primary_key] = primary_key [:foreign_key] = foreign_key_alias klass.send(association_type, name, lateral_subselection_scope, **) end |
.build_scope(klass, relation, primary_key:, foreign_key:, foreign_key_alias:, limit: nil) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/activerecord/has_some_of_many/associations.rb', line 30 def self.build_scope(klass, relation, primary_key:, foreign_key:, foreign_key_alias:, limit: nil) lateral_table = Arel::Table.new('lateral_table') subselect = klass.unscope(:select, :joins, :where, :order, :limit) .select(klass.arel_table[primary_key].as(foreign_key_alias), lateral_table[Arel.star]) .arel.join( relation .then { |query| relation.table.name == klass.arel_table.name ? ActiveRecord::HasSomeOfMany::RelationRewriter.new(query).alias_table("#{klass.table_name}__alias") : query } .then { |query| query.where(query.table[foreign_key].eq(klass.arel_table[primary_key])) } .then { |query| limit ? query.limit(limit) : query } .arel.lateral(lateral_table.name) ).on("TRUE") select_values = if relation.klass.ignored_columns.any? [relation.klass.arel_table[foreign_key_alias]] + relation.klass.columns.map { |column| relation.klass.arel_table[column.name] } else [relation.klass.arel_table[Arel.star]] end relation.klass.select(select_values).from(subselect.as(relation.arel_table.name)) end |