在大多数情况下,我无疑是一个真正的新手,包括形成和解析参数哈希。我正在尝试从投票应用程序的表单中获取相同模型实例的哈希值。用户可以根据排名为任意数量的候选人投票。
Myvotes#new
确实使用和正确设置创建Candidate.count
了 Vote 实例。我知道这一点,因为表格正在为每个候选人正确地迭代。user_id
rank
@user.votes
这是呈现形式的片段:
<input id="vote_rank" name="vote[rank]" type="hidden" value="1" />
<label for="vote_Candidate">Candidate</label>
<select id="vote_candidate_id" name="vote[candidate_id]"><option value=""></option>
<option value="1">Smithers</option>
<option value="2">Mr. Burns</option>
<option value="3">Bart</option>
<option value="4">Lionel Hutz</option>
<option value="5">Jimbo</option>
<option value="6">Troy McClure</option>
<option value="7">Duffman</option>
<option value="8">Maggie</option>
<option value="9">Moe</option>
<option value="10">Principal Skinner</option>
<option value="11">Apu Nahasapeemapetilan</option></select>
我不知道如何将集合从表单恢复到我的votes#create
. 我能够使用一组candidate_id
和rank
值(最后一个)获得一个参数哈希,但并不是我一开始就卡在其中的所有 11 个实例。表单想要放弃正确的数据。
@user.votes.create(vote_params)
invotes#create
抛出此错误:undefined method `stringify_keys' for "rank":String
这是我的控制器方法和表单。
def new
@user = current_user
@votes = Candidate.count.times { |i| @user.votes.build(:rank => i + 1) }
end
def create
@user = current_user
#params[:user][:votes].each do |vote_params|
#@user.votes.create(vote_params)
params[:vote].each do |vote_params|
@user.votes.create(vote_params)
end
respond_to do |format|
if @user.valid?
format.html { redirect_to @user, notice: 'votes were successfully created.' }
else
format.html { render action: "new" }
end
end
end
<%= form_for :votes, :url => votes_path do |f| %>
<% @user.votes.each do |v| %>
<%= fields_for v do |vote_fields| %>
<%= vote_fields.hidden_field :rank %>
<%= vote_fields.label "Candidate" %>
<%= vote_fields.collection_select :candidate_id, Candidate.all, :id, :name, :include_blank => true %>
<% end %>
<% end %>
<p><%= f.submit :class => 'medium radius button' %></p>
<% end %>
这是相关的HTML
只有一组值被传递:
{"utf8"=>"✓", "authenticity_token"=>"bVLXCQtOffEtu5xBNI0e94o9j9mJ8alHhuBhDkkfaRA=", "vote"=>{"rank"=>"11", "candidate_id"=>""}, "commit"=>"Save Votes", "action"=>"create", "controller"=>"votes"}
尽管表单试图放弃正确的值:
vote[rank]:1
vote[candidate_id]:2
vote[rank]:2
vote[candidate_id]:4
vote[rank]:3
vote[candidate_id]:2
vote[rank]:4
vote[candidate_id]:9
etc. (up to 11!)
任何帮助表示赞赏。
更新:
解决了它。我提出这个以防万一它对某人有帮助,因为我没有直接找到任何东西,而且我花了很长时间才解决这个问题。
我的表单正在创建名称相同的对象,这些对象只是被覆盖了。解释了为什么我只能将最后一组值输入数据库。
我的表单现在遍历传递的对象,votes#new
并在名称中包含投票的排名。
<%= form_for :vote, :url => votes_path do |f| %>
<% @user.votes.each do |v| %>
<% if v.errors.any? %>
<h1>errors</h1>
<% end %>
<%= f.fields_for "#{v.rank}" do |builder| %>
<%= builder.hidden_field :rank, :value => v.rank %>
<div class="row">
<div class="one columns"><%= builder.label "Rank #{v.rank}", :class => "left inline" %></div>
<div class="eleven columns"><%= builder.collection_select :candidate_id, Candidate.all, :id, :name, {:include_blank => true}, :class => "two" %></div>
</div>
<% end %>
<% end %>
<%= f.submit "Submit", :confirm => "Please review your ballot and confirm that your votes are correct before submitting. This message will appear as a reminder each time you press 'Submit', even if you've edited your ballot.", :class => "small round button" %>
<% end %>
这会产生一个params[:vote]
唯一命名的哈希值,例如
{"1"=>{"rank"=>"1", "candidate_id"=>"5"}, "2"=>{"rank"=>"2", "candidate_id"=>"2"}, "3"=>{"rank"=>"3", "candidate_id"=>"7"}, "4"=>{"rank"=>"4", "candidate_id"=>"4"}, "5"=>{"rank"=>"5", "candidate_id"=>"10"}, "6"=>{"rank"=>"6", "candidate_id"=>""}, "7"=>{"rank"=>"7", "candidate_id"=>""}, "8"=>{"rank"=>"8", "candidate_id"=>""}, "9"=>{"rank"=>"9", "candidate_id"=>""}, "10"=>{"rank"=>"10", "candidate_id"=>""}, "11"=>{"rank"=>"11", "candidate_id"=>""}}
我的votes#create
方法将由参数散列中的键/值对组成的数组转储到@user.votes.create(my_array)
def create
@user = current_user
@user.votes.create(sanitize_and_compress_vote_array params[:vote])
redirect_to thankyou_path
end
然后下一个挑战是让验证错误消息正常工作。这超出了我的想象,因为我要验证的是一个键值对数组,在任何值进入数据库之前,其candidate_id
作用域的唯一性。user_id
看起来 Rails 并没有让这变得容易。
validates :candidate_id, :presence => true, :uniqueness => {:scope => :user_id, :message => "You may only vote for a candidate once."}
验证可以很好地拒绝重复值,但它没有用,因为那些已经通过的值显然已经在数据库中了。我还没有发现如何在保存之前验证集合成员对自己的验证,我觉得我在自言自语:-(