Есть ли способ сделать атрибуты 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/