在rails控制台中创建实例时,Rails 4强参数失败
可能在这里做一些蠢事,但这是我的基本cookie切割器类:
class League < ActiveRecord::Base private def league_params params.require(:full_name).permit! end end
在创建联盟的新实例时:
2.0.0-p0 :001 > l = League.new(full_name: 'foo', short_name: 'bar') WARNING: Can't mass-assign protected attributes for League: full_name, short_name
我到底错在了什么? 这是一个Rails 4.0.0.beta1 build + Ruby 2.0
**更新**
我现在意识到强大的参数现在在Controller中实施而不是在模型中。 最初的问题仍然存在。 如果在控制器级别允许它们,如果我在Rails控制台中创建实例,如何正确地将属性列入白名单? 在这种情况下我是否还需要使用attr_accessible
,从而完全复制哪些强参数试图“修复”?
两件事情。 league_params
定义在控制器中,而不是模型。 并且params.require()
应该包含参数中需要出现的模型的名称,而不是属性。 属性存在检查仍应在模型validation中。 在使用permit!
之前,请确保您确实希望允许访问联盟模型中的所有属性permit!
。 所以,它应该是这样的:
class LeaguesController < ApplicationController private def league_params params.require(:league).permit! end end
更新:
是的,如果您希望在直接访问模型时限制属性,则需要切换回使用模型中的attr_accessible
。 该function已移至此gem: https : //github.com/rails/protected_attributes 。
我认为如果您直接在控制台中使用模型,则不需要保护属性,因为您确切知道输入的内容。 由于控制台可以完全访问您的应用程序,因此管理整个数据库与恶意分配属性一样容易。
存在强参数和attr_accessible的基本安全原因是模型中存在某些不应允许更改的属性,除非它是您的代码的明确意图。
他们之间的细微差别是他们完成工作的透视forms。
StrongParameters专注于用例:可以对每个控制器的操作进行微调,以允许或禁止某些参数,同时考虑任何条件。 总灵活性。
attr_accessible采用不同的视角。 它不是专注于用例,而是专注于角色。 因此,例如,取决于用户的角色,可以改变或不改变某些属性。
使用StrongParameters的方法是在param哈希上应用require
和permit
关键字。
require
状态指出密钥必须存在于params散列中。 如果没有这样的密钥,则require
将引发exception。
permit
表示允许使用字段。 任何不允许的密钥都将从哈希中删除,因此不会通过批量分配传递给模型。
模型
class League attr_protected :final_price # Nobody can mass-assign the final price attr_accessible :winner_name, :as => :jury end
和控制器
class LeaguesController < ApplicationController
这两个动作使用StrongParameters
# A common user can create a league def create league = League.new(league_params) league.final_price = 1000 league.save redirect_to(league) end # But only the admin can publish a league def publish_league league = League.find(params[:id] league.update_attributes(league_params_as_admin) end
这个使用attr_accessible
def publish_the_winner league = League.find(params[:id] # We would expect the current_user.role to return :jury. league.assign_attributes(params[:league], :as => current_user.role) end private def league_params params.require(:league).permit(:name) end def league_params_as_admin params.require(:league).permit(:name, :status) end end
在我的经验中:
使用强参数的灵活性来微调可以在每个控制器中批量分配的属性。
使用无处不在的attr_accesible来确保无论如何都无法对某些属性进行大规模分配。 例如,在Resque Task中,您可以将用户输入作为参数传递。 您将检查是否使用attr_accesible对某些属性进行了质量分配。
更多信息:
http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html
即使您正在运行Rails 4,白名单似乎仍处于活动状态。您是否从Rails 3应用程序升级到Rails 4? 你在config/application.rb
有这个吗?
config.active_record.whitelist_attributes = true
仔细检查所有型号上的强参数是否有效。 如果是,则可以将此设置更改为false
。
另外,请仔细检查模型中是否存在attr_accessible
。
如果您直接调用模型,那么它将回避您在控制器中实现的任何逻辑。
但是,您可以从控制台调用控制器,然后实现的StrongParameters将生效。
请参阅如何在Rails中从控制台调用控制器/视图方法?