2012-08-30 44 views
0

我有一個ActiveRecord類:Rails的誤差:的has_many:通過連接

class Post < ActiveRecord::Base 
    has_many :posts_tags 
    has_many :tags, :through => :posts_tags 
end 

class Tag < ActiveRecord::Base 
    has_many :posts_tags 
    has_many :posts, :through => :posts_tags 
end 
class PostsTags < ActiveRecord::Base 
    belongs_to :posts 
    belongs_to :tags 
end 
時,我想交標籤

<% @posts = Post.all %> 
    <% @posts.each do |post| %> 
     <% if post.tags.count != 0 %> 
      <div class="post-tags"> 
      <% post.tags.each do |tag| %> 
      <span><%= tag.name%></span> 
      <%end%> 
      </div>  
     <%end%> 
    <% end %> 

我得到的錯誤uninitialized constant Post::PostsTag 我怎樣才能解決這個問題問題?

回答

1

引用ActiveRecord的文檔:

選擇建立一個多一對多的關係,其方法並不總是簡單的。如果您需要使用關係模型作爲自己的實體,請使用has_many:through。使用has_and_belongs_to_many處理傳統模式時,或者從不直接處理關係本身。

由於看來你只使用PostsTags類的加入,你應該考慮切換到has_and_belongs_to_many

class Post < ActiveRecord::Base 
    has_and_belongs_to_many :tags  # foreign keys in the join table 
end 
class Tag < ActiveRecord::Base 
    has_and_belongs_to_many :posts # foreign keys in the join table 
end 

你應該已經有一個posts_tagspost_idtag_id列從PostsTags類。如果不是,那麼你需要創建一個。除非在聲明關係時爲連接表指定了自定義名稱,否則表必須被命名爲posts_tags。一個可能的遷移可能看起來像:

class CreatePostsTagsJoinTable < ActiveRecord::Migration 
    def change 
    create_table :posts_tags, :id => false do |t| 
     t.integer :post_id 
     t.integer :tag_id 
    end 
    end 
end 

您應該然後用has_and_belongs_to_many關係刪除app/models/posts_tags.rb文件,因爲,「[T]他加入表不應該有一個主鍵或與之相關的模型。」 - ActiveRecord :: Associations :: ClassMethods

documentation for this method提供了更多關於命名連接表和優化性能的信息。

1

傳遞給belongs_to名應該是單數:

belongs_to :post 
belongs_to :tag 

編輯

此外,該模型應該命名爲PostsTag。 ActiveRecord希望所有的模型名稱都是單數,並且以複數形式匹配表名。確保你的表名是'posts_tags'。

+0

我米得到相同的錯誤... – ghkaren

+0

@GhKaren模型名稱是錯誤的。看我的編輯。 – alf

1

你有許多一對多的關係,你應該閱讀A Guide to Active Record Associations

你有什麼沒有很困難,但確實需要一些研究。作爲一個簡單的規則:如果您要使用關聯(例如,您想將描述存儲到PostTag中),請使用以下代碼。如果不是:使用has_and_belongs_to_many已在前面的文章中介紹過。下面一個代碼,與移民,模型和視圖:

class Post < ActiveRecord::Base 
    has_many :post_tags 
    has_many :tags, :through => :post_tags 
end 

class Tag < ActiveRecord::Base 
    has_many :post_tags 
    has_many :posts, :through => :post_tags 
end 

class PostTag < ActiveRecord::Base 
    belongs_to :post 
    belongs_to :tag 
end 

而遷移應該是這個樣子:

class CreateTables < ActiveRecord::Migration 
    def self.up 
    create_table :tags do |t| 
     # some other attributes here 

     t.timestamps 
    end 

    create_table :posts do |t| 
     # some other attributes here 

     t.timestamps 
    end 

    create_table :post_tags do |t| 
     # some other attributes here 
     t.references :post 
     t.references :tag 

     t.timestamps 
    end 
    end 

    def self.down 
    drop_table :tags 
    drop_table :posts 
    drop_table :post_tags 
    end 
end 

而且您認爲應該是這樣的:

<% @posts = Post.all %> 
    <% @posts.each do |post| %> 
     <% if post.tags.any? %> 
      <div class="post-tags"> 
      <% post.tags.each do |tag| %> 
      <span><%= tag.name %></span> 
      <%end%> 
      </div>  
     <%end%> 
    <% end %>