Created
March 18, 2011 00:13
-
-
Save diebels727/875399 to your computer and use it in GitHub Desktop.
Super-Meta-Polymorphic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Where the associations table has sourcable_id,sourcable_type,targetable_id,targetable_type | |
class Association < ActiveRecord::Base | |
include Relatable | |
belongs_to_association :sourcable => :sourcable, :targetable => :targetable | |
end | |
#OR _any_ table that we want to be an association table can become one (if the source and target id and type columns do not exist, then the mixin creates them) | |
class AssociationTables < ActiveRecord::Base | |
include Relatable | |
belongs_to_association :sourcable => :left_side, :targetable => :right_side | |
end | |
#Old stuff below.... | |
#Where the association looks like: | |
# sourcable_id: <email_id>, sourcable_type: Email, targetable_id: <phile_id>, targetable_type: Phile | |
# | |
# | |
#What I think may be an easy solution is to write a dynamic extension to implement sourcable or targetable on a per-instance basis: | |
# | |
#For example: | |
# e = Email.new | |
# e.targetable | |
# e.associations << a | |
# | |
# Which enables this instance of Email to be an association target; which would allow us to do something like this: | |
# | |
# e = Email.new | |
# e.targetable | |
# e.associations << a | |
# e = Email.new | |
# e.sourcable | |
# e.associations << a | |
# | |
# Still doesn't enable e.sources or e.targets (or perhaps e.linked_to?) | |
# | |
# To accomplish this, I was looking in to using the dynamic finders -- So, Association.where(:sourcable_type => Email). This does return all of the | |
# email associations that are sources. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Which allows email.associations << a | |
class Email < ActiveRecord::Base | |
include Relatable | |
acts_as_association :associations, :as => :sourcable | |
end | |
#OR | |
class Email < ActiveRecord::Base | |
include Relatable | |
acts_as_association :association_tables, :as => :left_side | |
end | |
#So long as you have build the tables model w/ belongs_to_association :sourcable => :left_side, :targetable => :right_side |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Which allows phile.associations << a | |
class Phile < ActiveRecord::Base | |
include Relatable | |
acts_as_association :associations, :as => :targetable | |
end | |
#OR | |
class Phile < ActiveRecord::Base | |
include Relatable | |
acts_as_association :association_tables, :as => :right_side | |
end | |
#And now that we're super-polymorphic we can even state: | |
class Phile < ActiveRecord::Base | |
include Relatabe | |
acts_as_association :associations, :as => :targetable | |
acts_as_association :association_tables, :as => right_side | |
end | |
Phile | |
----- | |
|id| | |
| 1| | |
Associations | |
------------ | |
|id|sourcable_id|sourcable_type|targetable_id|targetable_type| | |
|10| | | 1| Phile| | |
AssociationTables | |
----------------- | |
|id|left_id|left_type|left_id|left_type| | |
|10| | | 1| Phile| | |
p.associations => all associations for this instance of Phile | |
r = Association.where(:targetable_type => 'Phile') => all associations of type Phile | |
l = Association.where(:sourcable_type => 'Phile') => all associations of type Phile | |
r + l => union (e.g. ALL associations of type Phile) | |
rt = AssociationTables.where(:targetable_type => 'Phile') | |
lt = AssociationTables.where(:sourcable_type => 'Phile) | |
rt + lt + r + l => All associations of type Phile across both tables |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Relatable | |
module ClassMethods | |
#acts_as_association <whatever I belong to>, :as => <key for left or right side> | |
def acts_as_association(associations,relationship) | |
Rails.logger.debug("DEBUG: #{self}") | |
self.class_eval( "has_many \"#{associations.to_sym}\", :as => \"#{(relationship[:as].to_sym)}\"" ) | |
end | |
#belongs_to_association :sourcable => <key for left side>,:targetable => <key for right side> | |
def belongs_to_association(relationships) | |
(sourcable,targetable) = relationships[:sourcable],relationships[:targetable] | |
#Better way to handle this is to not generate any exceptions | |
begin | |
#Keys are generated dynamically | |
add_association_columns( (sourcable.to_s+"_id").to_sym => :integer , (sourcable.to_s+"_type").to_sym => :string, | |
(targetable.to_s+"_id").to_sym => :integer, (targetable.to_s+"_type").to_sym => :string ) | |
rescue Exception => e | |
Rails.logger.debug( "Columns already exist for #{sourcable} and #{targetable}" ) | |
end | |
self.class_eval( "belongs_to \"#{sourcable}\", :polymorphic => true\n | |
belongs_to \"#{targetable}\", :polymorphic => true" ) | |
end | |
#Columns are generated via dynamic migration; so now our 'association' truly is polymorphic | |
def add_association_columns(association_columns) | |
association_columns.each { |k,v| ActiveRecord::Migration::add_column self.to_s.tableize.to_sym, k, v } | |
end | |
end | |
def instance_acts_as_association(associations,relationship) | |
Rails.logger.debug("DEBUG: #{self}") | |
end | |
def self.included(base) | |
base.extend(ClassMethods) | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment