一个StackOverflow问题已经问我需要什么,但自我答案并没有帮助我知道接下来该做什么。这个问题中提出的情景(whitelisting deeply nested strong parameters in rails)几乎就是我所发生的事情,但我会发布一个我的缩写(仍然很长)并希望有人 - 甚至可能是该职位的戴夫 - 可以提供帮助(我没有足够的声誉来发表评论并问他)。关于我无法阅读的嵌套强参数的链接很少,而且我已经在许多控制器和API端点上处理了一些,但这是应用程序中最复杂的。 (我包括这么长的例子,所以你可以看到完整的复杂性。)
这是在sales_controller
上,我们无法获得的其中一个属性是timezone_name
,它位于run_spans_attributes
中,位于{{ 1 {}在options_attributes
下。我已经尝试了几乎所有与嵌入式属性相匹配的不同语法方法,这些方法在StackOverflow上有强参数问题,但没有一个有效。我需要更多课程吗?有魔术括号吗?我需要新的建议。请。
应该注意的是,这是使用strong_parameters gem和Rails 3.2.21,但我想让Rails 4准备好应用程序,所以我希望避免短期解决方案。
对不起,这么久了:
sale
帮帮我这么做吧?顺便说一下,各种 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|
答案 0 :(得分: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_from
和type
:
{"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 :(得分:1)
试试这个:
params.require(:sale).permit(:options_attributes => [:other_attributes, { :run_spans_attributes => [:timezone_name] }]
答案 2 :(得分:1)
按照我在控制器中所做的操作,这是我认为会起作用的:
params.require(:sale).permit(:cloned_form, ... billing_addresses_attributes: [:id, :city, :building] ...)
有条不紊地,在&#34; 0&#34; =&gt;等属性周围加上括号。并且不要忘记adf:id和:_destroy就像我在回答中提到的那样,因为我最终创建了其他模型并使用了accepts_nested_attributes_for。
答案 3 :(得分:1)
对于后人,我想让大家知道我们最终发现了什么:嗯,信息就在那里,事实上,我在Russ Olsen的 Eloquent Ruby 中读到了它,值得庆幸的是,在与更高级开发人员的调试会话期间,我记得:#34;然而,随着Ruby 1.9的出现,哈希已经变得非常有序。&#34;
为什么那么重要?我将控制器上的属性按字母顺序排列,并且由于users
的设置方式,他们需要run_span_attributes
位于前面。如果它不是,那么它就无法实现。你只能想象调试这个如何折磨我们。但至少我们现在知道了:订单事项。所以,如果一切都失败了,请记住。
答案 4 :(得分:0)
经过一些实验,我发现这个问题似乎只存在于整数字符串的哈希键中。
当我用非整数字符串替换整数字符串时,强参数接受了哈希。
假设我们无法在参数中更改数据格式,一种解决方法是在遇到麻烦的级别allow arbitrary hashes(例如:run_spans_attributes => {})。
如果您使用表单来修改模型,则可能会打开使用任意哈希打开的模型进行批量分配的风险-您将牢记这一点。