Skip to content

Instantly share code, notes, and snippets.

@mdeiters
Created May 29, 2009 21:23
Show Gist options
  • Save mdeiters/120213 to your computer and use it in GitHub Desktop.
Save mdeiters/120213 to your computer and use it in GitHub Desktop.
require 'rubygems'
require 'active_record'
require 'spec'
ActiveRecord::Base.establish_connection( {
:adapter => 'mysql',
:host => 'localhost',
:database => 'testbed',
:username => 'root',
:password => ''
})
describe 'association modeling' do
before :all do
ActiveRecord::Migration.instance_eval do
create_table :users, :force => true do |t|
t.string :name
end
create_table :affiliations, :force => true do |t|
t.integer :user_id
t.references :affiliatable, :polymorphic => true
t.string :relationship_type
end
create_table :networks, :force => true do |t|
t.string :name
end
create_table :communities, :force => true do |t|
t.string :name
end
end
end
after :all do
ActiveRecord::Migration.instance_eval do
drop_table :users
drop_table :affiliations
drop_table :networks
drop_table :communities
end
end
class User < ActiveRecord::Base
has_many :affiliations
has_many :communities, :through => :affiliations, :source => :community,
:conditions => "affiliations.affiliatable_type = 'Community'"
has_many :networks, :through => :affiliations,
:conditions => "affiliations.affiliatable_type = 'Network'"
named_scope :in_network, lambda{ |network| {:joins => :networks, :conditions => ['affiliations.affiliatable_id = ?', network]} }
def fellow_members
self.class.scoped({:conditions => [
"users.id IN
(SELECT u.id from users u
INNER JOIN affiliations ON (u.id = affiliations.user_id)
INNER JOIN affiliations my_affiliations ON (affiliations.affiliatable_id = my_affiliations.affiliatable_id AND affiliations.affiliatable_type = 'Community')
WHERE (my_affiliations.user_id = ?))", id]})
end
end
class Affiliation < ActiveRecord::Base
belongs_to :user
belongs_to :affiliatable, :polymorphic => true
belongs_to :community, :class_name => "Community", :foreign_key => "affiliatable_id"
belongs_to :network, :class_name => "Network", :foreign_key => "affiliatable_id"
end
class Network < ActiveRecord::Base
has_many :affiliations, :as => :affiliatable
has_many :users, :through => :affiliations
end
class Community < ActiveRecord::Base
has_many :affiliations, :as => :affiliatable
has_many :users, :through => :affiliations
end
it 'has_many all around' do
me = User.create
network = Network.create
community = Community.create
me.affiliations.create(:affiliatable => network)
me.affiliations.create(:affiliatable => community)
me.should have(2).affiliations
network.should have(1).user
community.should have(1).user
me.should have(1).community
me.should have(1).network
end
it 'can do something special' do
community1 = Community.create
community2 = Community.create
me = User.create(:name => 'ME')
sally = User.create(:name => 'sally')
harry = User.create(:name => 'harry')
me.affiliations.create(:affiliatable => community1)
me.affiliations.create(:affiliatable => community2)
harry.affiliations.create(:affiliatable => community1)
me.fellow_members.should include(harry)
me.fellow_members.should_not include(sally)
sally.affiliations.create(:affiliatable => community2)
me.fellow_members.should include(harry, sally)
end
it 'can do something even better' do
community = Community.create
network = Network.create
me = User.create(:name => 'ME')
sally = User.create(:name => 'sally')
harry = User.create(:name => 'harry')
[me, sally, harry].each{|user| user.affiliations.create(:affiliatable => community) }
[me, sally].each{|user| user.affiliations.create(:affiliatable => network) }
me.networks.should_not be_empty
me.fellow_members.in_network(network).should include(sally)
me.fellow_members.in_network(network).should_not include(harry)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment