我正在构建一个gem,我希望它的部分功能扩展ActiveRecord::Associations::Builder::BelongsTo
,但我无法弄清楚如何做到这一点
所以基本上用户应该能够指定:
class Event < ActiveRecord::Base
belongs_to :users, foo: true
end
谁知道怎么做?
这不起作用:
module Mygem
module BelongsToFoo
def valid_options
super + [:foo]
end
#... other functionality
end
end
class ActiveRecord::Associations::Builder::BelongsTo
extend MyGem::BelongsToFoo
end
控制台
ActiveRecord::Associations::Builder::BelongsTo.valid_options.include? :foo
#=> false ... :(
Event
ArgumentError: Unknown key: foo
=============================================== ============================== 的更新
流动delwyns answer我试图再次查看我的代码,他说对了,但是ActiveRecord::Associations::Builder::BelongsTo
也有变量valid_options
。
所以我可以做到
ActiveRecord::Associations::Builder::BelongsTo.new(:a, :b, :c).valid_options.include? :foo
# => true
但也
ActiveRecord::Associations::Builder::BelongsTo.valid_options.include? :foo
# => true
所以它应该看起来像这样
module MyGem
module BelongsToFoo
extend ActiveSupport::Concern
included do
self.valid_options += [:foo]
end
def valid_options
super + [:foo]
end
def define_callbacks(model, reflection)
# this wont get executed
add_foo_callbacks(model, reflection)# if options[:foo]
super
end
def add_foo_callbacks(model, reflection)
# therefore this wont either
end
end
end
即使我试试这个
module MyGem
module BelongsToFoo
def define_callbacks(model, reflection)
raise "dobugging"
end
end
end
什么都不会发生,Rails完全忽略我的方法覆盖
所以是的,我可以定义自己的选项,但是他们什么都不做:(任何建议?
答案 0 :(得分:4)
有一种用于扩展关联代理的内置方法,请参阅http://guides.rubyonrails.org/association_basics.html#association-extensions
class Event < ActiveRecord::Base
belongs_to :users, :extend => MyGem::SpecialTouch
end
module MyGem
module SpecialTouch
def touch
# do the magic
end
end
end
然后您当然可以覆盖或别名链belongs_to
,以便它从选项哈希中弹出:foo
选项,将其转换为正确的:extend => ...
和(实际或有效)调用{{ 1}}。
答案 1 :(得分:2)
valid_options是一种实例方法,因此您需要使用include而不是extend。
module MyGem
def valid_options
super + [:foo]
end
end
class ActiveRecord::Associations::Builder::BelongsTo
include ::MyGem
end
relation = ActiveRecord::Associations::Builder::BelongsTo.new(:a, :b, :c)
relation.valid_options.include? :foo
#=> true
希望有所帮助。