严格参数-无法访问深层属性

问题描述 投票:2回答:5

一个StackOverflow问题已经问我需要什么,但是自我回答并没有帮助我知道下一步该怎么做。该问题(whitelisting deeply nested strong parameters in rails)中提出的场景几乎是我正在做的事情,但我将发布我的缩写(仍然很长),并希望有人-甚至是职位的戴夫-可以提供帮助(我没有足够的声誉来评论和询问他)。关于嵌套强参数的链接很少,我还没有读过,我已经在许多控制器和API端点上进行了处理,但这是应用程序中最复杂的。 (我提供了一个很长的示例,因此您可以看到全部的复杂性。)

这在sales_controller上,我们无法获得的属性之一是timezone_name,它在run_spans_attributes中,在options_attributes下的sale中。我已经尝试过所有与大多数嵌套属性匹配的不同语法方法,这些方法在StackOverflow上具有很强的参数问题,但没有一个起作用。我需要更多课程吗?有魔术括号吗?我需要新的建议。请。

应该注意,这是与strong_parameters gem和Rails 3.2.21一起使用的,但是我想为Rails 4准备好该应用程序,因此我希望避免短期解决方案。

抱歉,很长:

 Parameters:
    "sale"=>{
      "cloned_from"=>"",
      "type"=>"Localsale",
      "primary_contact_attributes"=>{
          "primary"=>"true",
          "first_name"=>"Fred",
          "id"=>"1712"
        },
      "contract_signed_on"=>"March 20, 2015",
      "billing_addresses_attributes"=>{
          "0"=>{
              "billing"=>"1",
              "city"=>"San Diego",
              "id"=>"29076"
            }
        },
      "other_contacts_attributes"=>{
          "0"=>{
              "first_name"=>"Fred",
              "_destroy"=>"false",
              "id"=>"170914"
            },
          "1"=>{
              "first_name"=>"Fred",
              "last_name"=>"Smith",
              "_destroy"=>"false",
              "id"=>"1798"
            }
        },
      "opportunity_detail_attributes"=>{
          "original_salesperson_id"=>"",
          "id"=>"10130"
        },
      "production_editor"=>"1868097",
      "event_sale_attributes"=>{
          "0"=>{
              "name"=>"is_super_sale",
              "value"=>"0",
              "id"=>"15326"
            },
          "1"=>{
              "name"=>"super_show_code",
              "value"=>""
            },
        },
      "scheduling_note"=>"",
      "category_ids"=>["2", "364"],
      "options_attributes"=>{
          "0"=>{
              "title"=>"T-Shirt and Bag Check",
              "event_starts_at(1i)"=>"2015",
              "event_starts_at(2i)"=>"6",
              "event_doors_open_at_attributes"=>{
                  "option_id"=>"8682604",
                  "doors_time(1i)"=>"",
                  "id"=>"278382"
                },
              "event_option_attributes"=>{
                  "0"=>{
                      "name"=>"event_duration",
                      "value"=>""
                    },
                  "1"=>{
                      "name"=>"send_pre_event_email",
                      "value"=>"1",
                      "id"=>"632546"
                    }
                },
              "language_id"=>"1",
              "run_spans_attributes"=>{
                  "0"=>{
                      "timezone_name"=>"Eastern Time (US & Canada)",
                      "_destroy"=>"false",
                      "id"=>"560878"
                    },
                  "1429320288130"=>{
                      "timezone_name"=>"Eastern Time (US & Canada)",
                      "_destroy"=>"false"
                    }
                },
              "_destroy"=>"false",
              "id"=>"8682604"
              }#ends 0 option
          },#ends options
      "coupons_per_redemption"=>"1",
      "methods_attributes"=>{
          "0"=>{
              "redemption_code"=>"0",
              "_destroy"=>"0",
              "id"=>"9797012"
            },
          "1"=>{
              "redemption_code"=>"4",
              "_destroy"=>"1",
              "vendor_provided_promo_code"=>"0",
              "promo_code"=>""
            }
        }, #ends redemption methods
      "addresses_attributes"=>{
          "0"=>{
              "street_address_1"=>"2400 Cat St",
              "primary"=>"0",
              "id"=>"2931074",
              "_destroy"=>"false"
            }
        },
      "zoom"=>"",
      "video_attributes"=>{
          "youtube_id"=>"",
        },
      "updated_from"=>"edit"
      }

帮我做对吗?顺便说一下,各种.tap do |whitelisted|方法都失败了。

 private
 def_sale_strong_params
    params.require(:sale).permit(:how, :the, :heck, :do, :the_attributes =>
       [:make, themselves => [:known, :outside => [:of, :these => [:darn,
        :parentheses], :and], :brackets]])
 end
ruby-on-rails ruby strong-parameters
5个回答
3
投票

1。在控制台中验证您的进度

