Module: Sequel::Plugins::Polymorphic::ClassMethods

Defined in:
lib/sequel_polymorphic/sequel_polymorphic.rb

Instance Method Summary collapse

Instance Method Details

#many_to_many(*args, &block) ⇒ Object

example: many_to_many :tags, :through => :taggings, :as => :taggable



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/sequel_polymorphic/sequel_polymorphic.rb', line 87

def many_to_many(*args, &block)
  many_to_class, options = *args # => :tags, :through => :taggings, :as => :taggable
  many_class = many_to_class.to_s.singularize # => tag
  options ||= {}
  if through = (options[:through] or options[:join_table]) and able = options[:as]
    through_klass = through.to_s.singularize.capitalize # => Tagging
    # self in the block passed to associate is an instance of the class, hence the self.class call
    associate(:many_to_many, many_to_class,
              :left_key => "#{able}_id".to_sym,
              :join_table => through) { |ds| ds.filter("#{able}_type".to_sym => self.class.to_s) }

    method_string = %{
      private

      def _add_#{many_class}(#{many_class})
        #{through_klass}.create(:#{many_class}_id => #{many_class}.pk, :#{able}_id => pk, :#{able}_type => '#{self}')
      end

      def _remove_#{many_class}(#{many_class})
        #{through_klass}.filter(:#{many_class}_id => #{many_class}.pk, :#{able}_id => pk, :#{able}_type => '#{self}').delete
      end

      def _remove_all_#{many_to_class}
        #{through_klass}.filter(:#{able}_id=>pk, :#{able}_type=>'#{self}').delete
      end
    }
    self.class_eval method_string
  else
    associate(:many_to_many, *args, &block)
  end
end

#many_to_one(*args, &block) ⇒ Object Also known as: belongs_to



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/sequel_polymorphic/sequel_polymorphic.rb', line 13

def many_to_one(*args, &block)
  able, options = *args
  options ||= {}
  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

#one_to_many(*args, &block) ⇒ Object Also known as: has_many



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/sequel_polymorphic/sequel_polymorphic.rb', line 52

def one_to_many(*args, &block)
  many_of_class, options = *args
  options ||= {}
  many_class = many_of_class.to_s.singularize
  if able = options[:as]
    associate(:one_to_many, many_of_class, :key=>"#{able}_id".to_sym) do |ds|
      ds.filter("#{able}_type".to_sym => self.class.to_s)
    end

     method_definitions = %{
       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_#{many_of_class}
         #{many_class.capitalize}.filter(:#{able}_id=>pk, :#{able}_type=>'#{self}').update(:#{able}_id=>nil, :#{able}_type=>nil)
       end
     }
     self.class_eval method_definitions
  else
    associate(:one_to_many, *args, &block)
  end
end