2009-06-05 8 views
1

J'ai un modèle de caractère et un modèle de lien. Le modèle Link représente un lien d'un caractère à un autre caractère. Un lien a un attribut 'description' textuel. Un lien du caractère A au caractère B est distinct du lien opposé de B à A. Un caractère a zéro ou un lien vers un autre caractère. Un personnage peut avoir différents liens vers différents personnages. Un personnage peut être lié à différents personnages.Relations ActiveRecord pour une table de jointure reliant deux enregistrements de la même table?

J'ai utilisé utilisé des relations Active Record à mettre en œuvre en partie les relations entre les modèles de personnages et Lien:

class Character 
has_many :links # the links from the character to other characters 

class Link 
belongs_to :character # the character from which starts the link to another character 

qui me donnent des méthodes utiles comme character.links (tableau de tous les liens à partir de ce caractère) ou link.character (caractère à partir duquel commence le lien)

Le modèle de lien a également un to_character_id qui contient l'ID du caractère à qui va le lien. Ainsi, un lien de caractère A à caractère B est une instance avec les attributs suivants:

  • character_id = id de caractère A
  • to_character_id = id de caractère B
  • description = texte

J'ai écrit diverses méthodes supplémentaires comme character.links_to (renvoyant un tableau de tous les liens pointant vers le caractère) ou link.to_character (retournant le caractère vers lequel pointe le lien), ou character.characters_who_link_to (retourner un tableau des autres caractères ayant un lien vers ce personnage). J'ai aussi écrit un rappel pour m'assurer que lorsqu'un caractère est supprimé, tous les liens qui vont à ce caractère sont supprimés (même chose pour la restauration).

Est-il possible d'utiliser des déclarations de relations AR supplémentaires qui me fourniraient ce type de méthodes supplémentaires, de sorte que je n'ai pas besoin d'écrire moi-même ces méthodes et rappels?

Le développement Web Agile avec Rails présente une solution dans la section "Utilisation de modèles comme tables de jointure" mais pour une table de jointure reliant deux tables différentes. Dans mon cas, ma table de jointure rejoint les enregistrements d'une seule table, Caractères.

+0

Donc, fondamentalement, vous voulez que les caractères aient une relation has_and_belongs_to_many: characters? – ErsatzRyan

Répondre

3

has_and_belongs_to_many n'est plus vraiment utilisé; J'utiliserais plutôt has_many :through.

class Character < ActiveRecord::Base 
    has_many :links, :dependent => destroy 
    has_many :characters, :through => :links 

    has_many :source_links, :class_name => "Link", 
    :foreign_key => "to_character_id", :dependent => :destroy 
    has_many :source_characters, :class_name => "Character", 
    :through => :destination_links 
end 

class Link < ActiveRecord::Base 
    belongs_to :character 
    belongs_to :source_character, :class_name => "Character", 
    :foreign_key => "to_character_id" 
end 

Notez les :dependent => :destroy les options - ceux-ci supprimera les liens lorsque le caractère est supprimé. Le nom est correct - du point de vue du personnage, source_links sont les liens à ce caractère. Alors maintenant vous pouvez faire:

@character.characters # characters I link to 
@character.links # links I have to other characters 
@character.source_characters # characters that link to me 
@character.source_links # links other characters have to me 
2

Je pense que vous voulez quelque chose comme ce qui suit:

class Character < ActiveRecord::Base 
    has_many :outbound_links, :class_name => "Link", :foreign_key => "from_character_id" 
    has_many :inbound_links, :class_name => "Link", :foreign_key => "to_character_id" 
end 

class Link < ActiveRecord::Base 
    belongs_to :from_character, :class_name => "Character", :foreign_key => "from_character_id" 
    belongs_to :to_character, :class_name => "Character", :foreign_key => "to_character_id" 
end 

Vous pouvez lire toutes vos options sur les associations ActiveRecord à http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

0

Je pense que ce que vous allez vraiment ici est un HABTM auto référentiel relation à l'aide d'une table de jointure

donc si vous aviez une table de jointure

create_table :character_links do |t| 
    t.integer :character_id 
    t.integer :linked_character_id 
    t.timestamps #if you want to know when the relationship was created 
end 

Ensuite, vous auriez

class Characters < ActiveRecord::Base 
    has_and_belongs_to_many :linked_characters, 
     :class_name => "Characters", 
     :join_table => :character_links, 
     :foreign_key => "character_id", 
     :associated_foreign_key => "linked_character_id" 

si vous avez besoin de liens sortants et des liens entrants alors vous pouvez faire

class Characters < ActiveRecord::Base 
    has_and_belongs_to_many :outgoing_links, 
     :class_name => "Characters", 
     :join_table => :character_links, 
     :foreign_key => "character_id", 
     :associated_foreign_key => "linked_character_id" 

    has_and_belongs_to_many :incoming_links, 
     :class_name => "Characters", 
     :join_table => :character_links, 
     :foreign_key => "linked_character_id", 
     :associated_foreign_key => "character_id" 

juste de passer le foreign_key et associated_foreign_key

Ceci élimine le besoin pour vous avoir un modèle séparé Links

Ceci est air co de (non testé)

Questions connexes