10

Tôi có vấn đề với mã của tôiSTI và đa hình

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 

Và trên nỗ lực đi lấy ý kiến ​​đối với một số NewsArticle tôi thấy trong nhật ký cái gì đó như

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

Lạ mà "commentable_type" = 'Đăng '. Có gì sai?

PS: Rails 2.3.5 & & ruby ​​1.8.7 (2010/01/10 patchlevel 249) [i686-darwin10]

Trả lời

5

Các commentable_type lĩnh vực cần phải lưu trữ tên của bảng chứa dữ liệu, sau khi hàng đó được tải từ bảng bên phải, loại được kế thừa sẽ được tải từ cột loại trên bài viết bảng.

Vì vậy:

Tại đây, chú thích sẽ trỏ đến bảng nhận xét. Bảng bài đăng, 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"> 

Sau đó, tải NewsArticle, id 1 được tải từ bài đăng và loại đó cho biết NewsArticle.

>> 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" 

Nếu commentable_type tổ chức "NewsArticle" nó sẽ phải nhìn vào lớp học để xác định bàn. Bằng cách này, nó chỉ có thể nhìn vào bàn và lo lắng về loại hình một khi nó được ở đó.

+0

huh ... tên bảng là chính xác, nhưng tên mô hình STI là sai –

+0

Đối với mối quan hệ đa hình, chỉ bảng quan trọng, khi bảng đó được tải, loại thừa kế có thể được xác định. – danivovich

1

Hãy xem phần Liên hợp đa hình của ActiveRecord::Associations API. Có một chút về việc sử dụng các hiệp hội đa hình kết hợp với kế thừa bảng đơn. Theo ví dụ mã thứ hai trong phần đó, tôi nghĩ rằng điều này có thể gần với những gì bạn muốn

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

Về mặt kỹ thuật, thực sự không có gì sai với điều này. Khi Rails đang xử lý một liên kết đa hình và đối tượng đang được liên kết đang sử dụng STI, nó đơn giản sử dụng lớp cơ sở làm kiểu (trong trường hợp của bạn là "commentable_type").

Nếu bạn có Bài đăng và NewsArticle trong các bảng riêng biệt, rõ ràng là commentable_type sẽ hiển thị dưới dạng Bài đăng và NewsArticle tương ứng.

+0

Làm cách nào bạn có thể truy xuất các nhận xét từ NewsArticle nếu điều này là chính xác? Tôi gặp vấn đề tương tự khi truy vấn của tôi không trả về gì vì nó đang tìm kiếm loại lớp cơ sở. – sweetroll

1

def commentable_type = (stype) siêu (sType.to_s.classify.constantize.base_class.to_s) cuối

Phương pháp này đang trở lại lớp như bài viết, những việc cần làm nếu bạn muốn để lưu trữ các lớp được thừa kế Đăng dưới dạng commentable_type?

1

Câu hỏi hay. Tôi đã có chính xác cùng một vấn đề bằng cách sử dụng Rails 3.1. Có vẻ như vấn đề vẫn chưa được giải quyết. Rõ ràng, việc sử dụng các hiệp hội đa hình kết hợp với Thừa kế bảng đơn (STI) trong Rails là một chút phức tạp.

Tài liệu Rails hiện tại cho Rails 3.2 đưa ra lời khuyên này để kết hợp polymorphic associations and STI:

Sử dụng các hiệp hội đa hình kết hợp với bảng duy nhất thừa kế (STI) là một chút khéo léo. Để các hiệp hội được hoạt động như mong đợi, hãy đảm bảo rằng bạn lưu trữ mô hình cơ sở cho các mô hình STI trong cột loại của liên kết đa hình.

Trong trường hợp của bạn, mô hình cơ sở sẽ là "Đăng", nghĩa là "commentable_type" phải là "Đăng" cho tất cả các nhận xét.