在 Rails 4 中如何使用 attr_accessible?
Posted
技术标签:
【中文标题】在 Rails 4 中如何使用 attr_accessible?【英文标题】:How is attr_accessible used in Rails 4? 【发布时间】:2013-06-26 14:50:11 【问题描述】:attr_accessible
似乎不再适用于我的模型。
在 Rails 4 中允许批量分配的方法是什么?
【问题讨论】:
【参考方案1】:Rails 4 现在使用 strong parameters。
现在在控制器中保护属性。这是一个例子:
class PeopleController < ApplicationController
def create
Person.create(person_params)
end
private
def person_params
params.require(:person).permit(:name, :age)
end
end
不再需要在模型中设置attr_accessible
。
处理accepts_nested_attributes_for
为了使用带有强参数的accepts_nested_attribute_for
,您需要指定哪些嵌套属性应列入白名单。
class Person
has_many :pets
accepts_nested_attributes_for :pets
end
class PeopleController < ApplicationController
def create
Person.create(person_params)
end
# ...
private
def person_params
params.require(:person).permit(:name, :age, pets_attributes: [:name, :category])
end
end
关键字是不言自明的,但以防万一,您可以找到有关强参数in the Rails Action Controller guide的更多信息。
注意:如果您仍想使用attr_accessible
,您需要将protected_attributes
添加到您的Gemfile
。否则,您将面临RuntimeError
。
【讨论】:
文档没有说attr_accessible
需要被删除。如果我们保留它会发生什么?
如果您不对 Gemfile 进行一些调整,将会出现错误。 RuntimeError in MicropostsController#index 'attr_accessible' is extracted out of Rails into a gem. Please use new recommended protection model for params(strong_parameters) or add 'protected_attributes' to your Gemfile to use old one.
很好的解释。然而,在实践中,这似乎使 Rails 从胖模型、瘦控制器等转向瘦模型,以及真正臃肿的控制器。你必须为每个实例编写所有这些东西,它读起来不太好,而且嵌套似乎很痛苦。模型系统中旧的 attr_accessible/attr_accessor 没有损坏,不需要修复。在这种情况下,一篇博文变得太受欢迎了。
您不必在控制器中处理允许的参数。事实上,这违反了单一责任原则。看看下面的博文edelpero.svbtle.com/strong-parameters-the-right-way
如此花哨且频繁更改的 API,再加上新发现的迂腐,在又一次痛苦的 Rails 升级中浪费了许多开发人员时间:-(【参考方案2】:
如果你更喜欢 attr_accessible,你也可以在 Rails 4 中使用它。 你应该像 gem 一样安装它:
gem 'protected_attributes'
之后,您可以像在 Rails 3 中一样在模型中使用 attr_accessible
另外,我认为这是最好的方法——使用表单对象来处理批量赋值,保存嵌套对象,你也可以这样使用 protected_attributes gem
class NestedForm
include ActiveModel::MassAssignmentSecurity
attr_accessible :name,
:telephone, as: :create_params
def create_objects(params)
SomeModel.new(sanitized_params(params, :create_params))
end
end
【讨论】:
当您使用“强参数”时,您会在控制器层过滤参数,我认为这并不是所有应用程序的最佳选择。对我来说,过滤参数的最佳方法是使用附加层。我们可以使用'protected_attributes' gem 来编写这一层【参考方案3】:Rails 5 的更新:
gem 'protected_attributes'
似乎不再起作用了。但是给:
gem 'protected_attributes_continued'
试一试。
【讨论】:
【参考方案4】:我们可以使用
params.require(:person).permit(:name, :age)
如果 person 是模型,您可以在方法 person_params 上传递此代码,并在 create 方法或 else 方法中使用 params[:person]
【讨论】:
【参考方案5】:1) 通过将这一行添加到应用程序的 Gemfile 中,更新 Devise 以便它可以处理 Rails 4.0:
gem 'devise', '3.0.0.rc'
然后执行:
$ bundle
2) 将 attr_accessible
的旧功能再次添加到 rails 4.0
尽量使用attr_accessible
,不要注释掉。
将此行添加到应用程序的 Gemfile:
gem 'protected_attributes'
然后执行:
$ bundle
【讨论】:
【参考方案6】:我不得不将 Rails 应用程序从 3.2 迁移到 6.1,所以即使 gem 'protected_attributes' 也不是一个选项。我很欣赏在控制器中使用 require().permit() 的参数,但我不想从模型中重新键入或剪切和粘贴所有这些属性,所以我决定改用这个初始化代码(放在一个文件中)在配置/初始化程序中):
# fix attr_accessible in an initializer
# wrap ActionController::Parameters code in singleton method defined
# from attr_accessible so controller code can call class method
# to get permitted parameter list
# e.g. model: class A < ActiveRecord::Base,
# controller calls A.permit_attr(params)
# lots simpler than moving all attr_accessible definitions to controllers
# bug: fails if more than one attr_accessible statement
def (ActiveRecord::Base).attr_accessible *fields
puts "attr_accessible:"+self.name+":permitted_params fields=#fields.inspect"
define_singleton_method("permit_attr") |params|
# may have subclasses where attr_accessible is in superclass
# thus must require by subclass name so should calculate require at runtime
rq = self.name.downcase.to_sym
puts "...permit_attr:self=#rq permit(#fields.inspect)"
params.require(rq).permit(fields)
end
为了防止出现多个 attr_accessible 声明,在定义方法之前,添加
raise "error: model can only have one attr_accessible declaration" if defined? permit_attr
【讨论】:
以上是关于在 Rails 4 中如何使用 attr_accessible?的主要内容,如果未能解决你的问题,请参考以下文章
Rails 4:如何在 Rails 中使用 JQuery 禁用基于复选框值的文本字段
Rails 4 - 如何在 /config/environments/production.rb 文件中使用常量?