2010-02-14 99 views
5

假設我們有一個攝影網站。任何作者都可以訂閱以接收來自其他作者的更新。顯然,如果一個作者是訂閱筆者B中並不意味着B被預訂A.所以,我們建立模型如何在Rails中創建「雙面」多對多關係?

class Author < ActiveRecord::Base 
    has_many :subscriptions 
    has_many :subscribed_by_author, :through => :subscriptions, :source => :subscribed_to 
end 

class Subscription < ActiveRecord::Base 
    belongs_to :author 
    belongs_to :subscribed_to, :class_name => "Author", :foreign_key => "subscribed_to" 
end 

這樣我們就可以使用

  1. some_author.subscribed_by_author - 列表的作者被some_author訂閱。
  2. 因爲我們可以知道的兩端(誰訂閱了誰)

但問題是,如何讓人們訂閱了一些筆者僅使用軌道列表中的任何訂閱(不使用普通的SQL),即GET答案是:「誰訂閱了some_author?」

問題:在Rails中是否有能力讓雙方的關係能夠工作,即不僅編寫some_author.subscribed_BY_author而且編寫了some_author_subscribed_TO_author?如果有一個,那麼它是什麼?

P.S. subscribed_BY_author:明顯的解決方案是

  1. 更改數據庫的設計,增加了一個名爲列的「方向」
  2. 創建2每個訂閱創建
  3. 加入筆者的模型

    的has_many時間記錄,:through =>:subscriptions,:source =>:subscribed_to,:conditions =>「direction ='by'」

    has_many:subscribed_TO_author,:through =>:subscriptions,:source =>:subscribed_to,:condit '=「方向='到'」

但我不知道是否有一個解決方案,而不改變數據庫設計。

回答

0
# Author model 
has_many :subscriptions_to, :class_name => "Subscription", :foreign_key => "subscribed_to" 
has_many :subscribed_to_author, :through => :subscriptions_to, :source => :author 

據我所知 - 它的工作原理! :)

+0

不幸的是它沒有。但它給了我正確的方向和以下代碼工作 #作者模型 has_many:subscriptions_to,:class_name =>「訂閱」,:foreign_key =>「subscribed_to」 has_many:subscribed_to_author,:through =>:subscriptions_to,:source =>:作者 所以我接受這個答案,但你必須編輯它是正確的第一個:) 謝謝! – 2010-02-14 17:34:44

+0

修理我的喉嚨總是我的榮幸:) – klew 2010-02-14 17:40:45

2

我會使用普通的HABTM來做這樣簡單的事情,但是無論如何你都需要一個連接表。

create_table :subscriptions do |t| 
    t.column :author_id, :integer 
    t.column :subscriber_id, :integer 
end 

點作者給它:

class Author < ActiveRecord::Base 
    has_and_belongs_to_many :subscribers 
    :class_name => "Author", 
    :join_table => "subscriptions", 
    :association_foreign_key => "subscriber_id" 

    def subscriptions # "subscribers" is already included above 
    self.subscribers.find(:all, :subscriber_id=>author.id) # hopefully not too 
    end              # much SQL 
end 

如果你真的致力於爲您的方法名稱:

def subscribed_to_author 
    subscribers 
    end 

    def subscribed_by_author(author) 
    self.subscribers.find(:all, :subscriber_id=>author.id) 
    end 

創建一些連接(我會想辦法讓SubscriptionsController是RESTy)

SubscriptionsController < ApplicationController 
    def create 
    @author = Author.find(params[:author_id] # author to be subscribed to 
    @user = current_user # user clicking the "subscribe" button 

    @author.subscribers << @user # assuming authors should only 
    @author.save     # be able to subscribe themselves 
    end 
end 

顯示名稱,或其他

@author.subscribers.each do |s| 
    s.name 
end 
# ...or...and...also... 
<%= render :partial => @author.subscribers -%> 
<%= render :partial => @author.subscriptions -%> 
+0

謝謝!這非常有幫助。現在我找到了兩種解決問題的方法。 – 2010-02-14 18:12:58

+0

@Sergii,這就是我在回答中所談論的內容,由於Eric的出衆方式,我刪除了該內容。 – 2010-02-14 18:18:44