Rails: объяснение has_many - PullRequest
       2

Rails: объяснение has_many

3 голосов
/ 08 сентября 2011

Попытка понять эффект :has_many, как он представлен в книге Agile Web Development, 4-е издание

Для корзины установлено следующее соотношение

class Cart < ActiveRecord::Base
  has_many :line_items, :dependent => :destroy
end

, что дополняетLineItem class

class LineItem < ActiveRecord::Base
  belongs_to :product
  belongs_to :cart
end

Все хорошо, я полностью понимаю моделирование отношений, и просто пытаюсь признать, что это просто «работает».Однако в коде автор вместо использования метода LineItem.find для поиска в базовой таблице использует объект line_items, например

current_item = line_items.where(:product_id => product_id).first

Может кто-нибудь объяснить это, и в конечном итоге япредставьте себе, каков на самом деле эффект вызова метода :has_many?Что такое line_items объект, откуда он взялся?Я думаю, тот же вопрос будет применяться к эффекту других реляционных методов Rails.

Спасибо. '

Ответы [ 3 ]

2 голосов
/ 08 сентября 2011

Считайте мой ответ очень большим комментарием к ответу Криса Кимптона .

Во-первых, вы должны прочитать документацию по 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 к каждому выражению.

1 голос
/ 08 сентября 2011

Я предполагаю, что образец строки кода находится в методе класса Cart?

Одна из «особенностей» вызова ActiveRecord / has_many - добавить этот псевдо-метод в ваш класс.

Таким образом, класс Cart получает метод line_items для доступа к ним.

Вызов line_items.where выполняет поиск в связанных элементах line_items, а не во всех LineItems, что и делает ваш вызов.Кажется, он ищет строку line_item, относящуюся к определенному продукту - интересно, откуда берется product_id var - параметр метода?

С другой стороны, вызов own_to в LineItem добавляет метод cart для доступакорзина, в которой она находится.

Надеюсь, это поможет, Крис

1 голос
/ 08 сентября 2011

Если код в точности такой, как вы написали здесь, этот объект line_items должен быть установлен где-то еще в этом коде.

Отношение has_many добавит вспомогательный метод, чтобы список связанных элементовэто может быть что-то вроде этого:

cart = Cart.find(1)
line_items = cart.line_items

cart.line_items вернет массив line_items, где line_item.cart_id = cart.id

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...