我在attribute_fu插件中看到以下代码:
module AttributeFu
module Associations #:nodoc:
def self.included(base) #:nodoc:
base.class_eval do
extend ClassMethods
class << self; alias_method_chain :has_many, :association_option; end
class_inheritable_accessor :managed_association_attributes
write_inheritable_attribute :managed_association_attributes, []
after_update :save_managed_associations
end
end
...
end
end
当我尝试更换
时class << self; alias_method_chain :has_many, :association_option; end
使用: alias_method_chain:has_many,:association_option?
我收到以下错误
/usr/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/core_ext/module/aliasing.rb:31:in `alias_method': undefined method `has_many' for class `ActiveRecord::Base' (NameError)
from /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/core_ext/module/aliasing.rb:31:in `alias_method_chain'
from /home/twong/git/physpace/vendor/plugins/attribute_fu/lib/attribute_fu/associations.rb:9:in `included'
我认为这两行会做同样的事情,但看起来我错了。有人可以解释我的错误吗?
答案 0 :(得分:3)
# init.rb
ActiveRecord::Base.class_eval { include AttributeFu::Associations }
module AttributeFu
module Associations
def self.included(base)
# base == ActiveRecord::Base (the class)
base.class_eval do
# class_eval makes self == ActiveRecord::Base, and makes def define instance methods.
extend ClassMethods
# If has_many were an instance method, we could do this
# alias_method_chain :has_many, :association_option; end
# but it's a class method, so we have to do the alias_method_chain on
# the meta-class for ActiveRecord::Base, which is what class << self does.
class << self; alias_method_chain :has_many, :association_option; end
end
end
end
end
另一种解决方法是将其放入IRB:
class A ; end
A.class_eval { puts self.inspect ; class << self ; puts self.inspect ; end }
另见
答案 1 :(得分:0)
在这种情况下,self
并不意味着anObject,它更像是糖结构。
class << self
...
end
定义封闭对象的类方法。方法alias_method_chain
是一种别名的方法。在这种情况下,它将has_many
与has_many_without_association_options
和has_many_with_association_options
与has_many
别名。在您的情况下,它是别名类方法,因此,您必须在类方法范围中使用它。它允许扩展方法没有太多麻烦。
类方法被称为,例如:
SomeThing.bar_method
而实例方法在类的实例上调用:
assoc = SomeThing.new
assoc.foo_method
相应的代码是:
class SomeThing
def foo_method
...
end
class << self
def bar_method
...
end
end
end
在您的情况下,您拥有模块AttributeFu::Associations
。当包含在类Foo中时,它运行Foo.class_eval,它定义了Foo中的一些实例属性,并在类方法范围(alias_method_chain
)内启动方法class << self
。
还有extends ClassMethods
必须定义:
def self.has_many_with_association_options
...
end
或
class << self
def has_many_with_association_options
...
end
end