Есть ли способ сделать атрибуты Rails ActiveRecord закрытыми? - PullRequest
32 голосов
/ 22 сентября 2010

По умолчанию ActiveRecord берет все поля из соответствующей таблицы базы данных и создает открытые атрибуты для всех них.

Я думаю, что разумно * не делать открытыми все атрибуты в модели. Более того, раскрытие атрибутов, предназначенных для внутреннего использования, затрудняет интерфейс модели и нарушает принцип инкапсуляции.

Итак, есть ли способ сделать некоторые атрибуты буквально private?

Или, может быть, мне стоит перейти на какой-нибудь другой ORM?

Ответы [ 7 ]

32 голосов
/ 22 сентября 2010

Джордини прошел большую часть пути

Большая часть active_record происходит в method_missing.Если вы определите метод заранее, он не будет вызывать method_missing для этого метода, а будет использовать ваш вместо (эффективно перезаписывая, но не совсем)

5 голосов
/ 17 августа 2011

Наткнулся на это недавно.Если вы хотите, чтобы частное письмо и чтение и публичное чтение было примерно таким,

class YourModel < ActiveRecord::Base

  attr_reader :attribute

  private

  attr_accessor :attribute


end

, мне кажется, это хорошо работает.Вы можете поиграться с attr_reader, attr_writer и attr_accessor, чтобы решить, что должно быть выставлено, а что должно быть приватным.

5 голосов
/ 22 сентября 2010

ну, вы всегда можете переопределить методы ...

class YourModel < ActiveRecord::Base

  private

  def my_private_attribute
    self[:my_private_attribute]
  end

  def my_private_attribute=(val)
    self[:my_private_attribute] = val
  end

end
1 голос
/ 15 января 2013

Для меня методы из Otto и jordinl работают нормально и делают rspec для объекта класса для передачи:

object.should_not respond_to :attribute

Но когда я использую метод jordinl, у меня появляется сообщение об отказе от записи в базу данныхнапрямую, но вместо этого используйте attr_writer.

ОБНОВЛЕНИЕ:

Но действительно «правильный» метод сделать это оказывается простым.Спасибо Младену Яблановичу и Кристоферу Крейцигу отсюда .Чтобы сделать предопределенный метод частным или защищенным ... просто переопределите его:

Class Class_name

  private :method_name
  protected :method_name_1
end

Что важно, вам не нужно переписывать ранее определенную логику метода.

1 голос
/ 22 сентября 2010

Вы можете сделать существующий метод приватным:

YourClass.send(:private, :your_method)
0 голосов
/ 11 ноября 2017

Я не думаю, что есть 100% надежный способ сделать это. Также стоит проверить самые популярные способы доступа к атрибутам:

http://www.davidverhasselt.com/set-attributes-in-activerecord/

0 голосов
/ 26 ноября 2012

При частной установке параметра генерируется ошибка ActiveRecord.

Я поместил код контроля доступа в перезаписанный метод публичного сеттера, проверив вызывающего:

def my_private_attribute=(val)
  if (caller.first.include?('active_record/base.rb') || caller.first.include?('app/models/myclass.rb'))
    self[:my_private_attribute] = val
  else
     raise Exception.new("Cannot set read-only attribute.")
  end
end
...