Разница между attr_accessor и attr_accessible

212

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

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

  • 4
    Вы правы, что attr_accessor используется для генерации методов получения и установки. Пожалуйста, смотрите мой ответ на предыдущий вопрос для довольно полного объяснения attr_accessible : stackoverflow.com/questions/2652907/… затем обновите свой вопрос, если после этого вам понадобятся какие-либо другие конкретные детали.
  • 2
    attr_accessible больше не поддерживается в Rails 4, если вы не используете гем protected_attributes, как указано в главном ответе на stackoverflow.com/questions/17371334/… (июль 2014 г.)
Теги:

6 ответов

233
Лучший ответ

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

  • 2
    Почему в документации по Rails нет attr_accessible ? api.rubyonrails.org
  • 18
    Похоже, у Rails4 появился новый способ делать вещи. Смотрите этот ответ: stackoverflow.com/questions/17371334/…
Показать ещё 1 комментарий
176

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

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

attr_accessor - это рубиновый код (быстро), создающий методы setter и getter в классе. Это все.

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

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

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

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

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

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

Модель 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

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

Хотя в вашем представлении пользователя не отображается поле "роль", пират может легко отправить запрос HTTP POST, который включает "роль" в хеше params. Отсутствующий атрибут "role" на attr_accessible предназначен для защиты вашего приложения от этого.

Вы все равно можете изменить свой атрибут user.role самостоятельно, как показано ниже, но не со всеми атрибутами.

@user.role = DEFAULT_ROLE

Почему, черт возьми, вы использовали бы attr_accessor?

Ну, это будет в том случае, если ваша пользовательская форма показывает поле, которое не существует в вашей таблице пользователей в качестве столбца.

Например, скажем, в вашем представлении пользователя отображается поле "please-tell-the-admin-that-I'm-in-here". Вы не хотите хранить эту информацию в своей таблице. Вы просто хотите, чтобы Rails отправил вам электронное письмо, предупреждающее вас о том, что пользователь "сумасшедший";-) подписался.

Чтобы иметь возможность использовать эту информацию, вам нужно временно ее хранить. Что проще, чем восстановить его в атрибуте user.peekaboo?

Итак, вы добавляете это поле в свою модель:

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname
  attr_accessor :peekaboo

end

Таким образом, вы сможете сделать образованное использование атрибута user.peekaboo где-то в вашем контроллере, чтобы отправить электронное письмо или сделать все, что захотите.

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

49

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

Итак, attr_accessor рассказывает о создании методов для хранения переменных, а attr_accessible - о безопасности массовых присвоений.

  • 2
    У вас есть опечатка, после блока кода должно быть указано attr_accesible
  • 0
    Отлично пишите, мне нравится пример класса. Дополнительные (поддельные) бонусные баллы за включение объяснения :as !
Показать ещё 1 комментарий
16

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
    Итак, вы говорите, что если я создал поля в миграции, а затем сделал их доступными с помощью attr_accessible, нет необходимости создавать геттер и сеттер? Но если поле отсутствует в базе данных, почему attr_accessible не действует как метод получения / установки? Если я добавлю строку «has_secure_password», то attr_accessible станет достаточным, чтобы позволить getter / setter: password и: password_confirmation, даже если их нет в базе данных. Очень смущенный ;)
2

Быстрый и краткий обзор различий:

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

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

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

2

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

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


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

Ура!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню