Permalink
Browse files

rework definition of methods

  • Loading branch information...
1 parent fa3dd4f commit 8d5e96ae3d1a9ec0c928728c7e39fcb0e92b59b8 @jackdempsey committed Dec 7, 2008
Showing with 74 additions and 62 deletions.
  1. +70 −50 lib/sequel_polymorphic/sequel_polymorphic.rb
  2. +4 −12 spec/sequel_polymorphic/sequel_polymorphic_spec.rb
@@ -3,63 +3,83 @@ module Plugins
module Polymorphic
# Apply the plugin to the model.
def self.apply(model, options = {})
- raise "You must pass in an options hash!" if options.blank?
- plural_model = model.to_s.downcase.pluralize
- singular_model = model.to_s.downcase.singularize
- if as_variable = (options[:belongs_to] or options[:many_to_one])
- # defining the polymorphic model
- model.class_eval %{associate(:many_to_one, :#{as_variable}, :reciprocal=>:#{plural_model},
- :dataset=>(proc { klass = #{as_variable}_type.constantize; klass.filter(klass.primary_key=>#{as_variable}_id) }),
- :eager_loader=>(proc do |key_hash, #{plural_model}, associations|
- id_map = {}
- #{plural_model}.each { |#{singular_model}| #{singular_model}.associations[:#{as_variable}] = nil; ((id_map[#{singular_model}.#{as_variable}_type] ||= {})[#{singular_model}.#{as_variable}_id] ||= []) << #{singular_model} }
- id_map.each do |klass_name, id_map|
- klass = klass_name.constantize
- klass.filter(klass.primary_key=>id_map.keys).all do |related_obj|
- id_map[related_obj.pk].each { |#{singular_model}| #{singular_model}.associations[:#{as_variable}] = related_obj }
- end
- end
- end))
-
- private
-
- def _#{as_variable}=(#{as_variable})
- self[:#{as_variable}_id] = (#{as_variable}.pk if #{as_variable})
- self[:#{as_variable}_type] = (#{as_variable}.class.name if #{as_variable})
- end
- }
- elsif one_to_many_variable = (options[:one_to_many] or options[:has_many])
- raise "You must pass in an :as key-value pair!" unless as_variable = options[:as]
- singular_one_to_many_variable = one_to_many_variable.to_s.singularize
- model.class_eval %{
- associate(:one_to_many, :#{one_to_many_variable}, :key=>:#{as_variable}_id) do |ds|
- ds.filter(:#{as_variable}_type=>'#{model}')
- end
-
- private
-
- def _add_#{singular_one_to_many_variable}(#{singular_one_to_many_variable})
- #{singular_one_to_many_variable}.#{as_variable}_id = pk
- #{singular_one_to_many_variable}.#{as_variable}_type = '#{model}'
- #{singular_one_to_many_variable}.save
- end
- def _remove_#{singular_one_to_many_variable}(#{singular_one_to_many_variable})
- #{singular_one_to_many_variable}.#{as_variable}_id = nil
- #{singular_one_to_many_variable}.#{as_variable}_type = nil
- #{singular_one_to_many_variable}.save
- end
- def _remove_all_#{one_to_many_variable}
- #{singular_one_to_many_variable.capitalize}.filter(:#{as_variable}_id=>pk, :#{as_variable}_type=>'Post').update(:#{as_variable}_id=>nil, :#{as_variable}_type=>nil)
- end
- }
- end
end
module InstanceMethods
end
module ClassMethods
+ def many_to_one(*args, &block)
+ able, options = *args
+ if options[:polymorphic]
+ model = self.class.to_s.downcase
+ plural_model = model.pluralize
+ singular_model = model.singularize
+ self.class_eval %{
+ associate(:many_to_one, :#{able}, :reciprocal=>:#{plural_model},
+ :dataset=>(proc { klass = #{able}_type.constantize; klass.filter(klass.primary_key=>#{able}_id) }),
+ :eager_loader=>(proc do |key_hash, #{plural_model}, associations|
+ id_map = {}
+ #{plural_model}.each do |#{singular_model}|
+ #{singular_model}.associations[:#{able}] = nil;
+ ((id_map[#{singular_model}.#{able}_type] ||= {})[#{singular_model}.#{able}_id] ||= []) << #{singular_model}
+ end
+ id_map.each do |klass_name, id_map|
+ klass = klass_name.constantize
+ klass.filter(klass.primary_key=>id_map.keys).all do |related_obj|
+ id_map[related_obj.pk].each { |#{singular_model}| #{singular_model}.associations[:#{able}] = related_obj }
+ end
+ end
+ end)
+ )
+
+ private
+
+ def _#{able}=(#{able})
+ self[:#{able}_id] = (#{able}.pk if #{able})
+ self[:#{able}_type] = (#{able}.class.name if #{able})
+ end
+ }
+ else
+ associate(:many_to_one, *args, &block)
+ end
+ end
+
+ alias :belongs_to :many_to_one
+
+ def one_to_many(*args, &block)
+ one_to_many_variable, options = *args
+ many_class = one_to_many_variable.to_s.singularize
+ if able = options[:as]
+ self.class_eval %{
+ associate(:one_to_many, :#{one_to_many_variable}, :key=>:#{able}_id) do |ds|
+ ds.filter(:#{able}_type=>'#{self}')
+ end
+
+ private
+
+ def _add_#{many_class}(#{many_class})
+ #{many_class}.#{able}_id = pk
+ #{many_class}.#{able}_type = '#{self}'
+ #{many_class}.save
+ end
+ def _remove_#{many_class}(#{many_class})
+ #{many_class}.#{able}_id = nil
+ #{many_class}.#{able}_type = nil
+ #{many_class}.save
+ end
+ def _remove_all_#{one_to_many_variable}
+ #{many_class.capitalize}.filter(:#{able}_id=>pk, :#{able}_type=>'#{self}').update(:#{able}_id=>nil, :#{able}_type=>nil)
+ end
+ }
+ else
+ associate(:one_to_many, *args, &block)
+ end
+ end
+
+ alias :has_many :one_to_many
+
end # ClassMethods
end # Polymorphic
end # Plugins
@@ -2,19 +2,11 @@
# Models we have: Post(name), Note(name), Asset(name)
describe Sequel::Plugins::Polymorphic do
- it "should raise an error if you call :has_many without providing an :as" do
- lambda do
- class Blowup < Sequel::Model
- is :polymorphic, :has_many => :items
- end
- end.should raise_error
+ it "should add :as to has_many/one_to_many" do
+
end
- it "should raise an error if you call 'is :polymorphic' without any args" do
- lambda do
- class Blowup < Sequel::Model
- is :polymorphic
- end
- end.should raise_error
+ it "should add :polymorphic => true to belongs_to" do
+
end
end

0 comments on commit 8d5e96a

Please sign in to comment.