A: 

I believe you should use the following:

class User < ActiveRecord::Base
   has_and_belongs_to_many :causes
   has_and_belongs_to_many :campaigns
end

class Cause < ActiveRecord::Base
   has_and_belongs_to_many :users
   has_many :campaigns
end

class Campaign < ActiveRecord::Base
   has_and_belongs_to_many :users
   belongs_to :cause
end

This way you can use

User.causes
User.campaigns

Cause.campaing
Cause.users

Campaign.users
Campaign.cause

You can read here about has_and_belongs_to_many relationship, here about has_one and here about belongs_to.

Let me know if this is what you want :]

Edit:

"I would still need User.campaigns to be campaigns from a user's causes or individual campaigns associated with a user"

You can have a method on users model that returns all campaigns. Something like this:

def all_campaigns
   self.campaigns + self.causes.collect{ |c| c.campaigns }
end
j.
I think it's close. A cause can have many campaigns though. And I would still need User.campaigns to be campaigns from a user's causes or individual campaigns associated with a user...
Dustin Brewer
see my edited answer :]
j.
I think your edited solution will work. I added .flatten.uniq to the returned collection to get rid of duplicates and I think I'm good to go. I really appreciate the help :) - I did use has_many :through instead of has_and_belongs_to_many.
Dustin Brewer
glad it helped ;]
j.
+1  A: 

This should work.

class User < ActiveRecord::Base
  has_many :causes, :through => :cause_users
  has_many :campaigns, :through => :campaign_users
  # other model stuff

class Cause < ActiveRecord::Base
  has_many :users, :through => :cause_users
  has-many :campaigns
  # other model stuff

class Campaign < ActiveRecord::Base
  belongs_to :cause
  has_many :users, :through => :campaign_users
  # other model stuff

class CampaignUser < ActiveRecord::Base
  belongs_to :campaign
  belongs_to :user
  # other model stuff

class CauseUser < ActiveRecord::Base
  belongs_to :cause
  belongs_to :user
  # other model stuff

has_many :through requires that you create a new model for each of these joins: campaign_users and cause_users, as is shown but it provides more functionality later on than has_and_belongs_to_many.

I would also suggest using better names than :campaign_users and :cause_users so the relationship is more meaningful.

Josh Pinter
Why using has_many `"provides more functionality later on than has_and_belongs_to_many"`?
j.
That's what I was originally thinking but it has some holes. Let's say a cause belongs to a user (that has campaigns), how would you inspect the campaigns through that cause through the user? It would be something like User.causes.campaigns BUT I would like to be able to call User.campaigns and find both campaigns from campaign_users and campaigns underneath cause_users for a particular user. Does that make sense?
Dustin Brewer
has_and_belongs_to_many (HABTM) doesn't allow you to have additional information about the relationship. For example, if you were to assign a user's role for a particular campaign (e.g. Leader for one campaign, Secretary for another), you wouldn't be able to do that with HABTM.
Josh Pinter
@Dustin: This sets up a user has_many relationship with campaigns, so you can access the campaigns directly from the user.
Josh Pinter
A: 

You can make :has_many :through associations between users and campaigns using a join model, and also between users and causes using the another join model. The you can make a :has_many :campaigns association in the causes model, putting a :belongs_to :cause in the campaign model.

But you won't be able to fetch all the users campaigns or causes by User.campaigns.orders or User.order.campaigns. You should make an iteration over the User.campaigns collection or User.causes, fetching Campaign.cause or Cause.capaigns. Or even making a custom SQL query, using joins and conditions to filter information in the joins.

Filipe Abreu