2010-03-05 8 views
4

J'essaie de comprendre comment créer des modèles ActiveRecord avec les associations qui peuvent donner les mêmes résultats que cette requête SQL:Comment créer des modèles Rails avec plusieurs associations/jointures complexes?

SELECT login, first_name, last_name, email_address 
FROM accounts 
INNER JOIN people ON person.id = accounts.person_id 
INNER JOIN email_address_people ON person.id = email_address_people.person_id 
INNER JOIN email_addresses ON email_address.id = email_address_people.email_address_id 
INNER JOIN email_address_types ON email_address_types.id = email_address_people.email_address_type_id 
WHERE email_address_types.email_address_type = 'account'; 

La structure de la table est la suivante, et prend chaque table a une id par ActiveRecord normale Convention:

comptes
id: int
person_id: int
connexion: string

personnes
id: int
prenom: string
last_name: string

email_address_people
id: int
person_id: int
email_address_id: int
email_address_type_id: int

EMAIL_ADDRESSES
id: int
email_address: string

email_address_types
id: int
email_address_type: string

J'ai besoin que les modèles soient pleinement fonctionnels, et non limités par des choses comme : find_by_sql.

Comment créer les modèles associés qui rendent cela possible?

Merci!
Chris Benson
[email protected]

Répondre

0

Je pense que la meilleure chose à faire ici est de vous donner la documentation d'abord: http://railsbrain.com/api/rails-2.3.2/doc/index.html
Cherchez "has_many" (attention à: par) et "belongs_to" , ainsi que "has_one", bien que je ne pense pas que vous utiliserez le plus tard.
This blog post vous aidera avec le concept has_many: through - et je pense qu'après cela, vous serez mis en place. Dites-nous s'il y a quelque chose qui n'est pas clair!

class Account < ActiveRecord::Base 
    belongs_to :person 
end 

class Person < ActiveRecord::Base 
    has_many :accounts 
    has_many :email_addresses :through => :email_address_people 
end 

class EmailAddress < ActiveRecord::Base 
    belongs_to :email_address_type 
    belongs_to :person 
    has_one :email_address_type 
end 

class EmailAddressType < ActiveRecord::Base 
    has_many :email_addresses :through => :email_address_people 
end 

Je commencerais avec cela. Ce n'est pas testé, mais si nous voyons quelles pauses, alors nous pouvons le réparer ..:)

+0

Merci, mais je l'ai déjà fait. Familier avec tous - belongs_to, has_one, HABTM, HM: T. Déjà les utiliser tous, mais ne peut pas comprendre comment faire fonctionner cette situation correctement. N'a pas trouvé d'exemples sur le web qui répondent aux jointures de cette complexité. Pourrait vraiment utiliser un exemple de code de modèle qui montre au moins 4-5 tables normalisées jointes et les utilise toutes dans une requête standard. – Chris

+0

Édité ma réponse (je ne sais pas si vous seriez averti à ce sujet). – Trevoke

3

Essayez ceci:

Vos classes de modèle:

class EmailAddress < ActiveRecord::Base 
    end 

    class EmailAddressType < ActiveRecord::Base 
    end 

    class People < ActiveRecord::Base 
    has_many :accounts 
    has_many :email_address_people 
    has_many :email_addresses, :through => :email_address_people 

    has_many :account_email_address_people, 
        :class_name => "EmailAddressPeople", 
        :conditions => "email_address_type = 'account'" 

    has_many :account_email_addresses, 
        :through => :account_email_address_people 

    end 

    class EmailAddressPeople < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :email_address 
    belongs_to :email_address_type 
    end 

Votre modèle de compte:

class Account < ActiveRecord::Base 
    belongs_to :person 

    # now to the actual method 
    def account_emails 
     person.account_email_addresses.map do |email| 
     [login, person.first_name, person.last_name, email.email_address] 
     end 
    end 

    # Brute force SQL if you prefer 
    def account_emails2 
     sql = "YOUR SQL HERE" 
     self.connection.select_values(sql) 
    end 

    end 

En supposant que vous avez l'objet de compte dans la main account.account_emails fait deux base de données appelle:

  • obtenir de la personne en utilisant un identifiant

  • Obtenez le compte des e-mails pour la personne

Aller directement à la base de données (i.e.. account.account_emails2) est l'option la plus rapide, mais ce n'est pas la méthode Rails.

Questions connexes