Ruby-on-rails attr_accessor 和 attr_accessible 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3136420/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:50:12  来源:igfitidea点击:

Difference between attr_accessor and attr_accessible

ruby-on-railsruby

提问by felix

In Rails, what is the difference between attr_accessorand attr_accessible? From my understanding, using attr_accessoris used to create getter and setter methods for that variable, so that we can access the variable like Object.variableor Object.variable = some_value.

在 Rails 中,attr_accessor和之间有什么区别attr_accessible?根据我的理解, usingattr_accessor用于为该变量创建 getter 和 setter 方法,以便我们可以像Object.variableor那样访问变量Object.variable = some_value

I read that attr_accessiblemakes that specific variable accessible to the outside world. Can someone please tell me whats the difference

我读到这attr_accessible使得外部世界可以访问该特定变量。有人可以告诉我有什么区别吗

回答by Paul Rubel

attr_accessoris a Ruby method that makes a getter and a setter. attr_accessibleis a Rails method that allows you to pass in values to a mass assignment: new(attrs)or update_attributes(attrs).

attr_accessor是一个 Ruby 方法,它生成一个 getter 和一个 setter。attr_accessible是一个 Rails 方法,它允许您将值传递给大量赋值:new(attrs)update_attributes(attrs).

Here's a mass assignment:

这是一个批量分配:

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

You can imagine that the order might also have a discount code, say :price_off. If you don't tag :price_offas attr_accessibleyou stop malicious code from being able to do like so:

您可以想象订单也可能有折扣代码,例如:price_off。如果你不标记:price_offattr_accessible您无法做到像这样阻止恶意代码:

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

Even if your form doesn't have a field for :price_off, if it's in your model it's available by default. This means a crafted POST could still set it. Using attr_accessiblewhite lists those things that can be mass assigned.

即使您的表单没有用于 的字段:price_off,如果它在您的模型中,默认情况下它也是可用的。这意味着精心制作的 POST 仍然可以设置它。使用attr_accessible白名单列出那些可以批量分配的东西。

回答by Douglas

Many people on this thread and on google explain very well that attr_accessiblespecifies a whitelist of attributes that are allowed to be updated in bulk (all the attributes of an object model together at the same time) This is mainly (and only) to protect your application from "Mass assignment" pirate exploit.

这个线程和谷歌上的很多人都解释得很好,attr_accessible指定了一个允许批量更新的属性白名单(对象模型的所有属性同时在一起)这主要是(并且仅)保护您的应用程序来自“大规模分配”海盗利用。

This is explained here on the official Rails doc : Mass Assignment

这在官方 Rails 文档中进行了解释:批量分配

attr_accessoris a ruby code to (quickly) create setter and getter methods in a Class. That's all.

attr_accessor是用于(快速)在类中创建 setter 和 getter 方法的 ruby​​ 代码。就这样。

Now, what is missing as an explanation is that when you create somehow a link between a (Rails) model with a database table, you NEVER, NEVER, NEVER need attr_accessorin your model to create setters and getters in order to be able to modify your table's records.

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

This is because your model inherits all methods from the ActiveRecord::BaseClass, which already defines basic CRUD accessors (Create, Read, Update, Delete) for you. This is explained on the offical doc here Rails Modeland here Overwriting default accessor(scroll down to the chapter "Overwrite default accessor")

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

Say for instance that: we have a database table called "users" that contains three columns "firstname", "lastname" and "role" :

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

SQL instructions :

SQL指令:

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

I assumed that you set the option config.active_record.whitelist_attributes = truein your config/environment/production.rb to protect your application from Mass assignment exploit. This is explained here : Mass Assignment

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

Your Rails model will perfectly work with the Model here below :

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

class User < ActiveRecord::Base

end

However you will need to update each attribute of user separately in your controller for your form's View to work :

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

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

Now to ease your life, you don't want to make a complicated controller for your User model. So you will use the attr_accessiblespecial method in your Class model :

现在为了让您的生活更轻松,您不想为您的 User 模型制作一个复杂的控制器。因此,您将attr_accessible在 Class 模型中使用特殊方法:

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname

end

So you can use the "highway" (mass assignment) to update :

因此,您可以使用“高速公路”(批量分配)来更新:

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

You didn't add the "role" attributes to the attr_accessiblelist because you don't let your users set their role by themselves (like admin). You do this yourself on another special admin View.

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

Though your user view doesn't show a "role" field, a pirate could easily send a HTTP POST request that include "role" in the params hash. The missing "role" attribute on the attr_accessibleis to protect your application from that.

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

You can still modify your user.role attribute on its own like below, but not with all attributes together.

您仍然可以像下面那样自行修改 user.role 属性,但不能同时修改所有属性。

@user.role = DEFAULT_ROLE

Why the hell would you use the attr_accessor?

你为什么要使用attr_accessor

Well, this would be in the case that your user-form shows a field that doesn't exist in your users table as a column.

好吧,这可能是在您的用户表单将用户表中不存在的字段显示为列的情况下。

