健壮参数

加入健壮参数功能后,Action Controller 的参数禁止在 Avtive Model 中批量赋值,除非参数在白名单中。也就是说,你要明确选择那些属性可以批量更新,避免意外把不该暴露的属性暴露了。

而且,还可以标记哪些参数是必须传入的,如果没有收到,会交由 raise/rescue 处理,返回“400 Bad Request”。

class PeopleController < ActionController::Base
   # This will raise an ActiveModel::ForbiddenAttributes exception
   # because it's using mass assignment without an explicit permit
   # step.
   def create
     Person.create(params[ :person ])
   end
 
   # This will pass with flying colors as long as there's a person key
   # in the parameters, otherwise it'll raise a
   # ActionController::ParameterMissing exception, which will get
   # caught by ActionController::Base and turned into that 400 Bad
   # Request reply.
   def update
     person = current_account.people.find(params[ :id ])
     person.update!(person_params)
     redirect_to person
   end
 
   private
     # Using a private method to encapsulate the permissible parameters
     # is just a good pattern since you'll be able to reuse the same
     # permit list between create and update. Also, you can specialize
     # this method with per-user checking of permissible attributes.
     def person_params
       params.require( :person ).permit( :name , :age )
     end
end
4.5.1 允许使用的标量值

假如允许传入 :id

params.permit( :id )

若 params 中有 :id,且 :id 是标量值,就可以通过白名单检查,否则 :id 会被过滤掉。因此不能传入数组、Hash 或其他对象。

允许使用的标量类型有:StringSymbolNilClassNumericTrueClassFalseClassDateTimeDateTimeStringIOIOActionDispatch::Http::UploadedFile 和 Rack::Test::UploadedFile

要想指定 params 中的值必须为数组,可以把键对应的值设为空数组:

params.permit(id: [])

要想允许传入整个参数 Hash,可以使用 permit! 方法:

params.require( :log_entry ).permit!

此时,允许传入整个 :log_entry Hash 及嵌套 Hash。使用 permit! 时要特别注意,因为这么做模型中所有当前属性及后续添加的属性都允许进行批量赋值。

4.5.2 嵌套参数

也可以允许传入嵌套参数,例如:

params.permit( :name , { emails: [] },
               friends: [ :name ,
                          { family: [ :name ], hobbies: [] }])

此时,允许传入 nameemails 和 friends 属性。其中,emails 必须是数组;friends 必须是一个由资源组成的数组:应该有个 name 属性,还要有 hobbies 属性,其值是由标量组成的数组,以及一个 family 属性,其值只能包含 name 属性(任何允许使用的标量值)。

4.5.3 更多例子

你可能还想在 new 动作中限制允许传入的属性。不过此时无法再根键上调用 require 方法,因为此时根键还不存在:

# using `fetch` you can supply a default and use
# the Strong Parameters API from there.
params.fetch( :blog , {}).permit( :title , :author )

使用 accepts_nested_attributes_for 方法可以更新或销毁响应的记录。这个方法基于 id 和 _destroy 参数:

# permit :id and :_destroy
params.require( :author ).permit( :name , books_attributes: [ :title , :id , :_destroy])

如果 Hash 的键是数字,处理方式有所不同,此时可以把属性作为 Hash 的直接子 Hash。accepts_nested_attributes_for 和 has_many 关联同时使用时会得到这种参数:

# To whitelist the following data:
# {"book" => {"title" => "Some Book",
#             "chapters_attributes" => { "1" => {"title" => "First Chapter"},
#                                        "2" => {"title" => "Second Chapter"}}}}
 
params.require( :book ).permit( :title , chapters_attributes: [ :title ])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值