Как я могу присоединиться к 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 ответа:
Я бы сделал это, используя: 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