4

我正在构建一个 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

属于_to源代码

==================================================== ============================ 更新

流动的delwyns 回答我试图重新审视我的代码,他是对的,它应该包含在内,但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 完全忽略了我的方法覆盖

所以是的,我可以定义我自己的选项,但是他们什么都不做:(有什么建议吗?

4

2 回答 2

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 => ...和(真正或有效的)调用belongs_to

于 2013-09-05T18:36:18.497 回答
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 

希望有帮助。

于 2013-08-21T16:16:41.230 回答