重写方法仍然被调用

时间:2013-09-08 10:04:05

标签: ruby-on-rails ruby couchbase ruby-2.0

我正在使用一个在数据库中的两个条目之间实现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检查时,它显示我最终进入this方法调用:

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 的帖子包含解决此问题的重要指示,我将接受他的回答。虽然他错过了关于扩展和预先设置我想要调用的方法的观点。有关我在预先设置方法时遇到问题的更详细讨论,请参阅this问题。

1 个答案:

答案 0 :(得分:1)

根据您发布的pry trace,您想要修补的方法是AdServeModel的类方法,而不是实例方法。

  • Associations模块方法的问题是,您正在向现有类调用Module#prependprepend模块,但是,您编写了self.included hook方法,只有在包含模块时才会被调用(不是前置)。你应该写Module#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