For instance, say your user view shows a "please-tell-the-admin-that-I'm-in-here" field. You don't want to store this info in your table. You just want that Rails send you an e-mail warning you that one "crazy" ;-) user has subscribed.

例如,假设您的用户视图显示“please-tell-the-admin-that-I'm-in-here”字段。您不想将此信息存储在您的表中。您只希望 Rails 向您发送一封电子邮件,警告您有一个“疯子”;-) 用户已订阅。

To be able to make use of this info you need to store it temporarily somewhere. What more easy than recover it in a user.peekabooattribute ?

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

So you add this field to your model :

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

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname
  attr_accessor :peekaboo

end

So you will be able to make an educated use of the user.peekabooattribute somewhere in your controller to send an e-mail or do whatever you want.

因此,您将能够充分利用user.peekaboo控制器中某处的属性来发送电子邮件或做任何您想做的事情。

ActiveRecord will not save the "peekaboo" attribute in your table when you do a user.savebecause she don't see any column matching this name in her model.

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

回答by Joshua Cheek

attr_accessoris a Ruby method that gives you setter and getter methods to an instance variable of the same name. So it is equivalent to

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

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

attr_accessibleis a Rails method that determines what variables can be set in a mass assignment.

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

When you submit a form, and you have something like MyModel.new params[:my_model]then you want to have a little bit more control, so that people can't submit things that you don't want them to.

当您提交表单时,MyModel.new params[:my_model]您希望拥有更多控制权,以便人们无法提交您不希望他们提交的内容。

You might do attr_accessible :emailso that when someone updates their account, they can change their email address. But you wouldn't do attr_accessible :email, :salarybecause then a person could set their salary through a form submission. In other words, they could hack their way to a raise.

您可以这样做,attr_accessible :email以便当有人更新他们的帐户时,他们可以更改他们的电子邮件地址。但是你不会这样做,attr_accessible :email, :salary因为这样一个人可以通过提交表单来设置他们的薪水。换句话说,他们可以通过黑客手段获得加薪。

That kind of information needs to be explicitly handled. Just removing it from the form isn't enough. Someone could go in with firebug and add the element into the form to submit a salary field. They could use the built in curl to submit a new salary to the controller update method, they could create a script that submits a post with that information.

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

So attr_accessoris about creating methods to store variables, and attr_accessibleis about the security of mass assignments.

所以,attr_accessor是关于创造方法来存储变量,attr_accessible是关于质量分配的安全性。

回答by shrikant1712

attr_accessoris ruby code and is used when you do not have a column in your database, but still want to show a field in your forms. The only way to allow this is to attr_accessor :fieldnameand you can use this field in your View, or model, if you wanted, but mostly in your View.

attr_accessor是 ruby​​ 代码,当您的数据库中没有列但仍想在表单中显示一个字段时使用。允许这样做的唯一方法是attr_accessor :fieldname,如果需要,您可以在您的视图或模型中使用此字段,但主要是在您的视图中。

Let's consider the following example

让我们考虑以下示例

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

Here we have used attr_reader(readable attribute) and attr_writer(writable attribute) for accessing purpose. But we can achieve the same functionality using attr_accessor. In short, attr_accessor provides access to both getter and setter methods.

这里我们使用了attr_reader可读属性)和attr_writer可写属性)作为访问目的。但是我们可以使用attr_accessor. 简而言之,attr_accessor 提供对 getter 和 setter 方法的访问。

So modified code is as below

所以修改后的代码如下

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

attr_accessibleallows you to list all the columns you want to allow Mass Assignment. The opposite of this is attr_protectedwhich means this field I do NOT want anyone to be allowed to Mass Assign to. More than likely it is going to be a field in your database that you don't want anyone monkeying around with. Like a status field, or the like.

attr_accessible允许您列出要允许批量分配的所有列。与此相反,这attr_protected意味着我不希望任何人被允许批量分配到该字段。它很可能会成为您数据库中的一个字段,您不希望任何人与它胡闹。像状态字段等。

回答by Manish Shrivastava

In two words:

用两个字:

attr_accessoris getter, settermethod. whereas attr_accessibleis to say that particular attribute is accessible or not. that's it.

attr_accessorgettersetter方法。而attr_accessible就是说特定属性是否可访问。就是这样。



I wish to add we should use Strong parameterinstead of attr_accessibleto protect from mass asignment.

我想补充一点,我们应该使用强参数而不是attr_accessible防止大规模分配。

Cheers!

干杯!

回答by Muhammad Yawar Ali

A quick & concise difference overview :

快速简洁的差异概述:

attr_accessoris an easy way to create read and write accessors in your class. It is used when you do not have a column in your database, but still want to show a field in your forms. This field is a “virtual attribute”in a Rails model.

virtual attribute– an attribute not corresponding to a column in the database.

attr_accessibleis used to identify attributes that are accessible by your controller methods makes a property available for mass-assignment.. It will only allow access to the attributes that you specify, denying the rest.

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

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

attr_accessible用于标识可由您的控制器方法访问的属性,使属性可用于批量分配。它只允许访问您指定的属性,拒绝其余的属性。