Ruby on Rails 6:表单通过隐藏字段提交哈希数组但被 <ActionController::Parameters ..... permitted: false> 阻止
Ruby on Rails 6: form submits an array of hashes via hidden field but gets blocked by <ActionController::Parameters ..... permitted: false>
在 posts 表单错误上显示 'User Must Exist'。
正在接收正确的参数,包括 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 %>
Post控制器
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
Post 型号
class Post < ApplicationRecord
belongs_to :user, dependent: :destroy
end
任何帮助将不胜感激
您没有使用您的 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'
}
}
注意它不一样,它是一个散列的散列,如果每个散列作为键(这是隐藏字段名称 items_bought[1]
和 items_bought[2]
的第一部分,你就有了 ID,并且ID 是字符串,而不是数字。
您也可以将哈希序列化为字符串:
hidden_field_tag :items_bougth, my_hash.to_json
然后在控制器上做
param_hash = JSON.parse(params[:items_bought]
但我不推荐这样做,这表明做的事情比需要的更复杂,您需要解析参数、使用额外的库等。
请注意,您不应该按原样对 LineItem 这样的复杂对象执行任何操作,您谈论的是哈希数组,LineItems 数组不是哈希数组,您必须先将对象转换为哈希使这两种方法始终如一地工作。
在 posts 表单错误上显示 'User Must Exist'。
正在接收正确的参数,包括 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 %>
Post控制器
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
Post 型号
class Post < ApplicationRecord
belongs_to :user, dependent: :destroy
end
任何帮助将不胜感激
您没有使用您的 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'
}
}
注意它不一样,它是一个散列的散列,如果每个散列作为键(这是隐藏字段名称 items_bought[1]
和 items_bought[2]
的第一部分,你就有了 ID,并且ID 是字符串,而不是数字。
您也可以将哈希序列化为字符串:
hidden_field_tag :items_bougth, my_hash.to_json
然后在控制器上做
param_hash = JSON.parse(params[:items_bought]
但我不推荐这样做,这表明做的事情比需要的更复杂,您需要解析参数、使用额外的库等。
请注意,您不应该按原样对 LineItem 这样的复杂对象执行任何操作,您谈论的是哈希数组,LineItems 数组不是哈希数组,您必须先将对象转换为哈希使这两种方法始终如一地工作。