2009-12-15 4 views
3

J'écris une interface web relativement simple pour la base de données de facturation/client/contrat. Je voudrais avoir la structure suivante pour mes modèles:Complexe joint avec les tables héritées dans Rails

class Invoice < ActiveRecord::Base 
    set_table_name 't10_invoices' 
    set_primary_key 'id_invoice' 
    has_one :client 
end 

class Client < ActiveRecord::Base 
    set_table_name 't20_clients' 
    set_primary_key 'id_client' 
    has_many :invoices 
end 

Le problème est que j'ai la structure de base de données suivante:

Tables: 
t10_invoices: 
    id_invoice - primary_key 
    id_contract - foreign_key 


t12_contracts: 
    id_contract - primary_key  

t15_contracts_clients 
    id_client - foreign_key 
    id_contract - foreign_key 

t20_clients 
    id_client - primary_key 

Il y a 1-1 relation entre t20_clients et t12_contracts par t15_contracts_clients et il existe une relation 1-n entre t20_clients et t10_invoices. Quelle est la différence entre :foreign_key et :association_foreign_key? Le problème est que je ne peux pas modifier la structure de la base de données et je suis tout à fait perdu dans la redéfinition des noms de tables, des clés étrangères, join_foreign_keys etc ... Je voudrais un moyen simple de trouver des clients de facture dans normal Rails way Invoice.find(:first).client

J'apprécierais toute suggestion et aide.

Répondre

2

Créer un ContractClient Joindre un modèle pour correspondre à la table t15_contracts_clients. Il spécifie le nom de table et utilise belongs_to associations pour les 2 clés étrangères:

class ContractClient < ActiveRecord::Base 
    set_table_name 't15_contracts_clients' 
    belongs_to :client, :foreign_key => :id_client 
    belongs_to :contract, :foreign_key => :id_contract 
end 

Indiquez la table et clé primaire pour Client:

class Client < ActiveRecord::Base 
    set_table_name 't20_clients' 
    set_primary_key 'id_client' 
end 

Utilisez un belongs_to :contract_client sur la facture puis un has_one :through associer la client à travers le ContractClient:

class Invoice < ActiveRecord::Base 
    set_table_name 't10_invoices' 
    set_primary_key 'id_invoice' 
    belongs_to :contract_client, :foreign_key => :id_contract 
    has_one :client, :through => :contract_client 
end 

Invoice.find(:first).client devrait alors Behav e comme prévu.

1

Avez-vous envisagé de créer une base de données view?

+0

Oui, je pensais à la création de vues mais je préférerais tout faire dans les rails - donc ce sera beaucoup plus flexible au lieu d'avoir demandé au DBA de créer des vues. –

+0

Je vois. Dans mon équipe, nous maintenons également la base de données, donc je préfère toujours éliminer les incohérences de base de données en utilisant des vues et garder la logique de mon application aussi propre que possible. Utile également si vous avez l'occasion de réécrire correctement le schéma de base de données. Toutefois, les vues n'étant généralement pas modifiables, il faut garder cela à l'esprit. –

2

Vous avez quelques bizarreries dans le modèle. Il n'est pas configuré de telle sorte que le client has_one contrat. Il a une table de jointure au milieu qui permet plusieurs contrats par client. Puisque vous ne pouvez pas modifier les tables, il est préférable de simplement appliquer les relations présentes dans le code. Comme cette table n'a apparemment pas de clé primaire, vous devez probablement utiliser has_and_belongs_to_many. Dans ce type de relation, :association_foreign_key est pour la « autre » classe et :foreign_key est pour la classe que vous êtes.

class Invoice < ActiveRecord::Base 
    set_table_name 't10_invoices' 
    set_primary_key 'id_invoice' 
    belongs_to :contract, :foreign_key => 'id_contract' 
    has_one :client, :through => :contract 
end 

class Contract 
    set_table_name 't12_contracts' 
    set_primary_key 'id_contract' 
    has_and_belongs_to_many :clients, 
          :join_table => 't15_contracts_clients' 
          :foreign_key => 'id_contract', 
          :association_foreign_key => 'id_client' 
    has_many :invoices, :foreign_key => 'id_contract' 
end 

class Client < ActiveRecord::Base 
    set_table_name 't20_clients' 
    set_primary_key 'id_client' 
    has_and_belongs_to_many :clients, 
          :join_table => 't15_contracts_clients' 
          :foreign_key => 'id_client', 
          :association_foreign_key => 'id_contract' 
    has_many :invoices, :through => :contracts 
end 

Vous devez ensuite invoquer

Invoice.find(:first).client 
Questions connexes