synamoid 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,106 +0,0 @@
1
- # encoding: utf-8
2
- require 'dynamoid/associations/association'
3
- require 'dynamoid/associations/single_association'
4
- require 'dynamoid/associations/many_association'
5
- require 'dynamoid/associations/has_many'
6
- require 'dynamoid/associations/belongs_to'
7
- require 'dynamoid/associations/has_one'
8
- require 'dynamoid/associations/has_and_belongs_to_many'
9
-
10
- module Dynamoid
11
-
12
- # Connects models together through the magic of associations. We enjoy four different kinds of associations presently:
13
- # * belongs_to
14
- # * has_and_belongs_to_many
15
- # * has_many
16
- # * has_one
17
- module Associations
18
- extend ActiveSupport::Concern
19
-
20
- # Create the association tracking attribute and initialize it to an empty hash.
21
- included do
22
- class_attribute :associations
23
-
24
- self.associations = {}
25
- end
26
-
27
- module ClassMethods
28
-
29
- # create a has_many association for this document.
30
- #
31
- # @param [Symbol] name the name of the association
32
- # @param [Hash] options options to pass to the association constructor
33
- # @option options [Class] :class the target class of the has_many association; that is, the belongs_to class
34
- # @option options [Symbol] :class_name the name of the target class of the association; that is, the name of the belongs_to class
35
- # @option options [Symbol] :inverse_of the name of the association on the target class; that is, if the class has a belongs_to association, the name of that association
36
- #
37
- # @since 0.2.0
38
- def has_many(name, options = {})
39
- association(:has_many, name, options)
40
- end
41
-
42
- # create a has_one association for this document.
43
- #
44
- # @param [Symbol] name the name of the association
45
- # @param [Hash] options options to pass to the association constructor
46
- # @option options [Class] :class the target class of the has_one association; that is, the belongs_to class
47
- # @option options [Symbol] :class_name the name of the target class of the association; that is, the name of the belongs_to class
48
- # @option options [Symbol] :inverse_of the name of the association on the target class; that is, if the class has a belongs_to association, the name of that association
49
- #
50
- # @since 0.2.0
51
- def has_one(name, options = {})
52
- association(:has_one, name, options)
53
- end
54
-
55
- # create a belongs_to association for this document.
56
- #
57
- # @param [Symbol] name the name of the association
58
- # @param [Hash] options options to pass to the association constructor
59
- # @option options [Class] :class the target class of the has_one association; that is, the has_many or has_one class
60
- # @option options [Symbol] :class_name the name of the target class of the association; that is, the name of the has_many or has_one class
61
- # @option options [Symbol] :inverse_of the name of the association on the target class; that is, if the class has a has_many or has_one association, the name of that association
62
- #
63
- # @since 0.2.0
64
- def belongs_to(name, options = {})
65
- association(:belongs_to, name, options)
66
- end
67
-
68
- # create a has_and_belongs_to_many association for this document.
69
- #
70
- # @param [Symbol] name the name of the association
71
- # @param [Hash] options options to pass to the association constructor
72
- # @option options [Class] :class the target class of the has_and_belongs_to_many association; that is, the belongs_to class
73
- # @option options [Symbol] :class_name the name of the target class of the association; that is, the name of the belongs_to class
74
- # @option options [Symbol] :inverse_of the name of the association on the target class; that is, if the class has a belongs_to association, the name of that association
75
- #
76
- # @since 0.2.0
77
- def has_and_belongs_to_many(name, options = {})
78
- association(:has_and_belongs_to_many, name, options)
79
- end
80
-
81
- private
82
-
83
- # create getters and setters for an association.
84
- #
85
- # @param [Symbol] symbol the type (:has_one, :has_many, :has_and_belongs_to_many, :belongs_to) of the association
86
- # @param [Symbol] name the name of the association
87
- # @param [Hash] options options to pass to the association constructor; see above for all valid options
88
- #
89
- # @since 0.2.0
90
- def association(type, name, options = {})
91
- field "#{name}_ids".to_sym, :set
92
- self.associations[name] = options.merge(:type => type)
93
- define_method(name) do
94
- @associations[:"#{name}_ids"] ||= Dynamoid::Associations.const_get(type.to_s.camelcase).new(self, name, options)
95
- end
96
- define_method("#{name}=".to_sym) do |objects|
97
- @associations[:"#{name}_ids"] ||= Dynamoid::Associations.const_get(type.to_s.camelcase).new(self, name, options)
98
- @associations[:"#{name}_ids"].setter(objects)
99
- end
100
- end
101
- end
102
-
103
-
104
- end
105
-
106
- end
@@ -1,116 +0,0 @@
1
- # encoding: utf-8
2
- module Dynamoid #:nodoc:
3
-
4
- # The base association module which all associations include. Every association has two very important components: the source and
5
- # the target. The source is the object which is calling the association information. It always has the target_ids inside of an attribute on itself.
6
- # The target is the object which is referencing by this association.
7
- module Associations
8
- module Association
9
- attr_accessor :name, :options, :source, :loaded
10
-
11
- # Create a new association.
12
- #
13
- # @param [Class] source the source record of the association; that is, the record that you already have
14
- # @param [Symbol] name the name of the association
15
- # @param [Hash] options optional parameters for the association
16
- # @option options [Class] :class the target class of the association; that is, the class to which the association objects belong
17
- # @option options [Symbol] :class_name the name of the target class of the association; only this or Class is necessary
18
- # @option options [Symbol] :inverse_of the name of the association on the target class
19
- #
20
- # @return [Dynamoid::Association] the actual association instance itself
21
- #
22
- # @since 0.2.0
23
- def initialize(source, name, options)
24
- @name = name
25
- @options = options
26
- @source = source
27
- @loaded = false
28
- end
29
-
30
- def loaded?
31
- @loaded
32
- end
33
-
34
- def find_target
35
- end
36
-
37
- def target
38
- unless loaded?
39
- @target = find_target
40
- @loaded = true
41
- end
42
-
43
- @target
44
- end
45
-
46
- def reset
47
- @target = nil
48
- @loaded = false
49
- end
50
-
51
- private
52
-
53
- # The target class name, either inferred through the association's name or specified in options.
54
- #
55
- # @since 0.2.0
56
- def target_class_name
57
- options[:class_name] || name.to_s.classify
58
- end
59
-
60
- # The target class, either inferred through the association's name or specified in options.
61
- #
62
- # @since 0.2.0
63
- def target_class
64
- options[:class] || target_class_name.constantize
65
- end
66
-
67
- # The target attribute: that is, the attribute on each object of the association that should reference the source.
68
- #
69
- # @since 0.2.0
70
- def target_attribute
71
- "#{target_association}_ids".to_sym if target_association
72
- end
73
-
74
- # The ids in the target association.
75
- #
76
- # @since 0.2.0
77
- def target_ids
78
- target.send(target_attribute) || Set.new
79
- end
80
-
81
- # The ids in the target association.
82
- #
83
- # @since 0.2.0
84
- def source_class
85
- source.class
86
- end
87
-
88
- # The source's association attribute: the name of the association with _ids afterwards, like "users_ids".
89
- #
90
- # @since 0.2.0
91
- def source_attribute
92
- "#{name}_ids".to_sym
93
- end
94
-
95
- # The ids in the source association.
96
- #
97
- # @since 0.2.0
98
- def source_ids
99
- source.send(source_attribute) || Set.new
100
- end
101
-
102
- # Create a new instance of the target class without trying to add it to the association. This creates a base, that caller can update before setting or adding it.
103
- #
104
- # @param [Hash] attribute hash for the new object
105
- #
106
- # @return [Dynamoid::Document] the newly-created object
107
- #
108
- # @since 1.1.1
109
- def build(attributes = {})
110
- target_class.build(attributes)
111
- end
112
-
113
- end
114
- end
115
-
116
- end
@@ -1,44 +0,0 @@
1
- # encoding: utf-8
2
- module Dynamoid #:nodoc:
3
-
4
- # The belongs_to association. For belongs_to, we reference only a single target instead of multiple records; that target is the
5
- # object to which the association object is associated.
6
- module Associations
7
- class BelongsTo
8
- include SingleAssociation
9
-
10
- private
11
-
12
- # Find the target association, either has_many or has_one. Uses either options[:inverse_of] or the source class name and default parsing to
13
- # return the most likely name for the target association.
14
- #
15
- # @since 0.2.0
16
- def target_association
17
- has_many_key_name = options[:inverse_of] || source.class.to_s.underscore.pluralize.to_sym
18
- has_one_key_name = options[:inverse_of] || source.class.to_s.underscore.to_sym
19
- if !target_class.associations[has_many_key_name].nil?
20
- return has_many_key_name if target_class.associations[has_many_key_name][:type] == :has_many
21
- end
22
-
23
- if !target_class.associations[has_one_key_name].nil?
24
- return has_one_key_name if target_class.associations[has_one_key_name][:type] == :has_one
25
- end
26
- end
27
-
28
- # Associate a source object to this association.
29
- #
30
- # @since 0.2.0
31
- def associate_target(object)
32
- object.update_attribute(target_attribute, target_ids.merge(Array(source.hash_key)))
33
- end
34
-
35
- # Disassociate a source object from this association.
36
- #
37
- # @since 0.2.0
38
- def disassociate_target(object)
39
- source.update_attribute(source_attribute, target_ids - Array(source.hash_key))
40
- end
41
- end
42
- end
43
-
44
- end
@@ -1,40 +0,0 @@
1
- # encoding: utf-8
2
- module Dynamoid #:nodoc:
3
-
4
- # The has and belongs to many association.
5
- module Associations
6
- class HasAndBelongsToMany
7
- include ManyAssociation
8
-
9
- private
10
-
11
- # Find the target association, always another :has_and_belongs_to_many association. Uses either options[:inverse_of] or the source class name
12
- # and default parsing to return the most likely name for the target association.
13
- #
14
- # @since 0.2.0
15
- def target_association
16
- key_name = options[:inverse_of] || source.class.to_s.pluralize.underscore.to_sym
17
- guess = target_class.associations[key_name]
18
- return nil if guess.nil? || guess[:type] != :has_and_belongs_to_many
19
- key_name
20
- end
21
-
22
- # Associate a source object to this association.
23
- #
24
- # @since 0.2.0
25
- def associate_target(object)
26
- ids = object.send(target_attribute) || Set.new
27
- object.update_attribute(target_attribute, ids.merge(Array(source.hash_key)))
28
- end
29
-
30
- # Disassociate a source object from this association.
31
- #
32
- # @since 0.2.0
33
- def disassociate_target(object)
34
- ids = object.send(target_attribute) || Set.new
35
- object.update_attribute(target_attribute, ids - Array(source.hash_key))
36
- end
37
- end
38
- end
39
-
40
- end
@@ -1,39 +0,0 @@
1
- # encoding: utf-8
2
- module Dynamoid #:nodoc:
3
-
4
- # The has_many association.
5
- module Associations
6
- class HasMany
7
- include ManyAssociation
8
-
9
- private
10
-
11
- # Find the target association, always a :belongs_to association. Uses either options[:inverse_of] or the source class name
12
- # and default parsing to return the most likely name for the target association.
13
- #
14
- # @since 0.2.0
15
- def target_association
16
- key_name = options[:inverse_of] || source.class.to_s.singularize.underscore.to_sym
17
- guess = target_class.associations[key_name]
18
- return nil if guess.nil? || guess[:type] != :belongs_to
19
- key_name
20
- end
21
-
22
- # Associate a source object to this association.
23
- #
24
- # @since 0.2.0
25
- def associate_target(object)
26
- object.update_attribute(target_attribute, Set[source.hash_key])
27
- end
28
-
29
- # Disassociate a source object from this association.
30
- #
31
- # @since 0.2.0
32
- def disassociate_target(object)
33
- object.update_attribute(target_attribute, nil)
34
- end
35
-
36
- end
37
- end
38
-
39
- end
@@ -1,39 +0,0 @@
1
- # encoding: utf-8
2
- module Dynamoid #:nodoc:
3
-
4
- # The HasOne association.
5
- module Associations
6
- class HasOne
7
- include Association
8
- include SingleAssociation
9
-
10
- private
11
-
12
- # Find the target association, always a :belongs_to association. Uses either options[:inverse_of] or the source class name
13
- # and default parsing to return the most likely name for the target association.
14
- #
15
- # @since 0.2.0
16
- def target_association
17
- key_name = options[:inverse_of] || source.class.to_s.singularize.underscore.to_sym
18
- guess = target_class.associations[key_name]
19
- return nil if guess.nil? || guess[:type] != :belongs_to
20
- key_name
21
- end
22
-
23
- # Associate a source object to this association.
24
- #
25
- # @since 0.2.0
26
- def associate_target(object)
27
- object.update_attribute(target_attribute, Set[source.hash_key])
28
- end
29
-
30
- # Disassociate a source object from this association.
31
- #
32
- # @since 0.2.0
33
- def disassociate_target(object)
34
- source.update_attribute(source_attribute, nil)
35
- end
36
- end
37
- end
38
-
39
- end
@@ -1,193 +0,0 @@
1
- # encoding: utf-8
2
- module Dynamoid #:nodoc:
3
-
4
- module Associations
5
- module ManyAssociation
6
- include Association
7
-
8
- attr_accessor :query
9
-
10
- def initialize(*args)
11
- @query = {}
12
- super
13
- end
14
-
15
- include Enumerable
16
- # Delegate methods to the records the association represents.
17
- delegate :first, :last, :empty?, :size, :class, :to => :records
18
-
19
- # The records associated to the source.
20
- #
21
- # @return the association records; depending on which association this is, either a single instance or an array
22
- #
23
- # @since 0.2.0
24
- def find_target
25
- Array(target_class.find(source_ids.to_a))
26
- end
27
-
28
- def records
29
- if query.empty?
30
- target
31
- else
32
- results_with_query(target)
33
- end
34
- end
35
-
36
- # Alias convenience methods for the associations.
37
- alias :all :records
38
- alias :count :size
39
- alias :nil? :empty?
40
-
41
- # Delegate include? to the records.
42
- def include?(object)
43
- records.include?(object)
44
- end
45
-
46
- # Deletes an object or array of objects from the association. This removes their records from the association field on the source,
47
- # and attempts to remove the source from the target association if it is detected to exist.
48
- #
49
- # @param [Dynamoid::Document] object the object (or array of objects) to remove from the association
50
- #
51
- # @return [Dynamoid::Document] the deleted object
52
- #
53
- # @since 0.2.0
54
- def delete(object)
55
- source.update_attribute(source_attribute, source_ids - Array(object).collect(&:hash_key))
56
- Array(object).each {|o| self.send(:disassociate_target, o)} if target_association
57
- object
58
- end
59
-
60
-
61
- # Add an object or array of objects to an association. This preserves the current records in the association (if any)
62
- # and adds the object to the target association if it is detected to exist.
63
- #
64
- # @param [Dynamoid::Document] object the object (or array of objects) to add to the association
65
- #
66
- # @return [Dynamoid::Document] the added object
67
- #
68
- # @since 0.2.0
69
- def <<(object)
70
- source.update_attribute(source_attribute, source_ids.merge(Array(object).collect(&:hash_key)))
71
- Array(object).each {|o| self.send(:associate_target, o)} if target_association
72
- object
73
- end
74
-
75
- # Replace an association with object or array of objects. This removes all of the existing associated records and replaces them with
76
- # the passed object(s), and associates the target association if it is detected to exist.
77
- #
78
- # @param [Dynamoid::Document] object the object (or array of objects) to add to the association
79
- #
80
- # @return [Dynamoid::Document] the added object
81
- #
82
- # @since 0.2.0
83
- def setter(object)
84
- target.each {|o| delete(o)}
85
- self << (object)
86
- object
87
- end
88
-
89
- # Create a new instance of the target class and add it directly to the association. If the create fails an exception will be raised.
90
- #
91
- # @param [Hash] attribute hash for the new object
92
- #
93
- # @return [Dynamoid::Document] the newly-created object
94
- #
95
- # @since 0.2.0
96
- def create!(attributes = {})
97
- self << target_class.create!(attributes)
98
- end
99
-
100
- # Create a new instance of the target class and add it directly to the association.
101
- #
102
- # @param [Hash] attribute hash for the new object
103
- #
104
- # @return [Dynamoid::Document] the newly-created object
105
- #
106
- # @since 0.2.0
107
- def create(attributes = {})
108
- self << target_class.create(attributes)
109
- end
110
-
111
- # Create a new instance of the target class and add it directly to the association. If the create fails an exception will be raised.
112
- #
113
- # @param [Hash] attribute hash for the new object
114
- #
115
- # @return [Dynamoid::Document] the newly-created object
116
- #
117
- # @since 0.2.0
118
- def each(&block)
119
- records.each(&block)
120
- end
121
-
122
- # Destroys all members of the association and removes them from the association.
123
- #
124
- # @since 0.2.0
125
- def destroy_all
126
- objs = target
127
- source.update_attribute(source_attribute, nil)
128
- objs.each(&:destroy)
129
- end
130
-
131
- # Deletes all members of the association and removes them from the association.
132
- #
133
- # @since 0.2.0
134
- def delete_all
135
- objs = target
136
- source.update_attribute(source_attribute, nil)
137
- objs.each(&:delete)
138
- end
139
-
140
- # Naive association filtering.
141
- #
142
- # @param [Hash] A hash of attributes; each must match every returned object's attribute exactly.
143
- #
144
- # @return [Dynamoid::Association] the association this method was called on (for chaining purposes)
145
- #
146
- # @since 0.2.0
147
- def where(args)
148
- filtered = clone
149
- filtered.query = query.clone
150
- args.each {|k, v| filtered.query[k] = v}
151
- filtered
152
- end
153
-
154
- # Is this array equal to the association's records?
155
- #
156
- # @return [Boolean] true/false
157
- #
158
- # @since 0.2.0
159
- def ==(other)
160
- records == Array(other)
161
- end
162
-
163
- # Delegate methods we don't find directly to the records array.
164
- #
165
- # @since 0.2.0
166
- def method_missing(method, *args)
167
- if records.respond_to?(method)
168
- records.send(method, *args)
169
- else
170
- super
171
- end
172
- end
173
-
174
- private
175
-
176
- # If a query exists, filter all existing results based on that query.
177
- #
178
- # @param [Array] results the raw results for the association
179
- #
180
- # @return [Array] the filtered results for the query
181
- #
182
- # @since 0.2.0
183
- def results_with_query(results)
184
- results.find_all do |result|
185
- query.all? do |attribute, value|
186
- result.send(attribute) == value
187
- end
188
- end
189
- end
190
-
191
- end
192
- end
193
- end