ruby-on-rails Rails远程表单参数未传递到控制器

kulphzqa  于 2022-11-19  发布在  Ruby
关注(0)|答案(2)|浏览(141)

我在rails应用程序中有一个表单,用户只需输入一个数字,表单就会通过 AJAX 提交。如果所有参数都存在,我的gamescontroller中就会创建一个新游戏。我有两个hidden_field_tags,它们的参数很好地传递给了controller,但最重要的参数,从用户输入中获得的参数,似乎没有传递给controller。
我的表单:

<%= 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,这是我在迁移中设置的默认值。我不知道我在这里做错了什么。有什么想法吗?谢谢!

c0vxltue

c0vxltue1#

您没有正确嵌套输入:

<%= form_for @game, html: { role: 'form' }, remote: true do |f| %>  
  <%= f.text_field :user_stake, class: 'form-control' %>
  <%= hidden_field_tag 'user_id', current_user.id  %>
  <%= hidden_field_tag 'jackpot_id', @jackpot.id  %> 
  # ..
<% end %>

这将给予以下params散列:

{
   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 do |f| %>  
  <%= 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

但是这里有一个很大的警告标志--千万不要通过参数传递当前用户ID,因为这会让恶意用户很容易只使用web检查器来攻击。
你不能伪造这一点,除非使用用户密码或通过破解会话加密。
此外,如果一个游戏属于头奖,我会将其设置为嵌套资源,并将id放在路径中,因为这会创建一个REST风格的结构,该结构清楚地显示您正在向父资源添加子资源,而不是在请求主体中隐藏重要信息。
第一个
请注意,不需要隐藏输入。

wsxa1bj1

wsxa1bj12#

您可能需要检查服务器日志以查看控制器的create方法中发布了什么。我怀疑game参数被封装在game散列中。要访问它,我建议将game_params更改为要求game:

def game_params
  params.require(:game).permit(:user_stake, :user_id, :jackpot_id)
end

相关问题