2011-12-19 3 views
1

J'ai deux tables (sujets et pages) dans les relations un-à-plusieurs. Je veux ajouter des critères de sujets ainsi que des pages pour analyser un sql, mais les progrès ont été très lents et souvent en cours d'exécution. Je suis tout nouveau dans les rails, s'il vous plaît aider.Ruby on Rails - Comment joindre deux tables?

class Subject < ActiveRecord::Base 
    has_many :pages 
end 

class Page < ActiveRecord::Base 
    belongs_to :subject 
end 

données d'échantillons chez les sujets, figurent trois colonnes ci-dessous:

id name level 
1 'Math' 1 
6 'Math' 2 
... 

données exemples dans les pages, les colonnes ci-dessous:

id name     subject_id 
-- -------------------- ---------- 
2 Addition    1 
4 Subtraction    1 
5 Simple Multiplication 6 
6 Simple Division   6 
7 Hard Multiplication  6 
8 Hard Division   6 
9 Elementary Divsion  1 

Étant donné que je ne connais pas le sujet. id, je ne connais que le nom et le niveau du sujet, et le nom de la page. Voici le sql que je veux générer (ou quelque chose de similaire qui permettrait d'atteindre le même résultat):

select subjects.id, subjects.name, pages.id, pages.name from subjects, pages 
where subjects.id = pages.subject_id 
    and subjects.name = 'Math' 
    and subjects.level = '2' 
    and pages.name like '%Division' ; 

Je me attends à obtenir deux lignes dans le résultat:

subjects.id  subjects.name pages.id pages.name 
-----------  ------------- -------- ----------- 
6    Math   6   Simple Division 
6    Math   8   Hard Division 

Ceci est un sql très simple , mais je n'ai pas pu obtenir le désir que je voulais dans les rails.

Here is my rails console: 

>> subject = Subject.where(:name => 'Math', :level => 2) 
    Subject Load (0.4ms) SELECT `subjects`.* FROM `subjects` WHERE `subjects`.`name` = 'Math' AND `subjects`.`level` = 2 
[#<Subject id: 6, name: "Math", position: 1, visible: true, created_at: "2011-12-17 04:25:54", updated_at: "2011-12-17 04:25:54", level: 2>] 
>> 
>> subject.joins(:pages).where(['pages.name LIKE ?', '%Division']) 
    Subject Load (4.2ms) SELECT `subjects`.* FROM `subjects` INNER JOIN `pages` ON `pages`.`subject_id` = `subjects`.`id` WHERE `subjects`.`name` = 'Math' AND `subjects`.`level` = 2 AND (pages.name LIKE '%Division') 
[#<Subject id: 6, name: "Math", position: 1, visible: true, created_at: "2011-12-17 04:25:54", updated_at: "2011-12-17 04:25:54", level: 2>, #<Subject id: 6, name: "Math", position: 1, visible: true, created_at: "2011-12-17 04:25:54", updated_at: "2011-12-17 04:25:54", level: 2>] 
>> 
>> subject.to_sql 
"SELECT `subjects`.* FROM `subjects` WHERE `subjects`.`name` = 'Math' AND `subjects`.`level` = 2" 
>> subject.size 
1 
>> subject.class 
ActiveRecord::Relation 

1ère déclaration: subject = Subject.where (: name => 'Math',: niveau => 2) 2ème: Déclaration subject.joins (: pages) .où ([ 'pages .name LIKE », '% Division'])

questions:

  1. les résultats de la chaîne SQL retourne vraiment deux lignes, mais subject.size dit seulement 1?
  2. Comment puis-je lui dire de retourner des colonnes de: pages aussi?
  3. Pourquoi subject.to_sql n'affiche toujours que l'instruction sql from 1, pourquoi n'a-t-il pas inclus l'instruction sql chaînée from 2?
  4. Essentiellement, de quoi ai-je besoin pour écrire les instructions différemment pour analyser le sql comme indiqué ci-dessus (ou obtenir le même résultat)?

Merci beaucoup.

Répondre

4

1) ActiveRecord va cartographier les résultats de la requête à objets pas arbitraires lignes retournées, parce que vous avez fondé la création de requête hors de la classe Subject il regarde vos lignes résultantes et les chiffres que ce ne se référait à 1 unique objet Subject, retourne donc que seule instance Subject.

2) Les données de colonne sont là, mais vous travaillez contre ce qu'ActiveRecord veut vous donner, à savoir les objets. Si vous préférez que Pages soit renvoyé, vous devez baser la création de la requête sur la classe Page.

3) Vous n'avez pas sauvegardé les résultats de l'ajout du join(:pages)... dans la variable subject.Si vous avez fait:

subject = subject.joins(:pages).where(['pages.name LIKE ?', '%Division']) 

vous obtiendrez la requête complète lors de l'exécution subject.to_sql

4) Pour obtenir la page des objets que vous pouvez faire quelque chose comme ça, notez que nous fondons hors tension de la classe Page:

pages = Page.joins(:subject).where(['subjects.name = ? AND subjects.level = ? AND pages.name LIKE ?', 'Math', 2, '%Division']) 

ensuite pour accéder au nom du sujet à partir de là pour le premier objet Page retourné:

pages[0].subject.name 

Qui, parce que vous avez la jointure dans le premier, ne donnera pas une autre requête SQL. J'espère que cela t'aides!

+0

Brillant! Merci beaucoup. Vous répondez à toutes mes questions, ça marche bien maintenant. :-) – jmsia