10

Ich habe Probleme mit meinem CodeSTI und Polymorphe

class Post < ActiveRecord::Base 
end 

class NewsArticle < Post 
    has_many :comments, :as => :commentable, :dependent => :destroy, :order => 'created_at' 
end 

class Comment < ActiveRecord::Base 
    belongs_to :commentable, :polymorphic => true, :counter_cache => true 
end 

Und Versuch zu holen Kommentare für einige Newsartikel i in Protokollen etwas sehen, wie

Comment Load (0.9ms) SELECT "comments".* FROM "comments" WHERE ("comments"."commentable_id" = 1 and "comments"."commentable_type" = 'Post') ORDER BY created_at 

Seltsam, dass "commentable_type" = ‚Beitrag '. Was ist los?

PS: Schienen 2.3.5 & & rubin 1.8.7 (2010-01-10 Patchlevel 249) [i686-darwin10]

Antwort

5

Das commentable_type Feld den Namen der Tabelle speichern muss, dass die enthalten Daten, sobald diese Zeile aus der rechten Tabelle geladen wird, wird der geerbte Typ von Typ Spalte auf Posts Tabelle geladen.

So:

Hier den Kommentar zeigt auf den Tisch, dass es kommentiert. Die Pfosten-Tabelle, ID 1

>> Comment.first 
=> #<Comment id: 1, commentable_id: 1, commentable_type: "Post", body: "test", created_at: "2010-04-09 00:56:36", updated_at: "2010-04-09 00:56:36"> 

dann die Newsartikel zu laden, ID 1 ist aus Pfosten geladen, und die Art es gibt einen Newsartikel.

>> Comment.first.commentable 
=> #<NewsArticle id: 1, type: "NewsArticle", name: "one", body: "body", created_at: "2010-04-09 00:55:35", updated_at: "2010-04-09 00:55:35"> 
>> Comment.first.commentable.class.table_name 
=> "posts" 

Wenn commentable_type gehalten "NewsArticle" hätte es in der Klasse suchen, die Tabelle zu bestimmen. Auf diese Weise kann es einfach zum Tisch schauen und sich um den Typ kümmern, sobald er da ist.

+0

huh ... Tabellenname ist korrekt, aber STI-Modellname ist falsch –

+0

Für die polymorphe Beziehung ist nur die Tabelle wichtig, sobald die Tabelle geladen ist, kann der Vererbungstyp bestimmt werden. – danivovich

1

Werfen Sie einen Blick auf den Abschnitt Polymorphe Assoziationen von ActiveRecord::Associations API. Es gibt ein wenig über die Verwendung von polymorphen Zuordnungen in Kombination mit der Vererbung einzelner Tabellen. Nach dem zweiten Codebeispiel in diesem Abschnitt denke ich, das zu nahe sein könnte, was Sie wollen

class Comment < ActiveRecord::Base 
    belongs_to :commentable, :polymorphic => true, :counter_cache => true 

    def commentable_type=(sType) 
    super(sType.to_s.classify.constantize.base_class.to_s) 
    end 
end 

class Post < ActiveRecord::Base 
    has_many :comments, :as => :commentable, :dependent => :destroy, :order => 'created_at' 
end 

class NewsArticle < Post 
end 
0

Technisch gesehen gibt es eigentlich nichts falsch mit diesem. Wenn Rails mit einer polymorphen Assoziation zu tun hat und das Objekt, das assoziiert wird, STI verwendet, verwendet es einfach die Basisklasse als Typ (in Ihrem Fall "commentable_type").

Wenn Sie Post und NewsArticle in separaten Tabellen haben, wird der commentable_type offensichtlich als Post bzw. NewsArticle angezeigt.

+0

Wie können Sie die Kommentare von einem NewsArticle abrufen, wenn dies korrekt ist? Ich habe ein ähnliches Problem, bei dem meine Abfrage nichts zurückgibt, weil sie nach dem Basisklassentyp sucht. – sweetroll

1

def commentable_type = (sType) Super (sType.to_s.classify.constantize.base_class.to_s) Ende

Diese Methode kehrt Klasse wie Post, was ist, wenn Sie tun, um die geerbte Klasse speichern möchten Als commentable_type veröffentlichen?

1

Gute Frage. Ich hatte genau das gleiche Problem mit Rails 3.1. Sieht das Problem noch nicht gelöst ist. Offensichtlich ist die Verwendung von polymorphen Assoziationen in Kombination mit der Single Table Inheritance (STI) in Rails ein wenig kompliziert.

Die aktuelle Rails-Dokumentation für Rails 3.2 gibt diesen Rat für polymorphic associations and STI Kombination:

polymorphe Assoziationen in Kombination Verwendung mit einzelner Tabelle Vererbung (STI) ist ein wenig kompliziert. Damit die Zuordnungen zu wie erwartet funktionieren, stellen Sie sicher, dass Sie das Basismodell für die Modelle STI in der Typspalte der polymorphen Assoziation speichern.

In Ihrem Fall wäre das Basismodell "Post", d. H. "Commentable_type" sollte für alle Kommentare "Post" sein.