How to create a two-to-many-to-many relationship in Rails?

Suppose we have a site for photography. Any author can subscribe to receive updates from any other author. Obviously, if author A is subscribed to author B, this does not mean that B is subscribed to A. Thus, we create models

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

So we can use

  • some_author.subscribed_by_author - a list of authors that some_author subscribed to.
  • For any subscription, we can find out both ends (who subscribed to them)

But the question is how to get a list of people subscribing to some author using only rails (not using plain SQL). Get the answer to the question: "Who subscribed to some_author?"

: Rails , , some_author.subscribed_BY_author, some_author_subscribed_TO_author? , ?

P.S.

  • , "direction"
  • 2 .
  • has_many: signed_BY_author,: through = > : subscriptions,,,,,,,,,,,,

    has_many: signed_TO_author,: through = > : subscriptions,,,,,,,,,,,,,,

, .

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

- !:)

0

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 -%>
+2

All Articles