Различия между *, self.* И @* при ссылке на ассоциации / атрибуты в Ruby/Rails Models/Controllers

Предполагая, что модель Rails с постоянными / непостоянными атрибутами, какова лучшая практика при обращении к ним? Если вы посмотрите на общедоступный код, используются разные шаблоны.

Например, если у вас есть связь от одной модели к другой. В чем разница между использованием self.association_name и @association_name?, Какой способ предпочтительнее?

То же, что и с непостоянными атрибутами, определенными с помощью attr_accessor: attr в моделях. Вы можете ссылаться на них с обоими подходами, self.attr и @attr. Какой способ предпочтительнее?

2 ответа

Решение

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

Удачного кодирования.

Большую часть времени вы бы предпочли использовать attr вместо @attr, Это потому, что метод attr часто устанавливать атрибуты, если он не существует.

Например этот модельный заказ:

model Order
  have_many :items

  def total
    @total ||= items.collect(&:price).sum
  end

  def taxes
    @taxes ||= total * 0.10
  end
end

Эта модель работает хорошо, если бы я использовал @total вместо total в методе taxes, исчисление будет неудачным, если я не вызову метод total на этом объекте раньше.

Как указывает @pst, @association_name не работает для ассоциации, вы должны использовать метод association_name,

Также self.attr следует использовать только для установки атрибута (вызов self.attr=) при чтении значения лучше использовать attr, см. эту статью: Когда использовать собственную модель Rails

Другие вопросы по тегам