通过 Rails 中的强参数仅允许某些值 4
Allowing only certain values though a strong parameter in Rails 4
我有一个字段otp_set_up,在company_user模型中允许"true" 或 "false".
有一个用例,系统管理员用户可以将此字段重置为 "false"。
虽然可以通过代码将字段设置为 "true",但用户不能通过表单编辑等将其设置为 "true"。
我没有在模型中添加验证,因为它可以是 "true" 或 "false"。
在 params.require .permit 位之前,我在特定于控制器更新的参数方法中有以下代码:
if curr_company_user.is_sys_admin? && curr_company_user.can_crud_company_users? && params[:id].to_i != curr_company_user.id
params[:company_user] = params[:company_user].except(:otp_set_up) if params[:company_user][:otp_set_up] == true
params.require(:company_user).permit(:otp_setup, etc. etc....
elsif etc. etc...
这行得通。系统管理员用户无法将 otp_set_up 设置为 "true"。
我的问题是:
这是在 Rails 中执行此操作的最佳和正确方法吗?对我来说似乎有点 hacky,通过 params 散列并删除一点。
有没有更好/更干净的方法?
我建议您仅在用户是管理员时才在参数中设置它,否则不要设置。我认为这是一个更好的方法。
在模型中,执行如下操作:
if user.role == 'admin'
attr_accessor #All the params
else
attr_accessor #All the other params except the one you want to
exclude
delete_if
清理它。仍然有点老套,但稍微不那么老套了:)
params.require(:company_user).permit(:otp_setup).delete_if do |key, val|
key == 'otp_setup' && val == true
end
这会使原始 params
对象完好无损。
没有内置的方法来执行此操作。以前好像有,现在没有了https://github.com/rails/strong_parameters/issues/167
delete_if
是在核心库中的 Hash
上定义的,因此它可能是在 Ruby 中进行此操作的最佳方法,并在 Rails 中进行扩展缺少内置方法。
更新
我认为这是一个有趣的想法,所以我为这种类型的用例写了一个名为 allowable 的小 gem。它将在 Hash
和 ActionController::Parameters
中添加一些方法:#allow
、#allow!
、#forbid
和 #forbid!
你会像这样使用它
params.require(:company_user).permit(:otp_setup).forbid(otp_setup: [true])
# or
params.require(:company_user).permit(:otp_setup).allow(otp_setup: [false])
您可以指定单个值或值数组,它不会改变原始 params
对象
我真的不建议在这种情况下摆弄 params
对象。我认为最好让大部分内容保持不变,以保留实际要求的内容。这样,如果您在下游某处再次需要该值,您就不会挠头。
另一种方法是在传递到 permit
之前构建要接受的属性列表。
# Attributes that everyone can modify.
attrs = [:attrs, :everyone, :can, :modify]
# Then "whitelist" other attributes based on your permission logic.
if curr_company_user.is_sys_admin? && curr_company_user.can_crud_company_users? && params[:id].to_i != curr_company_user.id
attrs << :otp_set_up unless params[:company_user][:otp_set_up] == true
elsif something_else?
# Modify what can be permitted for this case.
# etc...
end
params.require(:company_user).permit(*attrs)
我有一个字段otp_set_up,在company_user模型中允许"true" 或 "false".
有一个用例,系统管理员用户可以将此字段重置为 "false"。
虽然可以通过代码将字段设置为 "true",但用户不能通过表单编辑等将其设置为 "true"。
我没有在模型中添加验证,因为它可以是 "true" 或 "false"。
在 params.require .permit 位之前,我在特定于控制器更新的参数方法中有以下代码:
if curr_company_user.is_sys_admin? && curr_company_user.can_crud_company_users? && params[:id].to_i != curr_company_user.id
params[:company_user] = params[:company_user].except(:otp_set_up) if params[:company_user][:otp_set_up] == true
params.require(:company_user).permit(:otp_setup, etc. etc....
elsif etc. etc...
这行得通。系统管理员用户无法将 otp_set_up 设置为 "true"。
我的问题是:
这是在 Rails 中执行此操作的最佳和正确方法吗?对我来说似乎有点 hacky,通过 params 散列并删除一点。
有没有更好/更干净的方法?
我建议您仅在用户是管理员时才在参数中设置它,否则不要设置。我认为这是一个更好的方法。
在模型中,执行如下操作:
if user.role == 'admin'
attr_accessor #All the params
else
attr_accessor #All the other params except the one you want to
exclude
delete_if
清理它。仍然有点老套,但稍微不那么老套了:)
params.require(:company_user).permit(:otp_setup).delete_if do |key, val|
key == 'otp_setup' && val == true
end
这会使原始 params
对象完好无损。
没有内置的方法来执行此操作。以前好像有,现在没有了https://github.com/rails/strong_parameters/issues/167
delete_if
是在核心库中的 Hash
上定义的,因此它可能是在 Ruby 中进行此操作的最佳方法,并在 Rails 中进行扩展缺少内置方法。
更新
我认为这是一个有趣的想法,所以我为这种类型的用例写了一个名为 allowable 的小 gem。它将在 Hash
和 ActionController::Parameters
中添加一些方法:#allow
、#allow!
、#forbid
和 #forbid!
你会像这样使用它
params.require(:company_user).permit(:otp_setup).forbid(otp_setup: [true])
# or
params.require(:company_user).permit(:otp_setup).allow(otp_setup: [false])
您可以指定单个值或值数组,它不会改变原始 params
对象
我真的不建议在这种情况下摆弄 params
对象。我认为最好让大部分内容保持不变,以保留实际要求的内容。这样,如果您在下游某处再次需要该值,您就不会挠头。
另一种方法是在传递到 permit
之前构建要接受的属性列表。
# Attributes that everyone can modify.
attrs = [:attrs, :everyone, :can, :modify]
# Then "whitelist" other attributes based on your permission logic.
if curr_company_user.is_sys_admin? && curr_company_user.can_crud_company_users? && params[:id].to_i != curr_company_user.id
attrs << :otp_set_up unless params[:company_user][:otp_set_up] == true
elsif something_else?
# Modify what can be permitted for this case.
# etc...
end
params.require(:company_user).permit(*attrs)