2012-03-29 61 views
2

我有兩個模型:用戶,文章如何在Rails中定義多個has_and_belongs_to_many?

用戶可以喜歡或不喜歡很多文章,並且文章可以被許多用戶喜歡或不喜歡。所以我需要在它們之間建立一個多對多的關係。

在軌道,我想我需要使用has_and_belongs_to_many ..

我覺得代碼的結構如下圖所示:

class User 
    has_and_belongs_to_many :liked_articles 
    has_and_belongs_to_many :disliked_articles 
end 

class Article 
    has_and_belongs_to_many :liking_users 
    has_and_belongs_to_many :disliking_users 
end 

當然,上面的代碼不起作用。

但我不知道什麼是正確的代碼。誰能幫我?

更新時間:

我想出了這樣的代碼:

class User 
    has_and_belongs_to_many :liked_articles, :class_name => 'Article', :join_table => 'articles_users_like', :uniq => true 
    has_and_belongs_to_many :disliked_articles, :class_name => 'Article', :join_table => 'articles_users_dislike', :uniq => true 
end 

class Article 
    has_and_belongs_to_many :liking_users, :class_name => 'User', :join_table => 'articles_users_like', :uniq => true 
    has_and_belongs_to_many :disliking_users, :class_name => 'User', :join_table => 'articles_users_dislike', :uniq => true 
end 

我認爲它會工作。

但正如Peter Sobot和Jon McIntosh所說,現在has_many,:through是更優選的。你能告訴我爲什麼嗎? 後者在邏輯上比has_and_belongs_to更清晰?

回答

4

這些關聯方法與模型綁定。除非您有Liking_UserDisliking_User型號,否則這顯然不起作用。除此之外,我相信你會以錯誤的方式去做。

讓我們暫時解決這個問題。你有一個User和一個Article。您的Article需要功能爲不喜歡讚了Users,對不對?我將把它看作是一種類似於SO/Reddit信譽系統,並且假設User可以就像不喜歡Article一次。爲此,我將創建一個單獨的投票模型,稱爲Votes,並將其與has_many, :through關聯關聯起來。

User.rb

class User < ActiveRecord::Base 
    has_many :votes 
    has_many :articles, :through => :votes 
    end 

Article.rb

class Article < ActiveRecord::Base 
    has_many :votes 
    has_many :users, :through => :votes 
    end 

投票。RB

class Vote < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :article 
    end 

現在,這些協會都成立,該機型將要尋找數據庫中的幾個字段。結構看起來應該是這樣的:

Users 
+----+-----------+ 
| id | user_name | 
+----+-----------+  

Articles 
+----+--------+ 
| id | title | 
+----+--------+ 

Votes 
+----+----------+------------+-------+ 
| id | user_id | article_id | value | 
+----+----------+------------+-------+ 

這樣就通過給模型一個ID引用來完成關聯。現在,當你創建一個投票項,你可以親眼目睹神奇的鐵軌...

class ArticlesController < ApplicationController 
    def like 
    @article = Article.find(params[:article_id]) 
    @article.votes.create(:user_id => current_user, :value => 1) 

    respond_to do |format| 
     if @article.save 
     format.html { redirect_to @article, notice: 'Article was successfully liked.' } 
     format.json { head :no_content } 
     else 
     format.html { redirect_to @article, notice: 'Article was unsuccessfully liked.' } 
     format.json { render json: @article.errors, status: :unprocessable_entity } 
     end 
    end 

    end 
end 

編輯:每您的評論中,has_and_belongs_to_manyhas_many :through關係非常相似......你有兩個模型和一個連接表保存參考數據。兩者之間的區別在於,has_many :through需要第三個與關係(如說,用戶/文章/投票)之間交互的模型。

has_many :through被廣泛推薦的原因是它更加靈活,您可以更多地使用而不是後者。在你的情況下,你必須創建這種關係,因爲你需要第三個模型來計票。

您現在正在遵循的邏輯創建一個委託人來創建四個模型,並且需要根據用戶想要採取的操作更新特定的模型。這絕對不是軌道(或任何邏輯)的做事方式。把事情簡單化。

Ruby on Rails Guides: A Guide to Active Record Associations

+0

你的回答很清楚。但我仍然有一個問題。我已更新問題,請檢查〜:) – HanXu 2012-03-30 04:26:29

+0

編輯我的回覆 – 2012-03-30 06:08:49

+0

太棒了!謝謝! – HanXu 2012-03-30 09:39:35

3

has_and_belongs_to_many現在被認爲有些過時 - 在這種情況下您可能想要使用has_many :through。考慮使用一個表的「票」,做這樣的事情:

class User < ActiveRecord:Base 
    has_many :votes 
    has_many :articles, :through => :votes 
end 

class Article < ActiveRecord:Base 
    has_many :votes 
    has_many :users, :through => :votes 
end 

class Vote < ActiveRecord:Base 
    belongs_to :article 
    belongs_to :user 
end 

然後,您可以一「號」字段添加到vote顯示,如果它是一個給予好評或downvote,然後在該過濾器。

+0

謝謝:)。我已經更新了這個問題。檢查它〜 – HanXu 2012-03-30 04:25:52

相關問題