From 5821b1fd79eddd3dc8bb7ae919f235963e019442 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sat, 3 Nov 2018 23:26:13 +0900 Subject: [PATCH] Move `resolve_sti_reflections` which is table row related code into `TableRow` --- .../active_record/fixture_set/table_row.rb | 76 +++++++++++++++- .../active_record/fixture_set/table_rows.rb | 91 +------------------ 2 files changed, 78 insertions(+), 89 deletions(-) diff --git a/activerecord/lib/active_record/fixture_set/table_row.rb b/activerecord/lib/active_record/fixture_set/table_row.rb index 5f72c1df38..cb4726f1ee 100644 --- a/activerecord/lib/active_record/fixture_set/table_row.rb +++ b/activerecord/lib/active_record/fixture_set/table_row.rb @@ -3,6 +3,38 @@ module ActiveRecord class FixtureSet class TableRow # :nodoc: + class ReflectionProxy # :nodoc: + def initialize(association) + @association = association + end + + def join_table + @association.join_table + end + + def name + @association.name + end + + def primary_key_type + @association.klass.type_for_attribute(@association.klass.primary_key).type + end + end + + class HasManyThroughProxy < ReflectionProxy # :nodoc: + def rhs_key + @association.foreign_key + end + + def lhs_key + @association.through_reflection.foreign_key + end + + def join_table + @association.through_reflection.table_name + end + end + def initialize(fixture, table_rows:, label:, now:) @table_rows = table_rows @label = label @@ -31,7 +63,7 @@ module ActiveRecord interpolate_label generate_primary_key resolve_enums - @table_rows.resolve_sti_reflections(@row) + resolve_sti_reflections end def reflection_class @@ -74,6 +106,48 @@ module ActiveRecord end end end + + def resolve_sti_reflections + # If STI is used, find the correct subclass for association reflection + reflection_class._reflections.each_value do |association| + case association.macro + when :belongs_to + # Do not replace association name with association foreign key if they are named the same + fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s + + if association.name.to_s != fk_name && value = @row.delete(association.name.to_s) + if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "") + # support polymorphic belongs_to as "label (Type)" + @row[association.foreign_type] = $1 + end + + fk_type = reflection_class.type_for_attribute(fk_name).type + @row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type) + end + when :has_many + if association.options[:through] + add_join_records(HasManyThroughProxy.new(association)) + end + end + end + end + + def add_join_records(association) + # This is the case when the join table has no fixtures file + if (targets = @row.delete(association.name.to_s)) + table_name = association.join_table + column_type = association.primary_key_type + lhs_key = association.lhs_key + rhs_key = association.rhs_key + + targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/) + joins = targets.map do |target| + { lhs_key => @row[model_metadata.primary_key_name], + rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) } + end + @table_rows.tables[table_name].concat(joins) + end + end end end end diff --git a/activerecord/lib/active_record/fixture_set/table_rows.rb b/activerecord/lib/active_record/fixture_set/table_rows.rb index 8a99df29ce..23814b6cb5 100644 --- a/activerecord/lib/active_record/fixture_set/table_rows.rb +++ b/activerecord/lib/active_record/fixture_set/table_rows.rb @@ -6,40 +6,7 @@ require "active_record/fixture_set/model_metadata" module ActiveRecord class FixtureSet class TableRows # :nodoc: - class ReflectionProxy # :nodoc: - def initialize(association) - @association = association - end - - def join_table - @association.join_table - end - - def name - @association.name - end - - def primary_key_type - @association.klass.type_for_attribute(@association.klass.primary_key).type - end - end - - class HasManyThroughProxy < ReflectionProxy # :nodoc: - def rhs_key - @association.foreign_key - end - - def lhs_key - @association.through_reflection.foreign_key - end - - def join_table - @association.through_reflection.table_name - end - end - def initialize(table_name, model_class:, fixtures:, config:) - @table_name = table_name @model_class = model_class # track any join tables we need to insert later @@ -48,10 +15,10 @@ module ActiveRecord # ensure this table is loaded before any HABTM associations @tables[table_name] = nil - build_table_rows_from(fixtures, config) + build_table_rows_from(table_name, fixtures, config) end - attr_reader :table_name, :model_class + attr_reader :tables, :model_class def to_hash @tables.transform_values { |rows| rows.map(&:to_hash) } @@ -61,36 +28,9 @@ module ActiveRecord @model_metadata ||= ModelMetadata.new(model_class) end - def resolve_sti_reflections(row) - # If STI is used, find the correct subclass for association reflection - reflection_class = reflection_class_for(row) - - reflection_class._reflections.each_value do |association| - case association.macro - when :belongs_to - # Do not replace association name with association foreign key if they are named the same - fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s - - if association.name.to_s != fk_name && value = row.delete(association.name.to_s) - if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "") - # support polymorphic belongs_to as "label (Type)" - row[association.foreign_type] = $1 - end - - fk_type = reflection_class.type_for_attribute(fk_name).type - row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type) - end - when :has_many - if association.options[:through] - add_join_records(row, HasManyThroughProxy.new(association)) - end - end - end - end - private - def build_table_rows_from(fixtures, config) + def build_table_rows_from(table_name, fixtures, config) now = config.default_timezone == :utc ? Time.now.utc : Time.now @tables[table_name] = fixtures.map do |label, fixture| @@ -102,31 +42,6 @@ module ActiveRecord ) end end - - def reflection_class_for(row) - if row.include?(model_metadata.inheritance_column_name) - row[model_metadata.inheritance_column_name].constantize rescue model_class - else - model_class - end - end - - def add_join_records(row, association) - # This is the case when the join table has no fixtures file - if (targets = row.delete(association.name.to_s)) - table_name = association.join_table - column_type = association.primary_key_type - lhs_key = association.lhs_key - rhs_key = association.rhs_key - - targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/) - joins = targets.map do |target| - { lhs_key => row[model_metadata.primary_key_name], - rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) } - end - @tables[table_name].concat(joins) - end - end end end end