4

J'utilise ActiveRecord dans Rails 3 pour extraire des données de deux tables différentes dans deux bases de données différentes. Ces bases de données ne peuvent pas se joindre les unes aux autres, mais j'ai besoin de faire une simple jointure après le fait. Je voudrais préserver la relation pour pouvoir l'enchaîner.Comment faire une jointure dans ActiveRecord après que les enregistrements ont été renvoyés?

ici est une version simplifiée de ce que je fais

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

Comme vous pouvez le voir, je veux rejoindre browsers dans la relation events, où browser_id doit être égal browsers.name. events est une relation et je peux toujours ajouter des clauses sur la ligne, donc je ne veux pas lancer la requête sur la base de données pour le moment. Comment pourrais-je accomplir cela?

Modifier

Pour ceux qui voudraient voir le code pour la réponse que j'accepté ci-dessous, voici ce que je suis venu avec:

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 

me laisser aller le navigateur nom de la manière suivante

get_todays_events.browser.name 

Répondre

2

Je voudrais accomplir cela en utilisant un: e. Tenter de faire cela dans Ruby ne vous causera que du chagrin. Vous pouvez enchaîner sur un include très bien.

+0

hmm, il semble que les nouveaux rails font la jointure en mémoire plutôt que de la construire dans la requête sql. Merci pour le conseil! –

0

joins ne crée des jointures SQL comme prévu dans les rails actuels 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 ...

Cela devrait être très rapide, car il ne nécessite qu'une seule requête de base de données, alors que includes effectuera 1 + <number of rows in first table> + <number of rows in second table>...

Voici un exemple où includes nécessite 1750x aussi longtemps que 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