Как я могу присоединиться к ActiveRecord после того, как записи были возвращены?


Я использую ActiveRecord в Rails 3 для извлечения данных из двух разных таблиц в двух разных базах данных. Эти базы данных не могут объединяться друг с другом, но у меня есть необходимость сделать простое объединение после факта. Я хотел бы сохранить эту связь, чтобы я мог связать ее по цепочке.

Вот упрощенная версия того, что я делаю

browsers = Browser.all # <-- this is fairly small and can reside in memory
events = Event.where(:row_date=>Date.today).select(:name, :browser_id)

Итак, как вы можете видеть, я хочу соединить browsers в отношении events, где browser_id должно равняться browsers.name. events - это отношение, и я могу по-прежнему добавляйте к нему предложения вниз по строке, поэтому я пока не хочу запускать запрос в БД. Как бы я этого добился?

править

Для тех, кто хотел бы увидеть некоторый код для ответа, который я принял ниже, Вот что я придумал:

class EventLog < ActiveRecord::Base
  belongs_to :browser

  def get_todays_events
    Event.where(:row_date=>Date.today).select(:name, :browser_id).includes(:browser)
  end
end

Позволит мне получить имя браузера следующим образом

get_todays_events.browser.name
2 4

2 ответа:

Я бы сделал это, используя: include. Попытка сделать это в Ruby не принесет вам ничего, кроме горя. Вы можете приковать цепочку к включению просто отлично.

joins создает ли SQL-соединения, как ожидается, в текущих Rails 5:

pry(main)> Customer.joins(:orders).limit(5) Customer Load (0.2ms) SELECT `customers`.* FROM `customers` INNER JOIN `orders` ON `orders`.`customer_id` = `customers`.`id` LIMIT 5 => [#<Customer:0x007fb869f11fe8 ...

Это должно быть значительно быстрее, потому что для этого требуется только один запрос к базе данных, в то время как includes будет выполнять 1 + <number of rows in first table> + <number of rows in second table>...

Вот пример, где includes требуется 1750x до тех пор, пока joins:

pry(main)> benchmark do
   Order.joins(:address, :payments, :customer, :packages).all.size
> 0.02456 seconds

pry(main)> benchmark do
[14] pry(main)* Order.includes(:address, :payments, :customer, :packages).all.map(&:zip).max
[14] pry(main)*end
=> 35.607257 seconds