首页 > 解决方案 > 此代码中引用的模型关联行的 3.1 版本在哪里

问题描述

好的...所以,我继承了我最近升级到 Rails 3.1 的旧 Rails 2.3.14 应用程序(是的,我知道 6.x 是最新的,但首先是婴儿步骤。)

我在原始代码库中发现了一些看起来像是已经完成的元编程。三个类已被覆盖。只有最后一个...class AssociationReflection可以在 Rails 3.1 Activerecord 中引用。另外两个已经被重构为其他东西,在 Rails 3.1 Activerecord 的其他地方。

仅供参考:此代码中发生的情况是 alias_method 被用于允许使用这些修改后的副本覆盖原始代码。

...我已经标记了从原始更改的每一行,##ORIGINALY:总共大约有 7 行,其中 6 行我需要重构。

rails_fix.rb

# NOTE: 
# This makes brittle code. the instant the original methods aliased here no
# longer exist on the rails 3.1 activeRecord side..this code will break..and 
# the app will break. Which is why the new programmer(me) has to fix it.
# This instantly coupled the code to a specific version of rails.
#
# NOTE: this is meta programming ... see SO post
# https://stackoverflow.com/questions/3695839/ruby-on-rails-alias-method-chain-what-exactly-does-it-do

module ActiveRecord
  module Associations
    module ClassMethods
      class JoinDependency
        class JoinAssociation
          def association_join_with_fix
            connection = reflection.active_record.connection
            join = case reflection.macro
                   when :has_and_belongs_to_many
                     " #{join_type} %s ON %s.%s = %s.%s " % [
                       table_alias_for(options[:join_table], aliased_join_table_name),
                       connection.quote_table_name(aliased_join_table_name),
                       options[:foreign_key] || reflection.active_record.to_s.foreign_key,
                       connection.quote_table_name(parent.aliased_table_name),
                       reflection.active_record.primary_key] +
                       " #{join_type} %s ON %s.%s = %s.%s " % [
                         table_name_and_alias,
                         connection.quote_table_name(aliased_table_name),
                         klass.primary_key,
                         connection.quote_table_name(aliased_join_table_name),
                         options[:association_foreign_key] || klass.to_s.foreign_key
                       ]
                   when :has_many, :has_one
                     case
                     when reflection.options[:through]
                       through_conditions = through_reflection.options[:conditions] ? "AND #{interpolate_sql(sanitize_sql(through_reflection.options[:conditions]))}" : ''

                       jt_foreign_key = jt_as_extra = jt_source_extra = jt_sti_extra = nil
                       first_key = second_key = as_extra = nil

                       if through_reflection.options[:as] # has_many :through against a polymorphic join
                         jt_foreign_key = through_reflection.options[:as].to_s + '_id'
                         jt_as_extra = " AND %s.%s = %s" % [
                           connection.quote_table_name(aliased_join_table_name),
                           connection.quote_column_name(through_reflection.options[:as].to_s + '_type'),
                           klass.quote_value(parent.active_record.base_class.name)
                         ]
                       else
                         jt_foreign_key = through_reflection.primary_key_name
                       end

                       case source_reflection.macro
                       when :has_many
                         if source_reflection.options[:as]
                           first_key = "#{source_reflection.options[:as]}_id"
                           second_key = options[:foreign_key] || primary_key
                           as_extra = " AND %s.%s = %s" % [
                             connection.quote_table_name(aliased_table_name),
                             connection.quote_column_name("#{source_reflection.options[:as]}_type"),
                             klass.quote_value(source_reflection.active_record.base_class.name)
                           ]
                         else
                           first_key = source_reflection.association_foreign_key ##ORIGINALY: through_reflection.klass.base_class.to_s.foreign_key 
                           second_key = source_reflection.primary_key_name ##ORIGINALY: options[:foreign_key] || primary_key
                         end

                         unless through_reflection.klass.descends_from_active_record?
                           jt_sti_extra = " AND %s.%s = %s" % [
                             connection.quote_table_name(aliased_join_table_name),
                             connection.quote_column_name(through_reflection.active_record.inheritance_column),
                             through_reflection.klass.quote_value(through_reflection.klass.sti_name)]
                         end
                       when :belongs_to
                         first_key = primary_key
                         if reflection.options[:source_type]
                           second_key = source_reflection.association_foreign_key
                           jt_source_extra = " AND %s.%s = %s" % [
                             connection.quote_table_name(aliased_join_table_name),
                             connection.quote_column_name(reflection.source_reflection.options[:foreign_type]),
                             klass.quote_value(reflection.options[:source_type])
                           ]
                         else
                           second_key = source_reflection.primary_key_name
                         end
                       end

                       " #{join_type} %s ON (%s.%s = %s.%s%s%s%s) " % [
                         table_alias_for(through_reflection.klass.table_name, aliased_join_table_name),
                         connection.quote_table_name(aliased_join_table_name), ##ORIGINALY: connection.quote_table_name(parent.aliased_table_name),
                         connection.quote_column_name(parent.primary_key),
                         connection.quote_table_name(parent.aliased_table_name),##ORIGINALY: connection.quote_table_name(aliased_join_table_name),
                         connection.quote_column_name(jt_foreign_key),
                         jt_as_extra, jt_source_extra, jt_sti_extra
                       ] +
                         " #{join_type} %s ON (%s.%s = %s.%s%s) " % [
                           table_name_and_alias,
                           connection.quote_table_name(aliased_table_name),
                           connection.quote_column_name(first_key),
                           connection.quote_table_name(aliased_join_table_name),
                           connection.quote_column_name(second_key),
                           as_extra
                         ]

                     when reflection.options[:as] && [:has_many, :has_one].include?(reflection.macro)
                       " #{join_type} %s ON %s.%s = %s.%s AND %s.%s = %s" % [
                         table_name_and_alias,
                         connection.quote_table_name(aliased_table_name),
                         "#{reflection.options[:as]}_id",
                         connection.quote_table_name(parent.aliased_table_name),
                         parent.primary_key,
                         connection.quote_table_name(aliased_table_name),
                         "#{reflection.options[:as]}_type",
                         klass.quote_value(parent.active_record.base_class.name)
                       ]
                     else
                       foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key
                       " #{join_type} %s ON %s.%s = %s.%s " % [
                         table_name_and_alias,
                         aliased_table_name,
                         foreign_key,
                         parent.aliased_table_name,
                         reflection.options[:primary_key] || parent.primary_key
                       ]
                     end
                   when :belongs_to
                     " #{join_type} %s ON %s.%s = %s.%s " % [
                       table_name_and_alias,
                       connection.quote_table_name(aliased_table_name),
                       reflection.klass.primary_key, ##ORIGINALY: reflection.options[:primary_key] || reflection.klass.primary_key,
                       connection.quote_table_name(parent.aliased_table_name),
                       options[:foreign_key] || reflection.primary_key_name
                     ]
                   else
                     ""
                   end || ''
            join << %(AND %s) % [
              klass.send(:type_condition, aliased_table_name)] unless klass.descends_from_active_record?

            [through_reflection, reflection].each do |ref|
              join << "AND #{interpolate_sql(sanitize_sql(ref.options[:conditions], aliased_table_name))} " if ref && ref.options[:conditions]
            end

            join
          end

          alias_method_chain :association_join, :fix
        end
      end
    end
  end
