2

So Rails n'a pas de support pour: via les associations via une relation habtm. Il y a des plugins là-bas qui vont ajouter ceci pour Rails 2.x, mais j'utilise Rails 3/Edge, et seulement besoin de l'association pour un modèle particulier. Alors j'ai pensé que je me perdrais avec la beauté qu'est Arel.Simulation has_and_belongs_to_many comportement imbriqué dans Rails 3

D'abord, les modèles:

class CardSet < ActiveRecord::Base 
    has_and_belongs_to_many :cards, :uniq => true 
end 

class Card < ActiveRecord::Base 
    has_and_belongs_to_many :card_sets, :uniq => true 
    has_many :learnings, :dependent => :destroy 
end 

class Learning < ActiveRecord::Base 
    belongs_to :card 
end 

Je veux obtenir toutes les leçons apprises qui appartiennent à un jeu de cartes, notamment: à travers => cartes.

C'est ce que j'ai jusqu'à présent dans mon modèle cardset:

def learnings 
    c = Table(Card.table_name) 
    l = Table(Learning.table_name) 
    j = Table(self.class.send(:join_table_name, Card.table_name, CardSet.table_name)) 
    learning_sql = l.where(l[:card_id].eq(c[:id])).where(c[:id].eq(j[:card_id])).join(j).on(j[:card_set_id].eq(self.id)).to_sql 
    Learning.find_by_sql(learning_sql) 
end 

qui me donne (putain, Arel est belle!):

SELECT  `learnings`.`id`, `learnings`.`card_id`, `learnings`.`user_id`, `learnings`.`ef`, `learnings`.`times_seen`, `learnings`.`next_to_be_seen`, `learnings`.`interval`, `learnings`.`reps`, `learnings`.`created_at`, `learnings`.`updated_at`, `card_sets_cards`.`card_set_id`, `card_sets_cards`.`card_id` FROM  `learnings` INNER JOIN `card_sets_cards` ON `card_sets_cards`.`card_set_id` = 1 WHERE  `learnings`.`card_id` = `cards`.`id` AND `cards`.`id` = `card_sets_cards`.`card_id` 

qui est oh si proche de ce que je Je vise - il suffit d'ajouter dans la table cards dans la partie FROM de la déclaration.

Et voici ma question: j'ai regardé la source d'Arel, et pour la vie de moi je ne peux pas comprendre comment ajouter dans une autre table. En tant que sidenote, existe-t-il un meilleur moyen d'exécuter le résultat d'Arel (qui retourne généralement une relation Arel :: Relation, que je ne veux pas) via ActiveRecord, autre que de rendre sql et d'exécuter la requête avec find_by_sql comme je le fais?

Répondre

0

Cela est plus facile que ce que je l'ai écrit ci-dessus, après avoir appris comment Rails encapsule Arel de sorte que vous n'avez pas besoin de construire la requête directement.

Si vous essayez de bouchonner HABTM imbriqué dans le modèle cardset, alias:

has_many :learnings, :through => :cards 

alors vous pouvez l'utiliser pour simuler le comportement:

class CardSet < ActiveRecord::Base 

    has_and_belongs_to_many :cards, :uniq => true 

    def learnings 
    Learning.joins(:card).where(:cards => { :id => self.card_ids }) 
    end 
end 

alors une requête comme celle-ci travail:

CardSet.first.learnings 
0

Je ne suis pas familier avec Arel, mais il ne gérer:

l.includes(:card) 
+0

Cela tirera tous les apprentissages, plutôt que seulement ceux associés aux cartes qui sont associés à la card_set (a.k.a., habtm imbriqué). – bouchard