attr_accessor和attr_accessible之间的区别

时间:2010-06-28 21:52:30

标签: ruby-on-rails ruby

在Rails中,attr_accessorattr_accessible之间有什么区别?根据我的理解,使用attr_accessor用于为该变量创建getter和setter方法,以便我们可以访问Object.variableObject.variable = some_value等变量。

我读到attr_accessible使得该特定变量可供外界使用。 有人可以告诉我这是什么区别

6 个答案:

答案 0 :(得分:254)

attr_accessor是一个生成getter和setter的Ruby方法。 attr_accessible是一种Rails方法,可让您将值传入质量分配:new(attrs)update_attributes(attrs)

这是一个质量任务:

Order.new({ :type => 'Corn', :quantity => 6 })

您可以想象订单可能还有折扣代码,例如:price_off。如果您未将:price_off标记为attr_accessible,则会阻止恶意代码执行此操作:

Order.new({ :type => 'Corn', :quantity => 6, :price_off => 30 })

即使您的表单没有:price_off的字段,如果它在您的模型中,则默认情况下可用。这意味着精心设计的POST仍然可以设置它。使用attr_accessible白色列出可以批量分配的内容。

答案 1 :(得分:171)

此线程和Google上的很多人都非常清楚地说明attr_accessible指定了允许批量更新的属性列表(对象模型的所有属性同时在一起< /强>) 这主要是(并且仅)保护您的应用程序免受“大规模分配”盗版攻击。

这在官方Rails文档中解释:Mass Assignment

attr_accessor是一个ruby代码,用于(快速)在Class中创建setter和getter方法。就是这样。

现在,作为解释的缺失是,当您以某种方式创建(Rails)模型与数据库表之间的链接时,您永远不会在模型中需要attr_accessor来创建setter和getters为了能够修改表格的记录。

这是因为您的模型继承了ActiveRecord::Base类的所有方法,它已经为您定义了基本的CRUD访问器(创建,读取,更新,删除)。 这在官方文档Rails Model和此处Overwriting default accessor上进行了解释(向下滚动到“覆盖默认访问者”一章)

比如说:我们有一个名为“users”的数据库表,其中包含三列“firstname”,“lastname”和“role”:

SQL指令:

CREATE TABLE users (
  firstname string,
  lastname string
  role string
);

我假设您在config / environment / production.rb中设置了选项config.active_record.whitelist_attributes = true,以保护您的应用程序免受批量分配攻击。这在此解释:Mass Assignment

您的Rails模型将完全适用于以下模型:

class User < ActiveRecord::Base

end

但是,您需要在控制器中单独更新用户的每个属性,以使表单的视图正常工作:

def update
    @user = User.find_by_id(params[:id])
    @user.firstname = params[:user][:firstname]
    @user.lastname = params[:user][:lastname]

    if @user.save
        # Use of I18 internationalization t method for the flash message
        flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
    end

    respond_with(@user)
end

现在为了减轻您的生活,您不希望为您的用户模型制作复杂的控制器。 因此,您将在类模型中使用attr_accessible特殊方法:

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname

end

所以你可以使用“高速公路”(质量分配)来更新:

def update
    @user = User.find_by_id(params[:id])

    if @user.update_attributes(params[:user])
        # Use of I18 internationlization t method for the flash message
        flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
    end

    respond_with(@user)
end

您没有将“角色”属性添加到attr_accessible列表,因为您不允许用户自行设置角色(例如管理员)。您可以在另一个特殊的管理视图上自行完成此操作。

虽然您的用户视图未显示“角色”字段,但盗版者可以轻松地在params哈希中发送包含“角色”的HTTP POST请求。 attr_accessible上缺少的“角色”属性是为了保护您的应用程序。

您仍然可以自己修改user.role属性,如下所示,但不能同时修改所有属性。

@user.role = DEFAULT_ROLE

为什么你会使用attr_accessor

嗯,如果你的用户表单显示一个不在你的用户表中作为列的字段。

例如,假设您的用户视图显示“请告诉管理员 - 我在这里”字段。 您不希望将此信息存储在表中。你只是希望Rails向你发送一封电子邮件警告你一个“疯狂”;-)用户订阅了。

为了能够使用此信息,您需要暂时将其存储在某处。 还有什么比在user.peekaboo属性中恢复更容易?

因此,您将此字段添加到模型中:

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname
  attr_accessor :peekaboo

end

因此,您可以在控制器中的某个地方有条不紊地使用user.peekaboo属性来发送电子邮件或做任何您想做的事情。

当您执行user.save时,ActiveRecord不会在表格中保存“peekaboo”属性,因为她在模型中看不到任何与此名称匹配的列。

答案 2 :(得分:47)

attr_accessor是一个Ruby方法,它为您提供相同名称的实例变量的setter和getter方法。所以它相当于

class MyModel
  def my_variable
    @my_variable
  end
  def my_variable=(value)
    @my_variable = value
  end
end

attr_accessible是一个Rails方法,用于确定可以在批量赋值中设置哪些变量。

当您提交表单时,如果有MyModel.new params[:my_model]之类的内容,那么您希望获得更多控制权,以便人们无法提交您不希望他们提供的内容。

您可以执行attr_accessible :email,以便当有人更新其帐户时,他们可以更改自己的电子邮件地址。但你不会attr_accessible :email, :salary因为那时一个人可以通过表格提交来设定他们的工资。换句话说,他们可以破解他们的加薪方式。

需要明确处理这类信息。只是从表单中删除它是不够的。有人可以使用firebug并将元素添加到表单中以提交薪水字段。他们可以使用内置的curl向控制器更新方法提交新工资,他们可以创建一个脚本来提交包含该信息的帖子。

所以attr_accessor是关于创建存储变量的方法,attr_accessible是关于大规模分配的安全性。

答案 3 :(得分:18)

attr_accessor是ruby代码,当您在数据库中没有列但仍希望在表单中显示字段时使用。允许此操作的唯一方法是attr_accessor :fieldname,如果您愿意,可以在视图或模型中使用此字段,但主要在您的视图中。

让我们考虑以下示例

class Address
    attr_reader :street
    attr_writer :street  
    def initialize
        @street = ""
    end
end

此处,我们使用attr_reader可读属性)和attr_writer可写属性)进行访问。但我们可以使用attr_accessor实现相同的功能。简而言之, attr_accessor提供对getter和setter方法的访问。

所以修改后的代码如下

class Address
    attr_accessor :street  
    def initialize
        @street = ""
    end
end

attr_accessible允许您列出要允许批量分配的所有列。与此相反的是attr_protected,这意味着这个字段我不希望任何人被允许进行质量分配。很可能它会成为你数据库中的一个字段,你不希望任何人在一起工作。像状态字段一样。

答案 4 :(得分:2)

用两个词来说:

attr_accessorgettersetter方法。 而attr_accessible则表示特定属性是否可访问。而已。


我希望补充一点,我们应该使用Strong parameter而不是attr_accessible来防止大规模投降。

干杯!

答案 5 :(得分:2)

快速&amp;简明差异概述:

  

attr_accessor是一种创建读写访问器的简便方法   你的班。当您的数据库中没有列时使用它,   但仍想在表单中显示一个字段。这个字段是   在Rails模型中“virtual attribute”

     

虚拟属性 - 与数据库中的列不对应的属性。

     

attr_accessible用于标识可访问的属性   通过您的控制器方法使属性可用   mass-assignment ..它只允许访问你的属性   指定,否认其余部分。