end

module ActiveRecord
  module Associations
    class HasManyThroughAssociation
      def construct_joins_with_fix(custom_joins = nil)
        polymorphic_join = nil
        if @reflection.source_reflection.macro == :belongs_to
          reflection_primary_key = @reflection.klass.primary_key
          source_primary_key = @reflection.source_reflection.primary_key_name
          if @reflection.options[:source_type]
            polymorphic_join = "AND %s.%s = %s" % [
              @reflection.through_reflection.quoted_table_name, "#{@reflection.source_reflection.options[:foreign_type]}",
              @owner.class.quote_value(@reflection.options[:source_type])
            ]
          end
        else
          reflection_primary_key = @reflection.source_reflection.primary_key_name
          source_primary_key = @reflection.source_reflection.association_foreign_key ##ORIGINALY: @reflection.through_reflection.klass.primary_key
          if @reflection.source_reflection.options[:as]
            polymorphic_join = "AND %s.%s = %s" % [
              @reflection.quoted_table_name, "#{@reflection.source_reflection.options[:as]}_type",
              @owner.class.quote_value(@reflection.through_reflection.klass.name)
            ]
          end
        end

        "INNER JOIN %s ON %s.%s = %s.%s %s #{@reflection.options[:joins]} #{custom_joins}" % [
          @reflection.through_reflection.quoted_table_name,
          @reflection.quoted_table_name, reflection_primary_key,
          @reflection.through_reflection.quoted_table_name, source_primary_key,
          polymorphic_join
        ]
      end

      alias_method_chain :construct_joins, :fix
    end
  end
end

module ActiveRecord
  module Reflection
    class AssociationReflection
      def association_foreign_key_with_fix
        @association_foreign_key ||= @options[:primary_key] || class_name.foreign_key ##ORIGINALY: @association_foreign_key ||= @options[:association_foreign_key] || class_name.foreign_key
      end

      alias_method_chain :association_foreign_key, :fix
    end
  end
end


注意:这是元编程......请参阅 Ruby on Rails 的 SO 帖子:alias_method_chain,它到底是做什么的?

所以问题是:有什么...

module ActiveRecord
  module Associations
    class HasManyThroughAssociation
      def construct_joins

...和...

module ActiveRecord
  module Associations
    module ClassMethods
      class JoinDependency
        class JoinAssociation
          def association_join

...被重构为标记为 "#ORIGINALY:" 的 6 行的等价物是什么?

我想我可能必须rails_fix.rb使用 Rails 3.1 版本的 ActiveRecord 关联方法构建另一个版本。但我不知道当前代码是什么/在哪里。

我希望这个问题是有道理的。感谢您的时间。

标签: ruby-on-railsrubyactiverecord

解决方案


推荐阅读