2009-10-21 2 views
4

Im пытается установить тип модели наследования одной таблицы в форме. Поэтому у меня есть меню выбора для атрибута: type, а значения - это имена подклассов STI. Проблема журнал ошибок продолжает печать:Rails attr_accessible не работает для: type?

ВНИМАНИЕ: Не удается массово назначать эти защищенные атрибуты: тип

Так я добавил «attr_accessible: тип» модели:

class ContentItem < ActiveRecord::Base 
    # needed so we can set/update :type in mass 
    attr_accessible :position, :description, :type, :url, :youtube_id, :start_time, :end_time 
    validates_presence_of :position 
    belongs_to :chapter 
    has_many :user_content_items 
end 

Ничего не меняет, ContentItem все еще имеет: type = nil после вызова .update_attributes() в контроллере. Любая идея, как массовое обновление: type из формы?

ответ

6

Дуплекс в railsforum.com нашел обходной путь:

использовать виртуальный атрибут в формах и в модели вместо типа dirtectly:

def type_helper 
    self.type 
end 
def type_helper=(type) 
    self.type = type 
end 

Работали как очарование.

+0

Awesome! Именно то, что мне нужно. – jspooner

9

Вы должны использовать правильный конструктор на основе подкласса, который хотите создать, вместо вызова конструктора суперкласса и назначения типа вручную. Пусть ActiveRecord сделать это для вас:

# in controller 
def create 
    # assuming your select has a name of 'content_item_type' 
    params[:content_item_type].constantize.new(params[:content_item]) 
end 

Это дает вам преимущество определения различному поведения в ваших подклассах инициализация() метода или обратных вызовов. Если вам не нужны эти преимущества или вы планируете часто менять класс объекта, вам может потребоваться пересмотреть использование наследования и просто придерживаться атрибута.

1

Я следовал за http://coderrr.wordpress.com/2008/04/22/building-the-right-class-with-sti-in-rails/ для решения той же проблемы, что и у меня. Я довольно новичок в мире Rails, поэтому не уверен, что этот подход хорош или плох, но он работает очень хорошо. Я скопировал код ниже.

class GenericClass < ActiveRecord::Base 
    class << self 
    def new_with_cast(*a, &b) 
     if (h = a.first).is_a? Hash and (type = h[:type] || h['type']) and (klass = type.constantize) != self 
     raise "wtF hax!!" unless klass < self # klass should be a descendant of us 
     return klass.new(*a, &b) 
    end 
    new_without_cast(*a, &b) 
    end 
    alias_method_chain :new, :cast 
end 

class X < GenericClass; end 
GenericClass.new(:type => 'X') # => #<X:0xb79e89d4 @attrs={:type=>"X"}> 
20

мы можем переопределить attributes_protected_by_default

class Example < ActiveRecord::Base 

    def self.attributes_protected_by_default 
    # default is ["id","type"] 
    ["id"] 
    end 
end 

e = Example.new(:type=>"my_type") 
Смежные вопросы