Ruby on rails attr\u访问器和attr\u可访问之间的差异

Ruby on rails attr\u访问器和attr\u可访问之间的差异,ruby-on-rails,ruby,Ruby On Rails,Ruby,在Rails中,attr\u accessor和attr\u accessible之间有什么区别?据我所知,使用attr\u accessor可以为该变量创建getter和setter方法,这样我们就可以访问变量,如Object.variable或Object.variable=some\u value 我读到attr\u accessible使外部世界可以访问特定变量。 有人能告诉我有什么区别吗?attr\u accessor是一种Ruby方法,它可以生成getter和setterattr\u

在Rails中,
attr\u accessor
attr\u accessible
之间有什么区别?据我所知,使用
attr\u accessor
可以为该变量创建getter和setter方法,这样我们就可以访问变量,如
Object.variable
Object.variable=some\u value

我读到
attr\u accessible
使外部世界可以访问特定变量。
有人能告诉我有什么区别吗?attr\u accessor是一种Ruby方法,它可以生成getter和setter
attr\u accessible
是一种Rails方法,允许您将值传递给批量分配:
new(attrs)
update\u attributes(attrs)

这是一个集体作业:

Order.new({:type=>Corn',:quantity=>6})
您可以想象订单可能也有折扣代码,比如
:price\u off
。如果您不将
:price_off
标记为
attr_accessible
您可以阻止恶意代码这样做:

Order.new({:type=>Corn',:quantity=>6,:price\u off=>30})

即使您的表单没有用于
:price\u off
的字段,如果它在您的模型中,默认情况下也是可用的。这意味着一个精心制作的帖子仍然可以设置它。使用
attr\u accessible
white列出了那些可以批量分配的内容。

attr\u accessor
是一种Ruby方法,它为相同名称的实例变量提供setter和getter方法。所以它相当于

class MyModel
  def my_variable
    @my_variable
  end
  def my_variable=(value)
    @my_variable = value
  end
end
attr\u accessible
是一种Rails方法,用于确定在批量分配中可以设置哪些变量

当你提交一个表单时,你有一些类似于
MyModel.new参数[:my_model]
的东西,然后你想有更多的控制权,这样人们就不能提交你不希望他们提交的东西

您可以执行
attr\u accessible:email
,这样当某人更新其帐户时,他们可以更改其电子邮件地址。但是你不会做
attr\u accessible:email,:salary
,因为这样一个人就可以通过表单提交来设置他们的工资。换言之,他们可以通过黑客手段获得加薪

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


因此,
attr\u accessor
是关于创建存储变量的方法,而
attr\u accessible
是关于批量赋值的安全性。

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

让我们考虑下面的例子

class Address
    attr_reader :street
    attr_writer :street  
    def initialize
        @street = ""
    end
end
这里我们使用了
attr\u reader
(可读属性)和
attr\u writer
(可写属性)进行访问。但是我们可以使用
attr\u accessor
实现相同的功能。简而言之,attr\u访问器提供对getter和setter方法的访问。

所以修改后的代码如下所示

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

attr\u accessible
允许您列出要允许批量分配的所有列。与此相反的是
attr_protected
,这意味着我不希望任何人被允许对该字段进行批量分配。更有可能的是,它将是数据库中的一个字段,您不希望任何人胡闹。类似于状态字段等。

此线程和google上的许多人都很好地解释说,
attr\u accessible
指定了一个允许批量更新的属性白名单(对象模型的所有属性同时一起更新) 这主要(也是唯一)是为了保护您的应用程序免受“大规模分配”盗版攻击

官方Rails文档对此进行了解释:


attr\u accessor
是一个ruby代码,用于(快速)在类中创建setter和getter方法。就这些

现在,缺少的解释是,当您以某种方式在(Rails)模型和数据库表之间创建链接时,您永远、永远、永远不需要在模型中创建setter和getter来修改表的记录

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

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

SQL说明:

CREATE TABLE users (
  firstname string,
  lastname string
  role string
);
我假设您在config/environment/production.rb中设置选项
config.active\u record.whitelist\u attributes=true
,以保护应用程序免受大规模分配攻击。这里解释如下:

您的Rails模型将与以下模型完美配合:

class User < ActiveRecord::Base

end
现在,为了简化您的生活,您不想为您的用户模型制作复杂的控制器。 因此,您将在类模型中使用
attr\u accessible
特殊方法:

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname

end
您没有将“角色”属性添加到
attr\u accessible
列表中,因为您不允许用户自己设置角色(如管理员)。您可以在另一个特殊的管理视图中自己执行此操作

虽然您的用户视图没有显示“角色”字段,但盗版者可以很容易地发送一个HTTP POST请求,该请求在参数散列中包含“角色”。
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
@user.role = DEFAULT_ROLE
class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname
  attr_accessor :peekaboo

end