为什么 Rails 中的强参数顺序很重要?

Aug*_*rmo 2 forms ruby-on-rails nested-forms nested-form-for strong-parameters

在我的product_model_controller.rb强参数中,我有以下代码:

  def product_model_params
    params.require(:product_model)
          .permit(:name, :product_category_id, 
                  product_category_attributes: [:id, :name], attr_val_ids: [])
  end
Run Code Online (Sandbox Code Playgroud)

按照它的方式,它工作得很好。但是,如果我更改参数的顺序,它就会停止工作。例子:

  def product_model_params
    params.require(:product_model)
          .permit(:name, product_category_attributes: [:id, :name],
                  :product_category_id, attr_val_ids: [])
  end
Run Code Online (Sandbox Code Playgroud)

错误:

语法错误,意外的 ',',期望 => ..., :name], :product_category_id, attr_val_ids: []) ... ^

为什么会出现这种情况?我已经坚持了很长时间了:/


产品模型.rb

class ProductModel < ApplicationRecord
  validates :name, presence: true
  validates :name, uniqueness: true

  has_many :products
  has_many :product_model_attr_vals
  has_many :attr_vals, through: :product_model_attr_vals
  has_many :attrs, through: :attr_vals

  belongs_to :product_category

  accepts_nested_attributes_for :product_model_attr_vals
  accepts_nested_attributes_for :product_category
end
Run Code Online (Sandbox Code Playgroud)

产品类别.rb

class ProductCategory < ApplicationRecord
  validates :name, presence: true
  validates :name, uniqueness: true

  has_many :product_models
end
Run Code Online (Sandbox Code Playgroud)

Phi*_*rom 5

这不是强参数的问题,而是 Ruby 如何解析方法签名和哈希的问题。抽象一点你的第一个例子是这样的:

some_method(arg1, arg2, key1: val1, key2: val2)
Run Code Online (Sandbox Code Playgroud)

Ruby 将识别隐式尾随哈希并在内部将其表示为:

some_method(arg1, arg2, {key1: val1, key2: val2})
Run Code Online (Sandbox Code Playgroud)

这只适用最右边的散列式参数。在你的第二个例子中,你已经这样做了:

some_method(arg1, key1: val1, arg2, key2: val2)
Run Code Online (Sandbox Code Playgroud)

鲁比不知道该怎么办。它将key2参数转换为散列,但随后留下一个参数,看起来像一个命名参数,还有一个参数。它不喜欢那样。

您可以通过这样做来修复它:

some_method(arg1, {key1: val1}, arg2, key2: val2)
Run Code Online (Sandbox Code Playgroud)

甚至是这个:

some_method(arg1, {key1: val1}, arg2, {key2: val2})
Run Code Online (Sandbox Code Playgroud)

Ruby 会将这两者视为参数、散列、参数、散列并且能够处理。