我如何在Rails模型中为STI列选择输入?

时间:2010-06-14 23:32:37

标签: ruby-on-rails forms single-table-inheritance

我在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))

我读a suggestion使用字段#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

都没有奏效。有什么建议?奇怪的是,它在我的机器上工作正常(RVM上的MRI 1.8.6),但在登台服务器上失败(MRI 1.8.7不在RVM上)。

3 个答案:

答案 0 :(得分:1)

ryan bates的“建议”(谁比大多数人更了解铁路)和你的实现之间的关键区别是建议使用通过括号直接访问属性(“self [:type] =”)与你的使用方法调用的实现(“self.type =”)

所以尝试类似:

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

答案 1 :(得分:0)

您还可以尝试将与STI一起使用的列名更改为与type不同的内容。

根据railsapi.com,它可以在子类中设置,因此只需在pet模型中添加以下内容:

self.inheritance_column = "type_id"

我只是在猜...所以我很抱歉这是完全错误的。

答案 2 :(得分:0)

如果您必须这样做,我会在您的控制器中执行以下操作:

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

IMO,你最好不要在尝试这样做时明确而痛苦,因为在飞行中改变类型就像是一个非常糟糕的想法。