1

Hello fellow developers! Recently I've been playing with Rails 3.0 and after quite a bit of research I'm kinda stuck. I want to know what approach or solution is the best in my case(I couldn't find an answer yet). So what I'm trying to achieve is simple and straight forward.

I want to do something like this:

class User < ActiveRecord::Base
    has_many :feeds
    has_many :casts, :through => :feeds
end

class Feed < ActiveRecord::Base
  has_many :users
  has_many :casts
end

class Cast < ActiveRecord::Base
  belongs_to :feed
end

So at the end I need to have methods like User.first.feeds to get all the user's feeds and User.first.casts to get all the user's casts through his/her feeds. Also would be nice to have Feed.first.casts and Feed.first.users. Pretty simple, right, but I'm also having a hard time to create migrations for what I'm trying to achieve.

I know that the code above won't work - I've been playing with it so this is just the concept of what I'm trying to achieve.

Basically my questions are: should I do it through join model somehow or use scopes?(also could you give a code snippet) and how do I do migration for that?

Thanks, and sorry I couldn't find much information on the web regarding this simple case.

Edit: has_and_belongs_to_many on User and Feed won't work in my case because it won't allow me to have @user.casts, it gives only @user.feeds and @feed.users

Alex Bush
  • 735
  • 1
  • 13
  • 26

2 Answers2

2

What you want is a many to many relationship between User and Feed.

You'll want something like this in your code for the User and Feed relationship to work.

class User < ActiveRecord::Base
  has_and_belongs_to_many :feeds
end

class Feed < ActiveRecord::Base
  has_and_belongs_to_many :users
end

You can read more about this in the Rails Guides - http://guides.rubyonrails.org/association_basics.html#the-has_and_belongs_to_many-association

You may also want to look at using has_many :through with an intermediate model for this (explained here http://guides.rubyonrails.org/association_basics.html#choosing-between-has_many-through-and-has_and_belongs_to_many) if you'd like to store any meta data for a user-feed relationship record.

Edit: I managed to get a similar setup working on 3.0 as well as 3.1 (using has_many :through).

Here are the contents of my models.

➜  app  cat app/models/*
class Cast < ActiveRecord::Base
  belongs_to :feed
end

class Feed < ActiveRecord::Base
  has_many :subscriptions
  has_many :casts
end

class Subscription < ActiveRecord::Base
  belongs_to :user
  belongs_to :feed
end

class User < ActiveRecord::Base
  has_many :subscriptions
  has_many :feeds, :through => :subscriptions

  # For 3.1
  has_many :casts, :through => :feeds
  # For 3.0
  def casts
    Cast.joins(:feed => :subscriptions).where("subscriptions.user_id" => self.id)
  end
end

and here are the migrations I used

➜  app  cat db/migrate/*
class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :name

      t.timestamps
    end
  end

  def self.down
    drop_table :users
  end
end
class CreateFeeds < ActiveRecord::Migration
  def self.up
    create_table :feeds do |t|
      t.string :name

      t.timestamps
    end
  end

  def self.down
    drop_table :feeds
  end
end
class CreateCasts < ActiveRecord::Migration
  def self.up
    create_table :casts do |t|
      t.string :name
      t.integer :feed_id

      t.timestamps
    end
  end

  def self.down
    drop_table :casts
  end
end
class CreateSubscriptions < ActiveRecord::Migration
  def self.up
    create_table :subscriptions do |t|
      t.integer :feed_id
      t.integer :user_id
    end
  end

  def self.down
    drop_table :subscriptions
  end
end
Dogbert
  • 212,659
  • 41
  • 396
  • 397
  • I've red Rails Guides about it from top to bottom and didn't find the answer. I've already tried has_and_belongs_to_many and it simply gives me @user.feeds and @feed.users methods. What I really need is in addition to those two have @user.casts which will belong to this user through his feeds. – Alex Bush Jun 11 '11 at 21:56
  • Thanks, I've checked with Rails 3.0 and it works nice. I got my @user.casts method. Just one last thing I'm missing - @feed.users, I think I need to add something to Subscription model/migration, right? – Alex Bush Jun 12 '11 at 03:51
  • I haven't tested it, but adding `has_many :users, :through => :subscriptions` to the Feed model should work. There's no need of any migration. – Dogbert Jun 12 '11 at 09:22
0

In http://railscasts.com/episodes/265-rails-3-1-overview Ryan Bates says that rails 3.1 has support for chained has_many :through calls. It's not possible in 3.0

DGM
  • 26,629
  • 7
  • 58
  • 79
  • Ok, so in this case I have two questions: how to achieve something similar in 3.0(using scopes or something) and how do I do migrations if I'll decide to got with 3.1? Thank you. – Alex Bush Jun 11 '11 at 23:34