ActiveRecord building for nested resource
(NOTE: Source code here https://github.com/cthielen/dss-evote)
I've got a simple voting application. A survey is the set of questions to vote on, a ballot is a per-user instance of their preferences, and the ballot has_many preferences, which again, are unique to each user. Here's the modeling:
class Ballot < ActiveRecord::Base
belongs_to :survey
has_many :preferences
end
class Survey < ActiveRecord::Base
has_many :questions
has_many :eligibilities
has_many :ballots
accepts_nested_attributes_for :questions, :allow_destroy => true
attr_accessible :title, :description, :status, :deadline, :questions_attributes
def owner
Person.find(owner_id)
end
end
class Question < ActiveRecord::Base
belongs_to :survey
has_many :preferences
end
class Preference < ActiveRecord::Base
belongs_to :ballot
belongs_to :question
end
routes.rb only has this: resources :surveys do resources :ballots end
/surveys/1 seems to work, even /surveys/1/ballots. /surveys/1/ballots/开发者_JAVA百科new is where I run into issues:
in ballots_controller.rb:
def new
@survey = Survey.find(params[:survey_id])
@ballot = @survey.ballots.build
@survey.questions.count.times { @ballot.preferences.build }
respond_to do |format|
format.html # new.html.erb
end
end
(corresponding view)
<%= form_for [@survey, @ballot] do |f| %>
<%= f.fields_for @ballot.preferences do |preferences_fields| %>
<% for question in @preferences_fields %>
<p>
<%= f.label question.question %>
<%= radio_button(question.id, "preference", "Yes") %> Yes
<%= radio_button(question.id, "preference", "No") %> No
<%= radio_button(question.id, "preference", "Decline") %> Decline
</p>
<% end %>
<% end %>
<div class="actions">
<%= f.submit "Vote" %>
</div>
<% end %>
Results in the error:
NoMethodError in Ballots#new
Showing /Users/cthielen/Projects/Work/dss-evote/app/views/ballots/_form.html.erb where line #2 raised:
undefined method `model_name' for Array:Class
Extracted source (around line #2):
1: <%= form_for [@survey, @ballot] do |f| %>
2: <% f.fields_for @ballot.preferences do |preferences_fields| %>
3: <% for question in @preferences_fields %>
4: <p>
5: <%= f.label question.question %>
Now, it appears an array is being formed instead of proper instances of the class, but I'm at a loss for how to properly fix this.
EDIT: I should mention the reason I'm attempting to build @ballot.preferences are that the preferences represent a person's answer, and the length of preferences may change from survey to survey. So if a survey has six questions, @ballot.survey.questions.length will be 6, and I need to create 6 blank @ballot.preferences, which will then be represented by form_for and hopefully saved properly using a RESTful Create.
Thanks in advance for any help you can offer!
Ok, this is due to this line:
@ballot.preferences = @survey.questions.map{|question| question.preferences.build}
Because the mapping creates an Array which could not be used by the form_helper
(expecting a Model name generally provided by an ActiveRecord Relation).
You should stick to something like:
@survey.questions.count.times { @ballot.preferences.build }
Sidenote:
<% fields_for @ballot.preferences do |preferences_fields| %>
should be:
<%= f.fields_for :preferences do |preferences_field| %>
精彩评论