【问题标题】:Rails 5 - how to whitelist the param for an ENTIRE jsonb postgres column in a controller?Rails 5 - 如何将控制器中整个 jsonb postgres 列的参数列入白名单?
【发布时间】:2017-07-09 01:48:51
【问题描述】:

我尝试使用建议的示例from github。您还可以在诸如 this one for Rails 4 之类的一些答案中找到它。

我在 Rails 5.0.1 中试过这个,我只是得到一个空的哈希 {} 存储在数据库中:

def proposal_params
  params.require(:proposal).permit(:document, :account_id).tap do |whitelisted|
    whitelisted[:document] = params[:proposal][:document]
  end
end

显然,如果我允许的话!它有效。

我也试过this question的回答:

def proposal_params
  params.require(:proposal).permit(:account_id, document: Proposal.stored_attributes[:document])
end

但这也行不通。

:document 属性包含 json,它在请求之间永远不会相同......并且是一个长而复杂的结构。

我只需要将它原样转储到 jsonb 列中。

对于好奇的人,这里是document 中的示例:

{
   "document":{
      "customer":{
         "id":"273a0ad1-0867-4c17-8e0a-3284c6f2f6af",
         "first_name":"Ricardo",
         "last_name":"Bird",
         "email":"ricardo_bird@smithtrantow.co",
         "mobile":"07786560223"
      },
      "state":8,
      "salutation":"Mr & Mrs Bird",
      "total_price":0,
      "quoted_products":[
         {
            "product":{
               "sku":"9111",
               "name":"Solid European Oak",
               "price":25.99,
               "category":"Wood",
               "sub_category":"Solid",
               "updated_at":"2016-12-01",
               "updated_by":"Donald Duck",
               "created_at":"2016-11-01",
               "created_by":"Mickey",
               "image_url":"http://www.higherground.co.uk/wp-content/uploads/2015/11/wood-flooring-thumbnail.jpg"
            },
            "total_price":25.99,
            "total_area":1,
            "product_total_price":25.99,
            "is_manual_total":false,
            "is_installed":false,
            "install_price":null,
            "are_rooms_grouped":false,
            "rooms":[
               {
                  "name":"Dining Room",
                  "icon_url":"assets/fb-img/dining-room.png",
                  "number":null,
                  "area":1,
                  "width":null,
                  "length":null,
                  "subfloor_prep":null,
                  "subfloor_price":null,
                  "perimeter_product":null,
                  "perimeter_length":null,
                  "is_perimeter_installed":false,
                  "perimeter_price":null,
                  "perimeter_style":null,
                  "is_perimeter_remove_old":false,
                  "is_move_furniture":false,
                  "move_furniture_price":null,
                  "move_surcharge":null,
                  "stairs_stepcount":null,
                  "surcharge":null,
                  "is_installed":false,
                  "uplift_price":null,
                  "install_method":"bonded"
               }
            ],
            "is_extras":true,
            "threshold_count":2,
            "radiator_count":3,
            "trim_count":2,
            "threshold_price":30,
            "radiator_price":4,
            "trim_price":10,
            "is_rear_mat":false,
            "is_front_mat":true,
            "front_mat_type":"Coloured",
            "rear_mat_type":null,
            "front_mat_area":2,
            "front_mat_price":60.01,
            "rear_mat_area":null,
            "rear_mat_price":null,
            "extras_total_price":212.01999999999998
         }
      ],
      "status":"Draft",
      "is_details_oneprice":false,
      "notes":"Testing submission"
   }
}

【问题讨论】:

  • 似乎有一个杰出的公关可以在这里提供一个简单的解决方案:github.com/rails/rails/pull/26308
  • 此问题是否与您在尝试允许 document 参数时收到的警告“Unpermitted parameter: document”有关?
  • @Pyro 你的回答解决了它。谢谢!我认为在这种特殊情况下,未经许可的参数消息可能只是一个红鲱鱼。
  • 很高兴听到。奇怪的是,您的函数为我返回了相同的结果,我不完全确定这可以解决问题的原因。您链接到的即将发生的拉取请求可能就是这样做的。

标签: ruby-on-rails json postgresql parameters whitelist


【解决方案1】:

【讨论】:

  • 感谢链接,我没有意识到参数现在返回一个对象。
【解决方案2】:

如果我是正确的,你仍然需要permit!文档参数:

def proposal_params
  params.require(:proposal).permit(:account_id).tap do |whitelisted|
    whitelisted[:document] = params[:proposal].fetch(:document, ActionController::Parameters.new).permit!
  end
end

它的工作方式是它首先只保留account_id,然后在tap 中,我们通过尝试从原始参数中检索它来添加document 参数。 ActionController::Parameters.new 作为fetch 的默认值确保permit! 方法始终可调用,即使没有传递document 参数。

在引擎盖下ActionController::Parameters#permit! seems to recursively call the permit! function 包含的参数也是如此,因此我们可以在任何实例上调用它:

def permit!
  each_pair do |key, value|
    Array.wrap(value).each do |v|
      v.permit! if v.respond_to? :permit!
    end
  end

  @permitted = true
  self
end

【讨论】:

  • 感谢您的详细解释。这行得通,谢谢。我在问题中添加了一条评论,指出未来版本的 Rails 中有一个解决方案来简化这个问题的解决方案。
猜你喜欢
  • 1970-01-01
  • 2015-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
相关资源
最近更新 更多