2

在大多数情况下,我无疑是一个真正的新手,包括形成和解析参数哈希。我正在尝试从投票应用程序的表单中获取相同模型实例的哈希值。用户可以根据排名为任意数量的候选人投票。

Myvotes#new确实使用和正确设置创建Candidate.count了 Vote 实例。我知道这一点,因为表格正在为每个候选人正确地迭代。user_idrank@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_idrank值(最后一个)获得一个参数哈希,但并不是我一开始就卡在其中的所有 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."}

验证可以很好地拒绝重复值,但它没有用,因为那些已经通过的值显然已经在数据库中了。我还没有发现如何在保存之前验证集合成员对自己的验证,我觉得我在自言自语:-(

4

0 回答 0