Объединение вложенных ассоциаций, многоуровневое - PullRequest
5 голосов
/ 18 июля 2011

Для тех из вас, кто хорошо знает рельсы и sql, я ищу полезную информацию, на которую вы могли бы указать мне. Мой запрос очень похож на пример «Присоединение к вложенным ассоциациям» в этом разделе - http://guides.rubyonrails.org/active_record_querying.html#using-array-hash-of-named-associations

Мои модели (сокращенно):

User has_many :products    # User is 'great-grandparent'
Product has_many :posts    # Product is grandparent #1
Event has_many :posts      # Event is grandparent #2
Post belongs_to :event
Post belongs_to :product
Post has_many :orders      # Post is parent
Order belongs_to :post     # Order is great-grandchild, grandchild, & child

Я хочу собрать заказы на мероприятии для пользователя (продавца), и вот моя лучшая попытка сделать это.

class Order < ActiveRecord::Base
  def self.collect_for_seller_and_event(user_id, event_id)
    self.joins(:post => [{:product => :user }, :event]).where(:post => [{:product => {:user_id => user_id}}, {:event_id => event_id}])
  end

Как должно выглядеть это объединение?

Должен ли я разбить это на области в различных моделях в гирляндной цепи?

Просто чтобы показать, что у меня есть базовое понимание, я смог запустить свою первую рабочую вложенную таблицу соединений (я очень рад этому достижению)

BuyerFeedback 
belongs_to :order
def self.from_past_events
   self.joins(:order => {:post => :event}).where(:order => {:post => {:event => {:date.lt => Date.today}}})
end

1 Ответ

1 голос
/ 23 августа 2013

Ваша идея разбить это на области хороша.Но вам, возможно, не придется объединять в цепочку столько, сколько вы думаете, потому что вы можете объединить области из других моделей в любую связанную модель.Вот отличная статья о слиянии ARel #, которая делает эту замечательную вещь возможной: http://ben.hoskings.net/2012-07-04-arel-merge-a-hidden-gem

Таким образом, вы можете разбить свое мышление на более мелкие куски.Итак, начните с Post и создайте область действия, которая предоставит вам все связанные продукты, предоставленные пользователю.Затем создайте область видимости, которая связывает эту область с областью, которая получает все сообщения с данным событием.Затем просто объедините эту область с вашей областью пользователя.

Product
  scope :for_user, ->(user) { where(user_id: user) }  # The passed in `user` can be an instance of user or an id

Post
  scope :for_product, ->(product) { where(product_id: product) }
  scope :for_product_given_user, ->(product, user) { for_product(product).merge(Product.for_user(user)) }
  scope :for_product_given_user_and_event, ->(product, user, event) { for_product_given_user(product, user).where(event_id: event) }

Я не уверен, что нахожусь на правильном пути, учитывая, что я не могу проверить ... но, возможно, это поможет вам начать.Идея состоит в том, чтобы разбить обязанности на управляемые куски и позволить ARel выполнить сумасшедшую работу по слиянию SQL.

...