Различия между *, self. * И @* при ссылках на ассоциации/атрибуты в Ruby/Rails Модели/контроллеры
Предполагая модель Rails с постоянными/непостоянными атрибутами, какова наилучшая практика их ссылки? Если вы просматриваете общедоступный код, используются разные шаблоны.
Например, если у вас есть связь от одной модели к другой. В чем разница между использованием self.association_name и @association_name?. Какой предпочтительный способ?
То же, что и с ненастоящими атрибутами, определенными с помощью attr_accessor: attr в моделях. Вы можете ссылаться на них с обоими подходами: self.attr и @attr. Какой предпочтительный способ?
Ответы
Ответ 1
self.x
/self.x=y
всегда являются вызовами методов.
(self.x
- это просто сахар для self.__send__(:x)
и self.x = y
действительно просто сахар для self.__send__(:x=, y)
)
@x
, с другой стороны, относится только к переменной экземпляра .
Использование @x
не будет работать с AR-ассоциациями, поскольку AR определяет только x/x=
(которые являются методами) для его магической операции. (AR по существу просто "захватывает" намеренный доступ через эти методы и маршруты через свои собственные внутренние структуры данных, которые не связаны с любыми подобными именованными переменными экземпляра.)
attr_accessor
позволяет "получить доступ к обоим путям", потому что и только потому, что он использует переменную экземпляра с одинаковым именем при ее поддержке (она должна где-то хранят значение). Рассмотрим, что attr_accessor :x
эквивалентно:
def x; @x; end
def x= (y); @x = y; end
Счастливое кодирование.
Ответ 2
В большинстве случаев вы предпочитаете использовать attr
вместо @attr
. Это потому, что метод attr
часто устанавливает атрибуты, если он не существует.
Например, этот порядок модели:
model Order
have_many :items
def total
@total ||= items.collect(&:price).sum
end
def taxes
@taxes ||= total * 0.10
end
end
Эта модель работает vell, если бы я использовал @total
вместо total
в методе taxes
, то вычисление завершится неудачно, если я ранее не вызывал метод total
этого объекта.
Как указывает @pst, @association_name
не работает для объединения, вы должны использовать метод association_name
.
Также self.attr
следует использовать только для установки атрибута (вызов self.attr=
) при чтении значения, которое лучше использовать attr
, см. эта статья: когда используется модель self Rails