要配置强参数,它可以帮助在Rails控制台中工作。您可以将参数设置为ActiveSupport::HashWithIndifferentAccess对象,然后开始测试从ActionController::Parameters中得到的结果。

例如,假设我们开始于:

params = ActiveSupport::HashWithIndifferentAccess.new(
  "sale"=>{
    "cloned_from"=>"",
    "type"=>"Localsale"}
)

我们可以运行此:

ActionController::Parameters.new(params).require(:sale).permit(:cloned_from, :type)

并且我们将其作为返回值,并且我们知道我们已成功允许cloned_fromtype

{"cloned_from"=>"", "type"=>"Localsale"}

您可以继续努力直到所有参数都考虑在内。如果您包含问题中的全部参数,则...

params = ActiveSupport::HashWithIndifferentAccess.new(
  "sale"=>{
    "cloned_from"=>"",
    "type"=>"Localsale",
    ...
    "options_attributes"=>{
      "0"=>{
        "title"=>"T-Shirt and Bag Check",
        ...
        "run_spans_attributes"=>{
          "0"=>{
            "timezone_name"=>"Eastern Time (US & Canada)",
            ...
)

...您可以使用类似如下的结构来描述timezone_name

ActionController::Parameters.new(params).require(:sale).permit(:cloned_from, :type, options_attributes: [:title, run_spans_attributes: [:timezone_name]])

控制台中的返回值将是:

{"cloned_from"=>"", "type"=>"Localsale", "options_attributes"=>{"0"=>{"title"=>"T-Shirt and Bag Check", "run_spans_attributes"=>{"0"=>{"timezone_name"=>"Eastern Time (US & Canada)"}, "1429320288130"=>{"timezone_name"=>"Eastern Time (US & Canada)"}}}}}

2。将工作分解成较小的部分

试图在一行上处理每个模型的所有允许的属性可能会造成混淆。您可以将其分为几行,以使事情更容易理解。从此结构开始,并为每个模型填写其他属性:

video_attrs = []  # Fill in these empty arrays with the allowed parameters for each model
addresses_attrs = []
methods_attrs = []
run_spans_attrs = [:timezone_name]
event_option_attrs = []
options_attrs = [:title, event_option_attributes: event_option_attrs, run_spans_attributes: run_spans_attrs]
event_sale_attrs = []
opportunity_detail_attrs = []
other_contacts_attrs = []
billing_addresses_attrs = []
primary_contact_attrs = []
sales_attributes = [
  :cloned_from, 
  :type, 
  primary_contact_attributes: primary_contact_attrs, 
  billing_addresses_attributes: billing_addresses_attrs,
  other_contacts_attributes: other_contacts_attrs,
  options_attributes: options_attrs, 
  opportunity_detail_attributes: opportunity_detail_attrs,
  event_sale_attributes: event_sale_attrs,
  methods_attributes: methods_attrs,
  addresses_attributes: addresses_attrs,
  video_attributes: video_attrs
]

然后您可以将*sales_attributes发送到允许的参数中。您可以使用以下命令在控制台中进行验证:

ActionController::Parameters.new(params).require(:sale).permit(*sales_attributes)

1
投票

尝试一下:

params.require(:sale).permit(:options_attributes => [:other_attributes, { :run_spans_attributes => [:timezone_name] }]

1
投票

按照我在控制器中所做的事情,这是我认为可以使用的内容:

params.require(:sale).permit(:cloned_form, ... billing_addresses_attributes: [:id, :city, :building] ...)

有效地,将方括号括在“ 0” =>之类的属性上,不要忘了像我在回答中提到的那样adf:id和:_destroy,因为我最终创建了其他模型并使用了accepts_nested_attributes_for。


1
投票

[后代,我想让人们知道我们最终发现的东西:恩,信息在那里,实际上,我是在Russ Olsen的Eloquent Ruby中阅读它的,我很幸运地在与一位更高级的开发人员:“但是,随着Ruby 1.9的出现,哈希变得越来越有序。”

为什么这么重要?我按字母顺序排列了控制器上的属性,由于run_span_attributes的设置方式,它们需要timezone_name位于最前面。如果不是,那就无法实现。您只能想象调试它如何折磨我们。但至少我们现在知道:订购事项。因此,如果其他所有方法均失败,请记住这一点。


0
投票

经过一些实验,我发现这个问题似乎只存在于整数字符串的哈希键中。

当我用非整数字符串替换整数字符串时,强参数接受了哈希。

假设我们无法更改参数中的数据格式,一种解决方法是在遇到麻烦的级别将其设置为allow arbitrary hashes(例如:run_spans_attributes => {})。

如果您使用表单来修改模型,则可能会给您打开带有任意哈希的模型带来大量分配的风险,您要牢记这一点。

© www.soinside.com 2019 - 2024. All rights reserved.