2009-11-28 3 views
1

Ma compréhension de la relation has_many dans Rails est qu'il utilisera un JOIN pour trouver des lignes liées. Si je mettais cela en place, j'aurais créé une table relationnelle. Ai-je raison de penser qu'il sera plus lent d'utiliser un JOIN? Dans Django, je crois que les tables relationnelles sont créées, et je sais que je peux utiliser une table relationnelle dans Rails si je le souhaite. Je me demande pourquoi c'est le comportement par défaut et si cela fait n'importe quelle différence.has_many dans Rails utilise un JOIN

Merci

Répondre

2

Non, par défaut, une relation has_many n'utilise pas une jointure pour rechercher des lignes connexes. Voici une rapide des lignes de commande qui montrent ceci (j'ai un enregistreur de débogage activé pour mon script/console).

$ rails has_many_test 

$ cd has_many_test 

$ ruby script/generate model account 

$ ruby script/generate model user account_id:integer 

$ rake db:migrate 

$ ruby script/console 
Loading development environment (Rails 2.3.4) 
>> Account.has_many :users 
>> a = Account.create 
    Account Create (0.4ms) INSERT INTO "accounts" ("created_at", "updated_at") VALUES('2009-11-28 18:06:50', '2009-11-28 18:06:50') 
>> a.users 
    User Load (0.3ms) SELECT * FROM "users" WHERE ("users".account_id = 1) 

Cependant, si la relation has_many définit :through ou :include options, le SQL entraînera une JOIN, mais correctement ainsi.

1

Rails n'utilisez pas si vous joint pas lui dire de le faire.

Disons que vous avez un modèle User avec has_many :posts:

User.all 
# SELECT * FROM `users` 

User.all :joins => :posts 
# SELECT `users`.* FROM `users` INNER JOIN `posts` ON posts.user_id = users.id 

User.all :include => :posts 
# SELECT * FROM `users` 
# SELECT `posts`.* FROM `posts` WHERE (`posts`.user_id IN (1,2)) 

Si vous n'avez pas besoin/veulent se joindre alors il n'y aura pas de jointure.

1

Dans ActiveRecord (ORM utilisé par défaut dans Rails, mais pas le seul possible), une relation has_many implique généralement deux modèles et donc deux tables. Ainsi, ces modèles:

class Order < ActiveRecord::Base 
    has_many :order_items 
end 

class OrderItem < ActiveRecord::Base 
    belongs_to :order 
end 

... renverront orders et order_items tables, ce dernier ayant une référence foreign_key order_id à son ordre de parent.

Order.find(some_id) 

va récupérer une seule commande. order_items ne sera pas touché, sauf si vous le référencez explicitement, ou ajoutez des directives dans votre définition de classe pour exiger que l'association soit toujours naviguée.

Je ne sais pas pourquoi vous êtes si préoccupé par l'utilisation des jointures. Avec une indexation appropriée, presque tous les SGBD modernes seront très efficaces: c'est ce qu'ils sont conçus pour faire.

+0

Merci. Je ne m'en soucie pas vraiment. Juste curieux. Je pensais que c'était faire quelque chose qui avait du sens. Cela ne semblait pas être la façon dont j'avais appris à l'école. –