Rails 4中动态表单的未授权参数

3

我刚接触Rails,并基于此构建了一些东西:

http://railscasts.com/episodes/403-dynamic-forms

但是,我在存储附加字段中遇到了问题...... 我有一个ProductType对象,其中包含许多ProductField对象。 ProductField对象也属于ProductType,而Product对象则属于ProductType。

因此,可以通过构造函数ProductType轻松添加新的动态字段,但是当我尝试通过Product控制器在这些字段中设置数据时,什么也没有发生。

我确定问题与强参数有关,但是描述如下的修复(这里)(这里)并没有帮助。

product.rb

class Product < ActiveRecord::Base
    belongs_to :product_type
    serialize :properties, Hash
end

product_type.rb

class ProductType < ActiveRecord::Base
    has_many :fields, class_name: "ProductField"
    accepts_nested_attributes_for :fields, allow_destroy: true
end

product_field.rb

class ProductField < ActiveRecord::Base
    belongs_to :product_type
end

products_controller.rb

class ProductsController < ApplicationController
    def new
    @product = Product.new(product_type_id: params[:product_type_id])
    end
    def product_params
    params.require(:product).permit(:name, :price, :product_type_id, {:properties => []})
    end

product_type_controller.rb

class ProductTypesController < ApplicationController
    def product_type_params
    params.require(:product_type).permit(:name, fields_attributes: [:id, :name, :field_type, :required, :product_type_id])
    end

在控制台日志中: 未允许的参数:properties
Started PATCH "/products/4" for 127.0.0.1 at 2013-10-04 22:54:59 +0400
Processing by ProductsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"my3ra60OUXexmmguk2eqRetizx3tWPMq04Z2PnODJMQ=", "product"=>{"product_type_id"=>"1", "name"=>"Product1", "properties"=>{"gjfghjf"=>"123", "123"=>[""]}, "price"=>"10"}, "commit"=>"Update Product", "id"=>"4"}
Product Load (0.3ms)  SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1  [["id", "4"]]
Unpermitted parameters: properties

P.S:当观看播客时,可能有人遇到了类似的问题?

你能发布一下你的表单代码吗?我看到你在返回参数中得到了这个:"properties"=>{"gjfghjf"=>"123", "123"=>[""]}。Properties作为一个哈希表有两个条目,其中之一是一个数组。在你的product_params中,它期望一个基于如何编写的允许标量值的数组。这个Railscast最初是使用Rails 4完成的吗? - Beartech
如果你想测试一下是表单代码或者permit语句中参数构造的问题,你可以这样做:params.require(:product).permit!。它会将所有内容都列入白名单,这对于测试来说很好,但是对于安全性来说非常糟糕,所以你最好在某个时候解决这个问题。 - Beartech
是的,params.require(:product).permit! 确实有效,但对于安全性来说非常糟糕,你说得很对。 - AntonyZ
1个回答

12

如果你想将嵌套的哈希作为参数返回,你必须在permit数组中命名键。

class ProductsController < ApplicationController
def new
@product = Product.new(product_type_id: params[:product_type_id])
end
def product_params
params.require(:product).permit(:name, :price, :product_type_id, {:properties => [:foo, :bar, :id]})
end

如果您正在动态生成密钥,无法将它们编码到permit语句中,则需要使用此样式:

def product_params
  params.require(:product).permit(:name, :price, :product_type_id).tap do |whitelisted|
    whitelisted[:properties] = params[:product][:properties]
  end
end

对于新用户而言,这不是最友好的代码。我刚刚完成了华盛顿大学的3门Rails证书课程,他们甚至都没有涵盖.tap

这不是我的作品,我仍然只是在理解.permit的更深层次。这是我使用的博客文章:Strong Parameters by Example


以上的代码是否可以不做任何修改就能正常工作?如果需要进行任何修改,请在此处留下评论,我会进行更改以使答案更准确。如果它可以完美地开箱即用,那太棒了!这对我来说有点幸运,因为我只是根据我对Strong Params的了解和阅读的内容进行推断。 - Beartech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接