Skip to content

Instantly share code, notes, and snippets.

@gerred
Created March 5, 2011 00:13
Show Gist options
  • Save gerred/855953 to your computer and use it in GitHub Desktop.
Save gerred/855953 to your computer and use it in GitHub Desktop.
Doubly Polymorphic Join Models, for fun and profit
class Delivery < ActiveRecord::Base
belongs_to :deliverable, :polymorphic => true
belongs_to :receivable, :polymorphic => true
has_many :delivery_impressions
has_many :users, :through => :delivery_impressions
belongs_to :sender, :class_name => 'User', :foreign_key => :sender_id
end
class DeliveryImpression < ActiveRecord::Base
belongs_to :delivery
belongs_to :user
has_one :deliverable, :through => :delivery
end
class User < ActiveRecord::Base
has_many :delivery_impressions
has_many :deliveries, :through => :delivery_impressions
has_many :direct_deliveries, :as => :receivable, :class_name => 'Delivery'
has_many :direct_messages, :through => :direct_deliveries, :as => :deliverable, :source => :deliverable, :source_type => 'Message'
has_many :sent_deliveries, :class_name => 'Delivery', :foreign_key => :sender_id
has_many :ideas, :through => :sent_deliveries, :source => :deliverable, :source_type => 'Idea'
has_many :sent_messages, :through => :sent_deliveries, :source => :deliverable, :source_type => 'Message'
has_many :sent_notifications, :through => :sent_deliveries, :source => :deliverable, :source_type => 'Notification'
def unread_messages
delivery_impressions.where(:read => false).count
end
end
class Project < ActiveRecord::Base
has_friendly_id :title, :use_slug => true
has_many :deliveries, :as => :receivable
has_many :ideas, :through => :deliveries, :as => :deliverable, :source => :deliverable, :source_type => 'Idea'
has_many :messages, :through => :deliveries, :as => :deliverable, :source => :deliverable, :source_type => 'Message'
has_many :notifications, :through => :deliveries, :as => :deliverable, :source => :deliverable, :source_type => 'Notification'
has_one :sender, :through => :delivery, :class_name => 'User'
end
class Idea < ActiveRecord::Base
has_one :delivery, :as => :deliverable
has_one :project, :through => :delivery, :as => :receivable, :source => :receivable, :source_type => 'Project'
has_one :sender, :through => :delivery, :class_name => 'User'
has_many :receipts, :class_name => 'Delivery', :as => :receivable
has_many :replies, :through => :receipts, :as => :deliverable, :source => :deliverable, :source_type => 'Reply'
def unread_replies(user)
DeliveryImpression.joins(:delivery).where('deliverable_type = ? AND receivable_type = ? AND receivable_id = ? AND `delivery_impressions`.read = ? AND user_id = ?', 'Reply', 'Idea', id, false, user).count
end
end
class Message < ActiveRecord::Base
has_one :delivery, :as => :deliverable
has_one :project, :through => :delivery, :as => :receivable, :source => :receivable, :source_type => 'Project'
has_many :direct_users, :through => :delivery, :as => :receivable, :source => :receivable, :source_type => 'User'
has_many :receipts, :class_name => 'Delivery', :as => :receivable
has_many :replies, :through => :receipts, :as => :deliverable, :source => :deliverable, :source_type => 'Reply'
has_one :sender, :through => :delivery, :class_name => 'User'
end
class Reply < ActiveRecord::Base
has_one :delivery, :as => :deliverable
has_one :idea, :through => :delivery, :as => :receivable, :source => :receivable, :source_type => 'Idea'
has_one :message, :through => :delivery, :as => :receivable, :source => :receivable, :source_type => 'Message'
end
class Notification < ActiveRecord::Base
has_one :delivery, :as => :deliverable
has_one :project, :through => :delivery, :as => :receivable, :source => :receivable, :source_type => 'Project'
has_one :sender, :through => :delivery, :class_name => 'User'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment