2013-07-03 42 views
2
module HasUrl 
    extend ActiveSupport::Concern 

    included do 
    attr_accessor :bar 
    end 

    def bar 
    0 
    end 
end 

class Foo < ActiveRecord::Base 
    include HasUrl 
end 

bar屬性未存儲在數據庫中,但在表單中使用它(使用SimpleForm的f.input)。我想重寫此方法的getter,因此我可以根據其他屬性設置bar,並使表單正確預填充該值。如何從模塊重寫attr_accessor getter?

問題是,在這樣的包含塊中使用attr_accessor會在Foo類中設置獲取方。因爲模塊包含在祖先鏈中的Foo之上,所以從不觸及返回0的自定義bar方法。要解決這個

一種方法是

class Foo < ActiveRecord::Base 
    include HasUrl 

    def bar 
    super 
    end 
end 

但我想避免這種額外的步驟。我只是想包括模塊,並讓它只是「工作」。另一種選擇是在我的表單中使用不同的助手(f.input_field等),但是我無法利用SimpleForm的包裝。

Module#prepend也不能解決我的問題,因爲HasUrl也定義了一些其他的東西(特別是ActiveRecord回調函數)。如果我預先安排,這些回調會導致錯誤:

NoMethodError: undefined method `_run_...__find__...__callbacks` 

有沒有辦法解決這個錯誤,以便prepend可以工作?或另一種方式完全做到這一點?

回答

6

您確定要attr_accessorattr_writer不夠嗎?

require 'active_support/all' 

module HasUrl 
    extend ActiveSupport::Concern 

    included do 
    attr_writer :bar 
    end 

    def bar 
    0 
    end 
end 

class Foo 
    include HasUrl 
end 

p Foo.new.bar 

總之,如果你真的想用attr_accessor,這應該工作:

require 'active_support/all' 

module HasUrl 
    extend ActiveSupport::Concern 

    included do 
    attr_accessor :bar 
    define_method :bar do 
     0 
    end 
    end 
end 

class Foo 
    include HasUrl 
end 

p Foo.new.bar 
+0

這是正確的,如果你覆蓋吸氣,然後使用'attr_writer'將足以 – mrcasals

+0

謝謝。我以前用'attr_writer'去過了,但是它造成了我的表單問題。這是因爲我在'attr_accessor'行有兩個屬性,其中一個屬性需要getter。閱讀錯誤信息時我只是很蠢。另外,它似乎像prepend問題已在p195中修復:https://github.com/rails/rails/issues/10899,這樣也可以工作(我在p0上工作)。 –