2013-07-03 2 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 на основе других атрибутов и правильно заполнить форму.Как переопределить gett-attr_accessor из модуля?

Проблема заключается в том, что с помощью attr_accessor в включенном блоке, подобном этому, будет установлен геттер на классе Foo. Поскольку модуль включен выше Foo в цепочке предков, пользовательский метод bar, который возвращает 0, никогда не затрагивается.

Одним из способов решения этой проблемы является

class Foo < ActiveRecord::Base 
    include HasUrl 

    def bar 
    super 
    end 
end 

Но я хочу, чтобы избежать этого дополнительного шага. Я просто хочу включить модуль и заставить его просто «работать». Другой вариант - использовать разные помощники в моей форме (f.input_field и т. Д.), Но тогда я не могу воспользоваться обертками SimpleForm.

Модуль # prepend также не решит мои проблемы, так как HasUrl также определяет некоторые другие вещи (в частности, обратный вызов ActiveRecord). Если я предварять эти обратные вызовы вызывают ошибки:

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

Есть ли способ обойти эту ошибку, так что перед именем может работать? Или другой способ сделать это вообще?

ответ

6

Вы уверены, что хотите attr_accessor? Не хватит ли attr_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. При чтении сообщения об ошибке я просто был глуп. Кроме того, похоже, что проблема с предварительной подпиской была исправлена ​​в p195: https://github.com/rails/rails/issues/10899, так что это будет работать (я работаю на p0). –