2009-02-11 7 views
8

¿Cómo modelizarías las referencias y citas de publicaciones (artículos, libros, capítulos, etc. ...)?Relaciones de registro activas difíciles: polimórficas bidireccionales autorreferenciales

Una publicación puede ser un artículo, libro o un capítulo y tiene muchas referencias a otras publicaciones y otras publicaciones se refieren a ella (llamar a estas citas)

que necesito para ser capaz de enumerar las relaciones entre las publicaciones : Las referencias en una publicación y las citas de otras publicaciones a esta publicación

Mi comprensión inicial es que esta sería una relación polimórfica para manejar los diferentes tipos de publicaciones y que requeriría una unión bidireccional.

Mi puñalada en ella

Publication 
belongs_to :writing, :polymorphic =>true 
has_and_belongs_to_many :references 
    :class_name => "Publication" 
    :join_table => 'reference_citation' 
    :foreign_key => 'reference_id' 
    :foreign_key => 'citation_id' 

Book, Chapter, Article all have: 
has_many :publications :as =>writing 

me parece un poco confuso por lo que cualquier sugerencia que ayude a aclarar que sería genial. Incluso sugerencias de nombres de objetos y campos.

[I hizo una versión menos clara de esta cuestión here.]

también probable que tenga que utilizamos tiene muchos a través porque voy a necesitar la capacidad de destruir la relación

Respuesta

12

Aquí hay una solución con una relación de auto-referencial usando sola tabla herencia.Utilice estos comandos para crear la aplicación:

$ rails myproject 
$ cd myproject 
$ script/generate model publication type:string name:string 
$ script/generate model citation publication_id:integer reference_id:integer 

La configuración de las relaciones de esta manera:

class Publication < ActiveRecord::Base 
    has_many :citations 
    has_many :cited_publications, :through => :citations, :source => :reference 
    has_many :references, :foreign_key => "reference_id", :class_name => "Citation" 
    has_many :refered_publications, :through => :references, :source => :publication 
end 

class Citation < ActiveRecord::Base 
    belongs_to :publication 
    belongs_to :reference, :class_name => "Publication" 
end 

class Article < Publication 
end 

class Book < Publication 
end 

class Chapter < Publication 
end 

Ahora podemos crear la base de datos y probarlo desde la consola:

$ rake db:migrate 
$ script/console 
Loading development environment (Rails 2.2.2) 
>> a = Article.create!(:name => "Article") 
=> #<Article id: 1, ...> 
>> b = Book.create!(:name => "Book") 
=> #<Book id: 2, ...> 
>> a.citations.create(:reference => b) 
=> #<Citation id: 1, publication_id: 1, reference_id: 2, created_at: "2009-02-15 14:13:15", updated_at: "2009-02-15 14:13:15"> 
>> a.citations 
=> [#<Citation id: 1, ...>] 
>> a.references 
=> [] 
>> b.citations 
=> [] 
>> b.references 
=> [#<Citation id: 1, publication_id: 1, reference_id: 2, created_at: "2009-02-15 14:13:15", updated_at: "2009-02-15 14:13:15">]  
>> a.cited_publications 
=> [#<Book id: 2, type: "Book", name: "Book", created_at: "2009-02-15 14:11:00", updated_at: "2009-02-15 14:11:00">] 
>> a.refered_publications 
=> [] 
>> b.cited_publications 
=> [] 
>> b.refered_publications 
=> [#<Article id: 1, type: "Article", name: "Article", created_at: "2009-02-15 14:10:51", updated_at: "2009-02-15 14:10:51">] 
+1

Justo un poco de precaución para los demás: referido tiene dos R – srboisvert

5

Aquí hay una solución que no utiliza la herencia de tabla única para las publicaciones. Eso significa que hay artículos, libros y tablas de capítulos, en lugar de una tabla de publicaciones. Estos son los comandos a ejecutar para crear la aplicación:

$ rails myproject 
$ cd myproject 
$ script/generate model book name:string 
$ script/generate model chapter name:string 
$ script/generate model article name:string 
$ script/generate model citation publication_type:string publication_id:integer reference_type:string reference_id:integer 

crear este archivo en lib/acts_as_publication.rb:

module ActsAsPublication 
    def self.included(base) 
    base.extend(ClassMethods) 
    end 
    module ClassMethods 
    def acts_as_publication 
     has_many :citations, :as => :publication 
     has_many :references, :as => :reference, :class_name => "Citation"  
    end 
    end 
end 

crear este archivo en config/initializers/acts_as_publication.rb:

ActiveRecord::Base.send(:include, ActsAsPublication) 

luego llamar a que en cada modelo , Artículo, Libro y Capítulo, como este:

class Article < ActiveRecord::Base 
    acts_as_publication 
end 

A continuación, añadir estas relaciones en app/models/citation.rb:

class Citation < ActiveRecord::Base 
    belongs_to :publication, :polymorphic => true 
    belongs_to :reference, :polymorphic => true 
end 

Ahora podemos crear la base de datos y probarlo desde la consola:

$ rake db:migrate 
$ script/console 
Loading development environment (Rails 2.2.2) 
>> a = Article.create!(:name => "a") 
=> #<Article id: 1, ...> 
>> b = Article.create!(:name => "b") 
=> #<Article id: 2, ...> 
>> Citation.create!(:publication => a, :reference => b) 
=> #<Citation id: 1, publication_type: "Article", publication_id: 1, reference_type: "Article", reference_id: 2, created_at: "2009-02-15 13:14:27", updated_at: "2009-02-15 13:14:27"> 
>> a.citations 
=> [#<Citation id: 1, ...>] 
>> a.references 
=> [] 
>> b.citations 
=> [] 
>> b.references 
=> [#<Citation id: 1, ...>] 
>> Book.create!(:name => "foo") 
=> #<Book id: 1, name: "foo", created_at: "2009-02-15 13:18:23", updated_at: "2009-02-15 13:18:23"> 
>> a.citations.create(:reference => Book.first) 
=> #<Citation id: 2, publication_type: "Article", publication_id: 1, reference_type: "Book", reference_id: 1, created_at: "2009-02-15 13:18:52", updated_at: "2009-02-15 13:18:52"> 
>> Book.first.references 
=> [#<Citation id: 2, ...>] 
>> a.citations 
=> [#<Citation id: 1, publication_type: "Article", publication_id: 1, reference_type: "Article", reference_id: 2, created_at: "2009-02-15 13:14:27", updated_at: "2009-02-15 13:14:27">, #<Citation id: 2, publication_type: "Article", publication_id: 1, reference_type: "Book", reference_id: 1, created_at: "2009-02-15 13:18:52", updated_at: "2009-02-15 13:18:52">] 
Cuestiones relacionadas