我可以修补使用define_method定义的方法

时间:2014-09-30 22:50:03

标签: ruby-on-rails ruby activerecord associations monkeypatching

我试图修复updatng记录失败的情况,因为关联集合的id被强制为整数,而id是uuids(uuid上的to_i返回第一个数字部分)。 下面的代码片段显示了我尝试过的猴子补丁(coment#.map(&:to_i))。尽管已加载补丁,但仍会访问原始方法。

在ActiveRecord模块中进行更改对我有用,但我更喜欢一个补丁而不是冻结rails代码。

我会感激任何我缺少的暗示。

<!-- language: ruby -->

module ActiveRecord
  module Associations
    module ClassMethods
      private
            def collection_accessor_methods(reflection, association_proxy_class, writer = true)
              collection_reader_method(reflection, association_proxy_class)

              if writer
                define_method("#{reflection.name}=") do |new_value|
                  # Loads proxy class instance (defined in collection_reader_method) if not already loaded
                  association = send(reflection.name)
                  association.replace(new_value)
                  association
                end

                define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value|
                  ids = (new_value || []).reject { |nid| nid.blank? } #.map(&:to_i)
                  send("#{reflection.name}=", reflection.klass.find(ids).index_by(&:id).values_at(*ids))
                end
              end
            end

错误信息是例如。

“找不到ID = 281的PosperCategory”

根本原因是'218'是原始UUID的'.map(&amp;:to_i')。我需要使用UUID,因为rails app和Java app使用相同的遗留数据库。 这在rails 2.2.2中工作,在2.3.2中停止工作,在2.3.3(我认为)中再次工作并且再次停止工作。我现在在2.3.18。由于这里不应讨论的原因,升级到rails 3.x不是我的选择。

1 个答案:

答案 0 :(得分:0)

是的,可以在mokey修补中定义动态方法

例如

class Object
  def methods(*names)
    names.each do |name|
      define_method("#{name}=") do |value, &b|
        puts "setter"
        puts __method__
      end

      define_method("#{name}") do
        puts "getter"
        puts __method__
      end
    end
  end
end

module Module
  def n_attrib_keys(*names)
    Object.methods(*names)
  end
end

在您的班级中加入模块