La Déconstruction Des Rails .les jointures & .lorsque les méthodes
J'ai deux modèles - Banner
et BannerType
.
Leur schéma ressemble à ceci:
Bannière
# Table name: banners
#
# id :integer not null, primary key
# name :string(255)
# image :string(255)
# created_at :datetime not null
# updated_at :datetime not null
# url :string(255)
# banner_type_id :integer
BannerType
# Table name: banner_types
#
# id :integer not null, primary key
# name :string(255)
# created_at :datetime not null
# updated_at :datetime not null
Banner belongs_to :banner_type
et BannerType has_many :banners
J'ai deux dossiers dans BannerType qui sont ces:
BannerType.all
BannerType Load (0.3ms) SELECT "banner_types".* FROM "banner_types"
=> [#<BannerType id: 1, name: "Featured", created_at: "2012-12-17 04:35:24", updated_at: "2012-12-17 04:35:24">, #<BannerType id: 2, name: "Side", created_at: "2012-12-17 04:35:40", updated_at: "2012-12-17 04:35:40">]
Si je veux faire une requête pour trouver toutes les bannières de type Featured
je peux faire quelque chose comme ceci:
Banner.joins(:banner_type).where("banner_types.name = ?", 'Featured')
Je sais que je pourrais aussi faire la requête par le banner_type_id => 1
mais se rapportant à cette question particulière.
Si on décompose cette déclaration, il y a quelques choses qui sont un peu confus pour moi.
Banner.join(:banner_type)
- serait de générer desNoMethodError: undefined method 'join' for #<Class:0x007fb6882909f0>
Pourquoi il n'y a pas de Rails méthode appeléejoin
lorsque c'est le SQL, le nom de la méthode?- Pourquoi dois-je faire
Banner.joins(:banner_type)
c'est à dire le singulierbanner_type
lorsque le nom de la table estbanner_types
. Je ne suis pas à rejoindre la Bannière & BannerType tables (qui Rails de conventions de désigner comme au pluriel). Si j'essaieBanner.joins(:banner_types)
c'est l'erreur que j'obtiens:Banner.joins(:banner_types)
ActiveRecord::ConfigurationError: Association named 'banner_types' was not found; perhaps you misspelled it? - Pourquoi le
where
de la clause du besoinbanner_types
et pasbanner_type
(c'est à dire la marque du pluriel version - c'est à dire le nom de la table et non pas le symbole utilisé dans lejoins
méthode? Il semble qu'il serait plus intuitif si vous utilisez la table des noms de lieux ou d'utiliser les noms de symbole dans les deux endroits. Si, à tout le moins, à des fins de cohérence. - Pourquoi ne puis-je pas faire dynamique, comment trouver via des associations - c'est à dire qu'il serait bien si je pouvais faire
Banner.find_by_banner_type_name("Featured")
?
Aimerais entendre vos pensées.
Grâce.
OriginalL'auteur marcamillion | 2012-12-17
Vous devez vous connecter pour publier un commentaire.
#1
C'est plus clair lors de la lecture en tant que simple en anglais pour dire "Bannière rejoint la bannière de type" vs "Bannière de rejoindre la bannière de type". Je ne suis pas sûr qu'il y a plus d'une raison de plus.
#2
Dans
.joins(:banner_type)
,:banner_type
est la relation que vous êtes le rejoindre sur, pas sur la table. Vous avezc'est ce que les Rails rejoint. Ce est juste la façon dont les Rails fonctionne lorsque vous passez un Symbole de
.joins
, et c'est pourquoi l'erreur fait référence à l'association, lorsque vous passez un Symbole ne correspondant à aucune existant association pour votre modèle.C'est aussi pourquoi vous êtes capable de faire
JOIN
's plusieurs niveaux de profondeur à l'aide de symboles pour la imbriqués les associations, comme décrit dans le Guide RailsÉgalement décrit dans le Guide Rails, vous pouvez passer des Chaînes de
.joins
.Remarque dans ce dernier exemple, lorsqu'une Chaîne est passée à
joins
, le nom de la tableaddresses
est utilisé, pas une association nom; cela permet de répondre à #3.#3
Après un peu de chaîne d'interpolation, les Chaînes transmises à la
where
méthode (similaire àjoins
) sont plus ou moins passé directement dans la finale de la requête SQL (il y aura un peu de manipulation par ARel le long de la voie).name
est ambigu dans la colonne (à la fois votrebanners
etbanner_types
tables ont unename
colonne), donc, se référant à la table par son chemin d'accès complet[TABLE NAME].[COLUMN NAME]
est nécessaire. Si, par exemple, vous avez eu quelquescolor
colonne dansbanner_types
(qui ne sont pas présents dansbanners
), il n'y a pas besoin de l'utiliser comme"banner_types.color = ?"
dans votrewhere
méthode;"color = ?"
suffira.Note, tout comme dans #2, vous pouvez passer des symboles de la
where
méthode pourJOIN
'd tables.#4
Vous ne pouvez pas trouver des comme ça parce qu'il n'est pas pris en charge dans ARel, c'est vraiment (OMI, un nom de méthode comme
find_by_banner_type_name
assez déroutant).BannerType.find_by_name('Featured').banners
. Que serait un peu satisfaire ma dernière question, bien qu'un peu en arrière. Je ne reçois pas votre point si...peut être un peu déroutant.Aussi...re: #2, je n'ai pas
has_one :banner_type
explicitement. Dites-vous que parce queBanner belongs_to :banner_type
? De sorte que, en effet, est unhas_one
relation?La requête (la jointure), même sans le travail
has_one
association définie? Je n'ai jamais essayé. Je suis aussi curieux de savoir si il ya une raison pourquoi vous ne pas ont explicitement défini.Il fonctionne parfaitement maintenant, et je n'ai pas
has_one
défini. J'ai justehas_many :banners
sur leBannerType
modèle, etbelongs_to :banner_type
sur leBanner
modèle. Fonctionne comme un charme.la fin de la partie, mais en tant que n ° 1 :
join
est une méthode deArray
; commeActiveRecord::Relation
délégués de la méthode, il ne sait pas à sous-jacente d'un chargement paresseuxArray
de dossiers, si vous appelezjoin
vous touchez la méthode de la baie. Je suppose que la raison pourjoins
avec un supplément des
: 1) éviter la confusion entre les méthodes 2) éviter de masquer lajoin
méthode (ne me demandez pas pourquoi, je ne vois pas dans quel cas il serait utile) 3) faireRelation
'interface se sentir comme un tableau sur les stéroïdesOriginalL'auteur deefour