2017-09-15 3 views
1

Je crée un modèle referral qui pourra relier 2 clients, un référencé et un ayant fait référence. J'ai déjà le modèle client, mais me demande la bonne façon de configurer le modèle referral tel que je peux interroger:Rails 4: Associations de modèles de référence

Client.find(x).referrals 
# returns all referrals where referrer has the client's id 

Client.find(x).referred_by 
# returns client that referred this client 
+0

Je vous recommande d'utiliser une table de jointure http://guides.rubyonrails.org/active_record_migrations.html#creating-a-join-table –

+1

vous essayez de Semble faire des associations many-to-many, avec Referrals comme table de jointure. – EJ2015

Répondre

2

Mise en place de deux associations à la même table est l'une des associations les plus délicates dans ActiveRecord. La clé consiste à configurer différentes associations pour chaque colonne de clé étrangère.

permet donc commencer par la table de jointure:

# This is a Rails 5 migration - don't copy paste it 
# You'll have to generate one for rails 4 
class CreateReferrals < ActiveRecord::Migration[5.0] 
    def change 
    create_table :referrals do |t| 
     t.belongs_to :referrer_id, foreign_key: false 
     t.belongs_to :referred_id, foreign_key: false 
     # Since the table for the foreign key cannot be automatically derived you need to add them manually 
     add_foreign_key :referrals, :clients, column: :referrer_id 
     add_foreign_key :referrals, :clients, column: :referred_id 
     t.timestamps 
    end 
    end 
end 

Permet de configurer les associations sur le renvoi:

class Referral < < ActiveRecord::Base 
    belongs_to :referrer, class_name: 'Client' 
    belongs_to :referred, class_name: 'Client' 
end 

Rien funky ici encore. class_name: 'Client' indique à ActiveRecord (AR) sur quelle table pointe l'association car elle ne peut pas être dérivée du nom de l'association. permet maintenant de créer les associations inverses sur le client:

class Client < ActiveRecord::Base 
    has_many :referrals, class_name: 'Referral', 
    foreign_key: 'referrer_id' 
    has_many :referrals_as_referred, class_name: 'Referral', 
    foreign_key: 'referred_id' 
end 

Pour ajouter les associations à d'autres clients qui sont référés ou référants à un client utilisant une assocation indirecte:

class Client < ActiveRecord::Base 
    # ... 
    # clients reffered by this client 
    has_many :referred_clients, 
     through: :referrals, 
     source: :referred 
    has_many :referrers, 
     through: :referrals_as_referred, 
     source: :referrer 
end 
  • through: :referrals dit AR rejoindre grâce à l'association nommée :referrals.
  • source: :referred indique l'association sur la table de jointure à utiliser.
+0

Vous avez raison @DavidAldridge. Édité – max

+0

Vraiment apprécier la réponse complète. C'était beaucoup plus délicat que prévu –

0

Vous pouvez utiliser l'auto-association pour cela. Sur le modèle client, ajoutez la colonne referrals_id. L'association dans le modèle client serait comme ceci:

class Client < ActiveRecord::Base 
    has_many :referrals, class_name: "Client", foreign_key: :referrals_id 
    belongs_to :referred_by, class_name: "Client", foreign_key: :referrals_id 
end 

Considérez-vous ces deux enregistrements dans les tables.

[{ 
    "id":1, 
    "name":"Admin", 
    "referrals_id": nil, 
}, 
{ 
    "id":2, 
    "name":"Client", 
    "referrals_id":1, 
}] 

Maintenant, vous pouvez demander des références volonté retourne tous les renvois où referrer a l'ID du client

Client.find(1).referrals 

Cela va générer un SQL comme:

`SELECT "clients".* FROM "clients" WHERE "clients"."referrals_id" = ? [["referrals_id", 1]]` 

pour referred_by sera client de rendements orienté ce client

Client.find(2).referred_by 

Cela va générer SQL comme:

SELECT "clients".* FROM "clients" WHERE "clients"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]