Разница между attr_accessor и attr_accessible - PullRequest
232 голосов
/ 29 июня 2010

В Rails, в чем разница между attr_accessor и attr_accessible?Насколько я понимаю, использование attr_accessor используется для создания методов получения и установки для этой переменной, так что мы можем получить доступ к переменной, как Object.variable или Object.variable = some_value.

Я читал, что attr_accessible делает этоконкретная переменная, доступная внешнему миру.Может кто-нибудь, пожалуйста, скажите мне, в чем разница

Ответы [ 6 ]

255 голосов
/ 29 июня 2010

attr_accessor - это метод 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 белых списков тех вещей, которые могут быть назначены массово.

173 голосов
/ 17 октября 2012

Многие в этой теме и в Google очень хорошо объясняют, что attr_accessible задает белый список атрибутов, которые разрешено обновлять массово ( все атрибуты объектной модели одновременно) ) Это главным образом (и только) для защиты вашего приложения от пиратского эксплойта «Массовое назначение».

Это объясняется здесь на официальном документе Rails: Массовое назначение

attr_accessor - это код ruby ​​для (быстрого) создания методов установки и получения в классе.Вот и все.

Теперь в качестве объяснения не хватает того, что когда вы каким-либо образом создаете связь между моделью (Rails) и таблицей базы данных, вам НИКОГДА, НИКОГДА, НИКОГДА не потребуется attr_accessor в вашей модели, чтобысоздавать сеттеры и геттеры, чтобы иметь возможность изменять записи вашей таблицы.

Это потому, что ваша модель наследует все методы из класса ActiveRecord::Base, который уже определяет основные средства доступа CRUD (Create, Read, Update, Delete) для тебя.Это объясняется в официальном документе здесь Модель Rails и здесь Перезапись доступа по умолчанию (прокрутите вниз до главы «Перезапись доступа по умолчанию»)

Скажите, например, что:у нас есть таблица базы данных с именем «users», которая содержит три столбца «firstname», «lastname» и «role»:

инструкции SQL:

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

Я предположил, что вы установили опциюconfig.active_record.whitelist_attributes = true в вашем config / environment / production.rb для защиты вашего приложения от эксплойта Mass назначений.Это объясняется здесь: 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

Теперь, чтобы упростить вашу жизнь, вы не хотите создавать сложный контроллер для вашей модели User.Таким образом, вы будете использовать специальный метод 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

Вы не сделалине добавляйте атрибуты "role" в список attr_accessible, потому что вы не позволяете своим пользователям самим устанавливать свою роль (например, admin).Вы делаете это самостоятельно в другом специальном административном представлении.

Хотя в вашем пользовательском представлении не отображается поле «роль», пират может легко отправить HTTP-запрос POST, включающий «роль» в хэш параметров.Отсутствующий атрибут "role" в 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

Таким образом, вы сможете грамотно использовать *Атрибут 1070 * где-нибудь в вашем контроллере для отправки электронной почты или выполнения любых действий.

ActiveRecord не сохранит атрибут "peekaboo" в вашей таблице, когда вы выполните user.save, потому что она не видитлюбой столбец, соответствующий этому имени в ее модели.

48 голосов
/ 29 июня 2010

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 - безопасности массовых назначений.

18 голосов
/ 17 августа 2012

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 обеспечивает доступ как к методам получения, так и к методам установки.

Таким образом, модифицированный код как показано ниже

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

attr_accessible позволяет перечислить все столбцы, которые вы хотите разрешить массовое назначение. Противоположностью этому является attr_protected, что означает, что в этом поле я НЕ хочу, чтобы кому-либо было разрешено массовое назначение. Скорее всего, это будет поле в вашей базе данных, с которым вы не хотите, чтобы кто-то возился. Как поле состояния или тому подобное.

2 голосов
/ 31 марта 2016

Краткий и краткий обзор различий:

attr_accessor - это простой способ создания средств чтения и записи в твой класс. Он используется, когда у вас нет столбца в вашей базе данных, но все же хочу показать поле в ваших формах. Это поле “virtual attribute” в модели Rails.

виртуальный атрибут - атрибут, не соответствующий столбцу в базе данных.

attr_accessible используется для определения доступных атрибутов вашими методами контроллера делает свойство доступным для массовое назначение .. Это позволит только доступ к атрибутам, которые вы уточняйте, отказывая в остальном.

2 голосов
/ 18 февраля 2014

В двух словах:

attr_accessor - это метод getter, setter. тогда как attr_accessible означает, что определенный атрибут доступен или нет. вот и все.


Я хотел бы добавить, что мы должны использовать Сильный параметр вместо attr_accessible для защиты от массового присвоения.

Ура!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...