Как мне выбрать вход для столбца STI в модели Rails? - PullRequest
1 голос
/ 15 июня 2010

У меня есть модель с наследованием одной таблицы в столбце type:

class Pet < ActiveRecord::Base
  TYPES = [Dog, Cat, Hamster]
  validates_presence_of :name
end

Я хочу предложить выпадающий список <select> на новых и редактируемых страницах:

<% form_for @model do |f| %>
  <%= f.label :name %>
  <%= f.text_input :name %>

  <%= f.label :type %>
  <%= f.select :type, Pet::TYPES.map { |t| [t.human_name, t.to_s] } %>
<% end %>

Это дает мне следующую ошибку:

ActionView::TemplateError (wrong argument type String (expected Module))

Я прочитал предложение использовать псевдоним для поля #type, так как Ruby считает, что зарезервированное слово совпадает с #class. Я пробовал оба

class Pet < ActiveRecord::Base
  ...
  alias_attribute :klass, :type
end

и

class Pet < ActiveRecord::Base
  ...
  def klass
    self.type
  end
  def klass=(k)
    self.type = k
  end
end

Ни сработало. Какие-либо предложения? Как ни странно, он отлично работает на моей машине (MRI 1.8.6 на RVM), но не работает на промежуточном сервере (MRI 1.8.7 не на RVM).

Ответы [ 3 ]

1 голос
/ 15 июня 2010

Ключевое различие между «предложением» Райана Бейтса (который знает о рельсах больше, чем большинство) и вашей реализацией заключается в предложении использовать прямой доступ к атрибутам через скобки («self [: type] =») по сравнению с вашимреализовать, который использует вызов метода ("self.type =")

Так что попробуйте что-то вроде:

class Pet < ActiveRecord::Base
  ...
  def klass
    self[:type]
  end
  def klass=(k)
    self[:type] = k
  end
end
0 голосов
/ 15 июня 2010

Если вам абсолютно необходимо сделать это, я бы сделал что-то вроде этого в вашем контроллере:

@pet = Pet.new(params[:pet])
@pet[:type] = params[:pet][:type]

IMO, вам лучше быть и явным, и болезненным, когда пытаетесьэто так, как смена типов на лету, как будто это действительно плохая идея.

0 голосов
/ 15 июня 2010

Вы также можете попробовать изменить имя столбца, используемое с STI, на что-то отличное от type.

В соответствии с railsapi.com, его можно установить в подклассах, так что простодобавьте следующее в вашу pet модель:

self.inheritance_column = "type_id"

Я просто догадываюсь ... так что извините, это совершенно неправильно.

...