我在我的rails应用程序中有一个表单,用户只需输入一个数字,然后使用ajax提交表单。如果存在所有参数,则在我的游戏控制器中创建新游戏。我有两个hidden_field_tags,其参数非常好地传递给控制器,但最重要的参数,即从用户输入得到的参数,似乎没有传递给控制器。
我的表格:
<%= form_for @game, :url => {:controller => "games", :action => "create" }, :html => { :role => 'form' }, remote: true, method: :post do |f| %>
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="input-group">
<%= f.text_field :user_stake, class: 'form-control' %>
<span class="input-group-btn">
<%= f.submit 'Go', :html => { :type => "button" }, class: "btn btn-default" %>
</span>
</div>
</div>
</div>
<%= hidden_field_tag 'user_id', current_user.id %>
<%= hidden_field_tag 'jackpot_id', @jackpot.id %>
<% end %>
控制器:
before_action :game_params, only: [:create]
def create
@game = Game.new(game_params)
if @game.save
@jackpot = Jackpot.find(params[:jackpot_id])
ActionCable.server.broadcast 'jackpot_channel',
users: Jackpot.where(id: @jackpot.id),
pot: @jackpot,
user: User.find(@game.user_id),
game: @game,
stake: @game.user_stake.to_s
else
ActionCable.server.broadcast 'jackpot_channel',
error: @game.errors.full_messages
end
end
def new
@game = Game.new
end
private
def game_params
params.permit(:user_stake, :user_id, :jackpot_id)
end
无论@game中输入的是什么,都会以user_stake为0.0保存,我已将其设置为迁移中的默认值。我不知道我在这里做错了什么。有任何想法吗?谢谢!
答案 0 :(得分:2)
您可能需要检查服务器日志,以查看正在发布到控制器的创建方法的内容。我怀疑游戏参数是封装在game
哈希中的。要访问它,我建议将game_params
更改为要求游戏:
def game_params
params.require(:game).permit(:user_stake, :user_id, :jackpot_id)
end
答案 1 :(得分:2)
您未正确嵌套输入:
<%= form_for @game, html: { role: 'form' }, remote: true %>
<%= f.text_field :user_stake, class: 'form-control' %>
<%= hidden_field_tag 'user_id', current_user.id %>
<%= hidden_field_tag 'jackpot_id', @jackpot.id %>
# ..
<% end %>
这将给出以下参数哈希:
{
game: {
user_stake: 1.2
},
user_id: 3,
jackpot_id: 4
}
如果您通过白名单发送,则获得:
{
user_id: 3,
jackpot_id: 4
}
解决方案是简单地嵌套输入:
<%= form_for @game, html: { role: 'form' }, remote: true %>
<%= f.text_field :user_stake, class: 'form-control' %>
<%= f.hidden_field_tag 'user_id', current_user.id %>
<%= f.hidden_field_tag 'jackpot_id', @jackpot.id %>
# ..
<% end %>
正确地将它们列入白名单:
private
def game_params
params.require(:game)
.permit(:user_stake, :user_id, :jackpot_id)
end
但是这里有一个巨大的警告标志 - 从不通过params传递当前用户ID,因为它使得一个恶意用户很容易破解除了网络检查员。而是直接从会话中使用该值。
除了用户密码或了解应用程序密码外,您无法伪造。
此外,如果游戏属于累积奖金,我会将其设置为nested resource并将ID放在路径中,因为这会创建一个RESTful结构,清楚地表明您正在向父资源添加子项 - 而不是将重要信息隐藏在请求体中。
# routes.rb
resources :jackpots do
resources :games, shallow: true
end
class GamesController
before_action :set_jackpot, only: [:new, :create, :index]
# GET /jackpots/:jackpot_id/games/new
def new
@game = @jackpot.games.new
end
# POST /jackpots/:jackpot_id/games
def create
@game = @jackpot.games.new(game_params) do |g|
g.user = current_user
end
if @game.save
# ...
else
# ...
end
end
# GET /jackpots/:jackpot_id/games
def index
@games = @jackpot.games
end
private
def set_jackpot
@jackpot = Jackpot.includes(:games)
.find(params[:jackpot_id])
end
def game_params
params.require(:game).permit(:user_stake)
end
end
<%= form_for [@jackpot, @game], remote: true, html: { role: 'Form' } do |f| %>
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="input-group">
<%= f.number_field :user_stake, class: 'form-control' %>
<span class="input-group-btn">
<%= f.submit 'Go', :html => { :type => "button" }, class: "btn btn-default" %>
</span>
</div>
</div>
</div>
<% end %>
请注意,不需要隐藏的输入。