3

我正在使用一个实现belongs_to数据库中两个条目之间关联的库。由于这不是我需要的行为,我想通过prepend. 但是 pry 告诉我原来的方法仍然被调用。我仔细检查了一下,我使用的是 ruby​​ 2.0。

预先添加的代码:

module Associations
  module ClassMethods

    [...]
    #Add the attributeName to the belongsToAttributes
    #and add a field in the list for the IDs
    def belongs_to(attr_name)
      @belongsToAttributes ||= []
      @belongstoAttributes << attr_name

      create_attr attr_name.to_s
      attribute belongs_to_string.concat(attr_name.to_s).to_sym
    end

    def belongsToAttributes
      @belongsToAttributes
    end    
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

# prepend the extension 
Couchbase::Model.send(:prepend, Associations)

我在这个类中使用它:

注意:我也尝试直接覆盖这个类中的方法,但仍然没有发生

require 'couchbase/model'

class AdServeModel < Couchbase::Model

[...]
  #I tried to add the belongs_to method like this
  #def belongs_to(attr_name)
  #   @belongsToAttributes ||= []
  #   @belongstoAttributes << attr_name

  #   create_attr attr_name.to_s
  #    attribute belongs_to_string.concat(attr_name.to_s).to_sym
  #  end

  #  def belongsToAttributes
  #    @belongsToAttributes
  #  end
end

当我用 pry 检查时,它告诉我我最终进入了这个方法调用:

def self.belongs_to(name, options = {})
  ref = "#{name}_id"
  attribute(ref)
  assoc = name.to_s.camelize.constantize
  define_method(name) do
    assoc.find(self.send(ref))
  end
end

任何指向我做错了什么的指针都将不胜感激。

编辑: 好的,我解决了这样的问题:

 self.prepended(base)
    class << base
      prepend ClassMethods
    end
  end

end
# prepend the extension 
Couchbase::Model.send(:prepend, Associations)

由于Arie Shaw的帖子包含解决此问题的重要指示,我将接受他的回答。尽管他错过了关于扩展和预先设置我要调用的方法的要点。有关我在添加方法时遇到的麻烦的更详细讨论,请参阅问题。

4

1 回答 1

1

根据您发布的撬动跟踪,您想要猴子补丁的方法是类方法AdServeModel,而不是实例方法。

  • 您的Associations模块方法的问题是,您正在调用现有类的模块,但是,您编写了一个Module#prepend钩子方法,该方法仅在包含模块时才被调用(而不是前置)。你应该写钩子。prependself.includedModule#prepended

  • 直接覆盖方法的问题是,您实际上是在覆盖实例方法,而不是类方法。它应该是这样的:

require 'couchbase/model'

class AdServeModel < Couchbase::Model
  class << self
    # save the original method for future use, if necessary
    alias_method :orig_belongs_to, :belongs_to

    def belongs_to(attr_name)
      @belongsToAttributes ||= []
      @belongstoAttributes << attr_name

      create_attr attr_name.to_s
      attribute belongs_to_string.concat(attr_name.to_s).to_sym
    end

    def belongsToAttributes
      @belongsToAttributes
    end
  end
end
于 2013-09-08T12:27:42.757 回答