当我们只更新一个属性时,我们应该使用强params吗?
我正在开发一个Rails应用程序,我有几个操作(#delete_later,#ban_later等等),我只从请求参数中设置一个属性(具体来说,是执行该操作的reason
字段)。
我想知道是否可以这样做:
def ban_later @object.reason = params[:object][:reason] @object.save end
或者即使在这种情况下使用强对数也是最佳做法?
def ban_later @object.reason = object_params[:reason] @object.save end private def object_params params.require(:object).permit(:permitted_1, :permitted_2, :reason) end
哪种解决方案最好? 如果没有,那么问题的最佳解决方案是什么?
后来编辑:
#ban_later,#delete_later操作确实可以设置标志列status
但是可以在不从params散列中接收它的值的情况下完成。 由于您只为每个方法设置一个状态,因此当您在#delete_later时可以简单地设置状态“pending_delete”,当您在#ban_later时,可以设置“pending_ban”。
后来编辑
为什么直接使用#save
而不是update_attributes
? 假设你需要一个if @object.save
语句。 在false分支(对象未保存)上,您可能仍希望呈现使用该@object
内容的视图。
第一个节省计算。
第二个检查是否存在:object sub-hash,我认为它对容错有好处。
我最初会选择第一名,但经过一番思考后我更喜欢第二名。
最简单的答案是,如果你只在params
使用一个参数,并且没有将它传递给像model#create
#create那样的多属性setter,那么你就不必使用strong_parameters来获得安全的解决方案。
但是,我预计整个控制器不太可能出现这种情况。 ban_later
方法只需要一个参数,其他控制器方法需要更多。 在这种情况下,问题变成:“你想对ban_later
以不同方式处理params
以及如何将它用于其他控制器方法吗?”。
您也可以确定function不会改变,并且当您更改function时,您将记得更改params
的处理方式。
因此,我会使用strong_parameters,因为它意味着:
- 参数在控制器中的所有方法中一致地处理。
- 随着function的变化,对方法的更改不太可能暴露漏洞。
如果要更新单个属性,为什么不使用update_attributes
方法? ( update_attribute
不调用validation)
def ban_later @object.update_attributes reason: params(:reason) end private def params params params = %i(:permitted_1, :permitted_2, :permitted_3) unless params params.require(:object).permit params end
根据ReggieB
的评论,您还可以使用update
选项:
def ban_later @object.update reason: params(:reason) end
如上所述,Reggie和其他答案解释了如何最好地工作的原理图(具有mass-assignment
IE等)。 以上是您可以自由使用的可操作代码。
这里的底线是,如果你想保持你的应用程序多function(IE在任何你需要的地方具有最大的可扩展性),你需要坚持强大的params设置。
其他答案概述了该设置的工作原理,以及它的function如何根据您的需要而有所不同。
我已经包含了一个技巧,所以你只接受params方法中的特定参数。 我没有对它进行过广泛的测试,因此我们可能需要对其进行重构以获得所需的结果。
强参数检查后为什么不只是update
对象? 它只是一个标准的工作流程。 (请告诉我,如果你的情况有任何理由不这样做)
def ban_later @object.update(object_params) # dont forget validation check end private def object_params params.require(:object).permit(:permitted_1, :permitted_2, :reason) end
在这种情况下,添加更多可更新字段会更容易。