如何同时更新Rails中的两个模型?

时间:2011-12-31 05:40:21

标签: ruby-on-rails forms models matching

假设我有一个与两个人相互匹配的应用程序,有点像“热门与否”。

我的比赛视图将随机用户拉出数据库并将它们相互匹配。当用户为其中一个人投票时,我希望将:wins:matches_played增加1,但我还想将失败者:matches_played增加1,以便我可以计算排名

是否有办法为每个人使用表单来完成此操作,或者我需要一个模型介于两者之间,比如匹配,其中有两列用于赢家和输家,如果是,那么这将如何工作。

2 个答案:

答案 0 :(得分:3)

仅使用模式(“简单”方式)执行此操作:

  • Pro's:很容易
  • Con's:人们很容易通过使用Firebug或Chrome的检测工具伪造表单参数来夸大他们的“胜利”

假设你有这些路线:

new_person  GET     /people/new(.:format)        {:action=>"new", :controller=>"people"}
edit_person GET     /people/:id/edit(.:format)   {:action=>"edit", :controller=>"people"}
person      GET     /people/:id(.:format)        {:action=>"show", :controller=>"people"}
            PUT     /people/:id(.:format)        {:action=>"update", :controller=>"people"}
            DELETE  /people/:id(.:format)        {:action=>"destroy", :controller=>"people"}

HAML版本的视图代码:

- # Person A form
= form_tag(person_path(@personA, :loser_id => @personB), :method => :put) do
  = submit_tag "Vote for Person A"

- # Person B form
= form_tag(person_path(@personB, :loser_id => @personA), :method => :put) do
  = submit_tag "Vote for Person B"

ERB版本:

<%# Person A form %>
<% form_tag(person_path(@personA, :loser_id => @personB), :method => :put) do %>
  <%= submit_tag "Vote for Person A" %>
<% end %>

<%# Person B form %>
<% form_tag(person_path(@personB, :loser_id => @personA), :method => :put) do %>
  <%= submit_tag "Vote for Person B" %>
<% end %>

然后在您的控制器中执行update操作:

def update
  People.transaction do
    winner = People.find(params[:id])
    loser = People.find(params[:loser_id])

    # Increment the winner
    winner.increment! :matches_played
    winner.increment! :wins

    # Increment the loser
    loser.increment! :matches_played
  end

  respond_to do |format|
    format.html { redirect_to new_match_path }
  end
end

正如有人在评论中指出的那样,您应该将其包含在所谓的transaction中,这样只有当事务中的所有内容都成功保存时,它才会永久保存在数据库中。


即使我向您展示了上述方法,我仍然建议使用Match模型。最终,使用这个额外的模型将帮助您验证以下内容,以便人们无法对您的系统进行游戏。

  • 用户每场比赛只能投票一次
  • 用户不能对涉及他们的比赛进行投票
  • 用户不能伪造表格来夸大他们的胜利
  • 就模型而言,单独关注并保持数据更有条理,更清晰,以便进行分析

是的,这一切都需要更多的工作(这就是为什么我没有为它显示代码),但如果你担心上述任何一个,那么你可能想要这样做。

答案 1 :(得分:0)

您应该编写表单提交,将两个用户ID提交给您的控制器,并指示获胜用户。然后你可以对它们进行操作并将它们保存到db。

winner = People.find(params[:winner_id])
loser  = People.find(params[:loser_id])
winner.matches_played += 1
winner.wins += 1
loser.matches_played += 1
winner.save!
loser.save!