Есть ли способ сделать атрибуты Rails ActiveRecord частными?

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

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

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

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

Ответ 1

Джордини был в основном там

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

class YourModel < ActiveRecord::Base

  private

  def my_private_attribute
    self[:my_private_attribute]
  end

  def my_private_attribute=(val)
    write_attribute :my_private_attribute, val
  end

end

Ответ 2

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

class YourModel < ActiveRecord::Base

  attr_reader :attribute

  private

  attr_accessor :attribute


end

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

Ответ 3

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

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

Ответ 4

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

YourClass.send(:private, :your_method)

Ответ 5

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

object.should_not respond_to :attribute

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

UPDATE:

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

Class Class_name

  private :method_name
  protected :method_name_1
end

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

Ответ 6

Приведение значения private приводит к ошибке 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

Ответ 7

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

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