为已转换的属性和数组设置强参数



结合使用mobilitygem和ActiveStorage, Rails指南建议为存储对象设置强参数的关系可能为

def message_params
params.require(:message).permit(:title, :content, images: [])
end

但是,由于需要建立可转换的参数,因此需要第二个强参数集合。

translated_params = (I18n.available_locales.map do |l|
[:"element_#{Mobility.normalize_locale(l)}"]
end.flatten)
params.require(:component).permit(:element, :tag_ids, :reference_ids, translated_params, documents: [])

呈现。但是,下面的语法

params.require(:vocabular).permit(:element, :tag_ids, :reference_ids, documents: [], translated_params)

生成错误syntax error, unexpected ')', expecting => ...cuments: [], translated_params)

这是令人惊讶的,因为没有立即的语法错误;这更像是一个陷阱。
为什么ruby解释有一个括号的要求-或者在参数的末尾放置显式声明的数组?

为了便于查看:

def permit *filters
filters
end
>> permit(:positional_arg)
=> [:positional_arg]
>> permit(:positional_arg, keyword: :arg)
=> [:positional_arg, {:keyword=>:arg}]
>> permit(:positional_arg, keyword: :arg, :err)
/home/alex/.rbenv/versions/3.2.1/lib/ruby/3.2.0/irb/workspace.rb:119:in `eval': (irb):6: 
syntax error, unexpected ')', expecting => (SyntaxError)
...ional_arg, keyword: :arg, :err)
...                              ^

:err)这是一个语法错误,因为ruby期望=>,如另一个关键字参数的键/值对,但你给了它)

>> permit(:positional_arg, keyword: :arg, not: :err)
=> [:positional_arg, {:keyword=>:arg, :not=>:err}]
#                    ^                          ^
# see how it's part of a single hash

它与参数无关,实际上它不是一个有效的语法:

>> [one: :two, :three]
syntax error, unexpected ']', expecting => (SyntaxError)
[one: :two, :three]
^

和下面的操作是一样的:

>> {one: :two, :three} 
syntax error, unexpected '}', expecting => (SyntaxError)
{one: :two, :three}
^

translated_params是一个数组,它应该在关键字参数前面。因为实际的permit方法将所有参数平展,所以不需要将*平展到数组中。

如果你只是想保持translated_params独立,你可以把它作为第一个参数:

params.require(:vocabular)
.permit(translated_params, :element, :tag_ids, :reference_ids, documents: [])

或者像这样:

params.require(:vocabular)
.permit([:element, :tag_ids, :reference_ids, documents: []], translated_params)

只是为了清楚,这适用于permit方法,它并不适用于所有。