How do I so a select input for a STI column in a Rails model?
I have a model with single-table inheritance on the type
column:
class Pet < ActiveRecord::Base
TYPES = [Dog, Cat, Hamster]
validates_presence_of :name
end
I want to offer a <select>
dropdown on the new and edit pages:
<% 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 %>
That gives me the following error:
ActionView::TemplateError (wrong argument type String (expected Module))
I read a suggestion to use an alias for the field #type
since Ruby considers that a reserved word that's the same as #class
. I tried both
class Pet < ActiveRecord::Base
...
alias_attribute :klass, :type
end
and
class Pet < ActiveRecord::Base
...
def klass
self.type
end
def klass=(k)
self.type = k
end
end
Neither worked. Any suggestions? Oddly, it works fine on my machine (MRI 1.8.6 on RVM), but fails on the stag开发者_如何学JAVAing server (MRI 1.8.7 not on RVM).
The key difference between ryan bates' "suggestion" (who knows more about rails than most) and your implementation is the suggestion used the direct access to the attributes via the brackets ("self[:type] = ") versus your implement that uses method calling ("self.type = ")
So try something like:
class Pet < ActiveRecord::Base
...
def klass
self[:type]
end
def klass=(k)
self[:type] = k
end
end
You could also try to change the column name used with STI for something different from type
.
According to railsapi.com
, it can be set in subclasses, so just add the following in your pet
model:
self.inheritance_column = "type_id"
I'm just guessing... so I'm sorry this is totally wrong.
If you absolutely have to do this, I'd do something along the lines of this in your controller:
@pet = Pet.new(params[:pet])
@pet[:type] = params[:pet][:type]
IMO, you're better off being both explicit and painful when trying to do this, as changing types on the fly like that feels like a really bad idea.
精彩评论