Считайте мой ответ очень большим комментарием к ответу Криса Кимптона .
Во-первых, вы должны прочитать документацию по API , где ассоциации довольно хорошо объяснены.
Короче говоря, когда вы вызываете метод has_many
в коде класса (помните, что в Ruby каждая строка представляет собой исполняемый код, поэтому has_many :something
- это просто вызов некоторого существующего метода) тогда этот метод определяет еще два метода с тем же именем, что и переданный вами аргумент.
В этом случае это будет Символ :line_items
, поэтому метод has_many
делает нечто примерно эквивалентное: def line_items(force_reload = false)
и def line_items=(objects)
.
Вновь созданный метод line_items
возвращает объект коллекции всех объектов LineItem, отфильтрованных по WHERE cart_id = #{self.id}
(это упрощенный пример) .
Этот объект коллекции работает как массив, но он также реагирует на некоторые другие методы (например, find
или build
) , помогающие управлять отношением между объектом Cart и LineItem.
Итак, строка:
line_items.where(:product_id => some_id).first
является эквивалентом:
LineItem.where(:cart_id => self.id).where(:product_id => some_id).first
Используя первый метод (коллекция line_items
) , вам не нужно помнить о добавлении этого :cart_id => self.id
к каждому выражению.