【问题标题】:Ruby on Rails 6: form submits an array of hashes via hidden field but gets blocked by <ActionController::Parameters ..... permitted: false>Ruby on Rails 6:表单通过隐藏字段提交哈希数组,但被 <ActionController::Parameters ..... allowed: false> 阻止
【发布时间】:2019-12-15 02:50:51
【问题描述】:

在帖子表单错误中显示“用户必须存在”。

正在接收正确的参数,包括 user_id,但仍然拒绝所有参数。 我怀疑它与哈希数组有关,因为它们来自另一个控制器,但通过一个表单。

所以当我检查 Post 参数时,它会说:

<ActionController::Parameters {"email"=>"test@test.com", "user_id"=>"2", "items_bought"=>"[#<LineItem id: 3, product_id: 1, cart_id: 3, quantity: 1>, #<LineItem id: 4, product_id: 2, cart_id: 3, quantity: 4>]"} permitted: false>

Simple_form_for @post

<%= simple_form_for @post, :url => user_posts_path do |f| %>

  <%= f.error_notification %>

  <ul>

    <%= @post.errors.full_messages.each do |message| %>
      <li><%= message %></li>
    <%end%>

  </ul>

   <%= f.input :email, :input_html => { value: "#{current_user.email}" } %>
   <%= f.input :user_id, :as => :hidden, :input_html => { value: "#{current_user.id}" } %>
   <%= f.input :items_bought, :as => :hidden, :input_html => { value: "#{current_cart.line_items.to_a}" } %>

   <%= f.error :base %>
   <%= f.button :submit %>

<% end %>

帖子控制器

class PostsController < ApplicationController

 def new
    @user = current_user
    @post = Post.new
 end

 def create
    @user = current_user
    @post = current_user.posts.build(params[:post_params])

  if @post.save 
    render plain:
    params[:post].inspect
  else
    render 'new'
  end

  end

  private

  def post_params
    params.require(:post).permit(:email, :user_id, items_bought: [:LineItem_id [], :product_id[], :cart_id[], :quantity[]])
  end
end

后模型

class Post < ApplicationRecord

  belongs_to :user, dependent: :destroy


end

任何帮助将不胜感激

【问题讨论】:

  • 这可能是由于_post.json.jbuilder.rb ...... json.extract! post, :user_id, :email, items_bought: [:LineItem_id [], :product_id[], :cart_id[], :quantity[]], :created_at, :updated_at json.url user_posts_url(user,post, 格式: :json )
  • 这看起来像是一次非常失败的尝试,应该使用嵌套属性或拆分为多个控制器操作来完成。
  • 您能否重新表述问题并询问您实际想要完成的工作,而不是您认为的解决方案?

标签: arrays ruby-on-rails forms hash actioncontroller


【解决方案1】:

你没有使用你的post_params方法,改变这个:

@post = current_user.posts.build(params[:post_params])

到这里:

@post = current_user.posts.build(post_params)

编辑:请注意,将 user_id 作为参数传递存在安全风险,有人可以更改隐藏字段的值。使用 current_user id 而不是从表单中接收 id。

实际上,所有隐藏信息都是从 current_user 中检索的,您实际上不需要使用隐藏字段,因为如果您可以访问 current_user,那么您已经可以访问所有这些信息(id、购物车项目)

编辑 2:如果您想在 :items_bought 参数中包含一个哈希数组,您需要使用多个具有特定名称的隐藏字段,以便它被 rails 解析为哈希。

假设你有这样的结构:

[
  {
    id: 1,
    name: 'Foo',
    some_attr: 'Lorem'
  },
  {
    id: 2,
    name: 'Bar',
    some_attr: 'Impsum'
  }
]

如果您将其作为参数发送,则需要多个隐藏字段:

hidden_field_tag 'items_bought[1][id]', 1
hidden_field_tag 'items_bought[1][name]', 'Foo'
hidden_field_tag 'items_bought[1][some_attr]', 'Lorem'
hidden_field_tag 'items_bought[2][id]', 2
hidden_field_tag 'items_bought[2][name]', 'Bar'
hidden_field_tag 'items_bought[2][some_attr]', 'Impsum'

提交后,params[:items_bought] 将是:

{
  '1' => {
    id: '1',
    name: 'Foo',
    some_attr: 'Lorem'
  },
  '2' => {
    id: '2',
    name: 'Bar',
    some_attr: 'Impsum'
  }
}

注意它不一样,它是一个哈希值,如果每个哈希值作为键,你就有 ID(这是隐藏字段名称 items_bought[1]items_bought[2] 的第一部分,ID 是字符串,而不是数字。

您还可以将哈希序列化为字符串:

hidden_field_tag :items_bougth, my_hash.to_json

然后在控制器上做

param_hash = JSON.parse(params[:items_bought]

但我不建议这样做,这表明做的事情比它需要的更复杂,你需要解析参数,使用额外的库等。

注意你不应该对像 LineItem 这样的复杂对象做任何这样的事情,你谈论的是一个哈希数组,一个 LineItems 数组不是一个哈希数组,你必须首先将对象转换为哈希始终如一地工作的方法。

【讨论】:

  • 感谢您的及时回复@arieljoud,您是对的,我做了您推荐的更改。这样做是为了查看将从会话中传递的内容,即 current_user。问题在于将散列数组传递给数据库。我明白您在控制器中而不是在表单中传递该信息的意思。但是有没有办法通过改变 post_params 方法来传递一个哈希数组?
  • 您不应该将哈希数组作为单个参数传递,您所拥有的只是 LineItems 数组的字符串表示形式,这不是 http 参数的工作方式,我将编辑我的答案向您展示在您的情况下应该如何完成,但我没有看到用例,这很难,因为这不是正确的方法
  • 感谢@arieljuod 把我从那个兔子洞里拉出来。我将改为通过控制器传递该数据。顺便说一句,使用 hidden_​​field_tag :items_bougth,my_hash.to_json 是一个很棒的我会尝试看看它是如何进行的。
猜你喜欢
  • 2023-04-11
  • 2017-08-03
  • 2011-03-06
  • 1970-01-01
  • 2012-05-12
  • 1970-01-01
  • 1970-01-01
  • 2014-04-22
  • 1970-01-01
相关资源
最近更新 更多