dynamoid 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Dynamoid.gemspec +65 -3
- data/Gemfile +3 -0
- data/Gemfile.lock +6 -0
- data/README.markdown +117 -22
- data/Rakefile +22 -9
- data/VERSION +1 -1
- data/doc/.nojekyll +0 -0
- data/doc/Dynamoid.html +300 -0
- data/doc/Dynamoid/Adapter.html +1387 -0
- data/doc/Dynamoid/Adapter/AwsSdk.html +1561 -0
- data/doc/Dynamoid/Adapter/Local.html +1487 -0
- data/doc/Dynamoid/Associations.html +131 -0
- data/doc/Dynamoid/Associations/Association.html +1706 -0
- data/doc/Dynamoid/Associations/BelongsTo.html +339 -0
- data/doc/Dynamoid/Associations/ClassMethods.html +723 -0
- data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +339 -0
- data/doc/Dynamoid/Associations/HasMany.html +339 -0
- data/doc/Dynamoid/Associations/HasOne.html +339 -0
- data/doc/Dynamoid/Components.html +202 -0
- data/doc/Dynamoid/Config.html +395 -0
- data/doc/Dynamoid/Config/Options.html +609 -0
- data/doc/Dynamoid/Criteria.html +131 -0
- data/doc/Dynamoid/Criteria/Chain.html +759 -0
- data/doc/Dynamoid/Criteria/ClassMethods.html +98 -0
- data/doc/Dynamoid/Document.html +512 -0
- data/doc/Dynamoid/Document/ClassMethods.html +581 -0
- data/doc/Dynamoid/Errors.html +118 -0
- data/doc/Dynamoid/Errors/DocumentNotValid.html +210 -0
- data/doc/Dynamoid/Errors/Error.html +130 -0
- data/doc/Dynamoid/Errors/InvalidField.html +133 -0
- data/doc/Dynamoid/Errors/MissingRangeKey.html +133 -0
- data/doc/Dynamoid/Fields.html +649 -0
- data/doc/Dynamoid/Fields/ClassMethods.html +264 -0
- data/doc/Dynamoid/Finders.html +128 -0
- data/doc/Dynamoid/Finders/ClassMethods.html +502 -0
- data/doc/Dynamoid/Indexes.html +308 -0
- data/doc/Dynamoid/Indexes/ClassMethods.html +351 -0
- data/doc/Dynamoid/Indexes/Index.html +1089 -0
- data/doc/Dynamoid/Persistence.html +653 -0
- data/doc/Dynamoid/Persistence/ClassMethods.html +568 -0
- data/doc/Dynamoid/Validations.html +399 -0
- data/doc/_index.html +439 -0
- data/doc/class_list.html +47 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +55 -0
- data/doc/css/style.css +322 -0
- data/doc/file.LICENSE.html +66 -0
- data/doc/file.README.html +279 -0
- data/doc/file_list.html +52 -0
- data/doc/frames.html +13 -0
- data/doc/index.html +279 -0
- data/doc/js/app.js +205 -0
- data/doc/js/full_list.js +173 -0
- data/doc/js/jquery.js +16 -0
- data/doc/method_list.html +1054 -0
- data/doc/top-level-namespace.html +105 -0
- data/lib/dynamoid.rb +2 -1
- data/lib/dynamoid/adapter.rb +77 -6
- data/lib/dynamoid/adapter/aws_sdk.rb +96 -16
- data/lib/dynamoid/adapter/local.rb +84 -15
- data/lib/dynamoid/associations.rb +53 -4
- data/lib/dynamoid/associations/association.rb +154 -26
- data/lib/dynamoid/associations/belongs_to.rb +32 -6
- data/lib/dynamoid/associations/has_and_belongs_to_many.rb +29 -3
- data/lib/dynamoid/associations/has_many.rb +30 -4
- data/lib/dynamoid/associations/has_one.rb +26 -3
- data/lib/dynamoid/components.rb +7 -5
- data/lib/dynamoid/config.rb +15 -2
- data/lib/dynamoid/config/options.rb +8 -0
- data/lib/dynamoid/criteria.rb +7 -2
- data/lib/dynamoid/criteria/chain.rb +55 -8
- data/lib/dynamoid/document.rb +68 -7
- data/lib/dynamoid/errors.rb +17 -2
- data/lib/dynamoid/fields.rb +44 -1
- data/lib/dynamoid/finders.rb +32 -6
- data/lib/dynamoid/indexes.rb +22 -2
- data/lib/dynamoid/indexes/index.rb +48 -7
- data/lib/dynamoid/persistence.rb +111 -51
- data/lib/dynamoid/validations.rb +36 -0
- data/spec/app/models/address.rb +2 -1
- data/spec/app/models/camel_case.rb +11 -0
- data/spec/app/models/magazine.rb +4 -1
- data/spec/app/models/sponsor.rb +3 -1
- data/spec/app/models/subscription.rb +5 -1
- data/spec/app/models/user.rb +10 -1
- data/spec/dynamoid/associations/association_spec.rb +67 -1
- data/spec/dynamoid/associations/belongs_to_spec.rb +16 -1
- data/spec/dynamoid/associations/has_and_belongs_to_many_spec.rb +7 -0
- data/spec/dynamoid/associations/has_many_spec.rb +14 -0
- data/spec/dynamoid/associations/has_one_spec.rb +10 -1
- data/spec/dynamoid/criteria_spec.rb +5 -1
- data/spec/dynamoid/document_spec.rb +23 -3
- data/spec/dynamoid/fields_spec.rb +10 -1
- data/spec/dynamoid/indexes/index_spec.rb +19 -0
- data/spec/dynamoid/persistence_spec.rb +24 -0
- data/spec/dynamoid/validations_spec.rb +36 -0
- metadata +105 -4
@@ -1,18 +1,37 @@
|
|
1
1
|
module Dynamoid
|
2
2
|
module Adapter
|
3
|
+
|
4
|
+
# This gimpy hash construct should be equivalent to Amazon's actual DynamoDB, for offline development.
|
5
|
+
# All tests pass with either this or connecting to the real DynamoDB, and that's good enough for me.
|
3
6
|
module Local
|
4
7
|
extend self
|
5
|
-
|
6
|
-
|
8
|
+
|
9
|
+
# The hash holding all of our data.
|
10
|
+
#
|
11
|
+
# @return [Hash] a hash of raw values
|
12
|
+
#
|
13
|
+
# @since 0.2.0
|
7
14
|
def data
|
8
15
|
@data ||= {}
|
9
16
|
end
|
10
17
|
|
18
|
+
# A convenience method for testing that destroys all table data without destroying their structure.
|
19
|
+
#
|
20
|
+
# @since 0.2.0
|
11
21
|
def reset_data
|
12
22
|
self.data.each {|k, v| v[:data] = {}}
|
13
23
|
end
|
14
24
|
|
15
|
-
#
|
25
|
+
# Get many items at once from the hash.
|
26
|
+
#
|
27
|
+
# @example Retrieve IDs 1 and 2 from the table testtable
|
28
|
+
# Dynamoid::Adapter::Local.batch_get_item('table1' => ['1', '2'])
|
29
|
+
#
|
30
|
+
# @param [Hash] options the hash of tables and IDs to retrieve
|
31
|
+
#
|
32
|
+
# @return [Hash] a hash where keys are the table names and the values are the retrieved items
|
33
|
+
#
|
34
|
+
# @since 0.2.0
|
16
35
|
def batch_get_item(options)
|
17
36
|
Hash.new { |h, k| h[k] = Array.new }.tap do |hash|
|
18
37
|
options.each do |table_name, keys|
|
@@ -30,24 +49,48 @@ module Dynamoid
|
|
30
49
|
end
|
31
50
|
end
|
32
51
|
|
33
|
-
#
|
52
|
+
# Create a table.
|
53
|
+
#
|
54
|
+
# @param [String] table_name the name of the table to create
|
55
|
+
# @param [Symbol] key the table's primary key (defaults to :id)
|
56
|
+
# @param [Hash] options provide a range_key here if you want one for the table
|
57
|
+
#
|
58
|
+
# @since 0.2.0
|
34
59
|
def create_table(table_name, key, options = {})
|
35
60
|
data[table_name] = {:hash_key => key, :range_key => options[:range_key], :data => {}}
|
36
61
|
end
|
37
62
|
|
38
|
-
#
|
63
|
+
# Removes an item from the hash.
|
64
|
+
#
|
65
|
+
# @param [String] table_name the name of the table
|
66
|
+
# @param [String] key the hash key of the item to delete
|
67
|
+
# @param [Number] range_key the range key of the item to delete, required if the table has a composite key
|
68
|
+
#
|
69
|
+
# @since 0.2.0
|
39
70
|
def delete_item(table_name, key, range_key = nil)
|
40
71
|
data[table_name][:data].delete("#{key}.#{range_key}")
|
41
72
|
end
|
42
73
|
|
43
|
-
#
|
74
|
+
# Deletes an entire table from the hash.
|
75
|
+
#
|
76
|
+
# @param [String] table_name the name of the table to destroy
|
77
|
+
#
|
78
|
+
# @since 0.2.0
|
44
79
|
def delete_table(table_name)
|
45
80
|
data.delete(table_name)
|
46
81
|
end
|
47
82
|
|
48
|
-
# DescribeTable
|
83
|
+
# @todo Add a DescribeTable method.
|
49
84
|
|
50
|
-
#
|
85
|
+
# Fetches an item from the hash.
|
86
|
+
#
|
87
|
+
# @param [String] table_name the name of the table
|
88
|
+
# @param [String] key the hash key of the item to find
|
89
|
+
# @param [Number] range_key the range key of the item to find, required if the table has a composite key
|
90
|
+
#
|
91
|
+
# @return [Hash] a hash representing the raw item
|
92
|
+
#
|
93
|
+
# @since 0.2.0
|
51
94
|
def get_item(table_name, key, range_key = nil)
|
52
95
|
if data[table_name][:data]
|
53
96
|
data[table_name][:data]["#{key}.#{range_key}"]
|
@@ -56,19 +99,39 @@ module Dynamoid
|
|
56
99
|
end
|
57
100
|
end
|
58
101
|
|
59
|
-
#
|
102
|
+
# List all tables on DynamoDB.
|
103
|
+
#
|
104
|
+
# @since 0.2.0
|
60
105
|
def list_tables
|
61
106
|
data.keys
|
62
107
|
end
|
63
108
|
|
64
|
-
#
|
109
|
+
# Persists an item in the hash.
|
110
|
+
#
|
111
|
+
# @param [String] table_name the name of the table
|
112
|
+
# @param [Object] object a hash or Dynamoid object to persist
|
113
|
+
#
|
114
|
+
# @since 0.2.0
|
65
115
|
def put_item(table_name, object)
|
66
116
|
table = data[table_name]
|
67
117
|
table[:data][object[table[:hash_key]]]
|
68
118
|
table[:data]["#{object[table[:hash_key]]}.#{object[table[:range_key]]}"] = object.delete_if{|k, v| v.nil? || (v.respond_to?(:empty?) && v.empty?)}
|
69
119
|
end
|
70
120
|
|
71
|
-
# Query
|
121
|
+
# Query the hash.
|
122
|
+
#
|
123
|
+
# @param [String] table_name the name of the table
|
124
|
+
# @param [Hash] opts the options to query the table with
|
125
|
+
# @option opts [String] :hash_value the value of the hash key to find
|
126
|
+
# @option opts [Range] :range_value find the range key within this range
|
127
|
+
# @option opts [Number] :range_greater_than find range keys greater than this
|
128
|
+
# @option opts [Number] :range_less_than find range keys less than this
|
129
|
+
# @option opts [Number] :range_gte find range keys greater than or equal to this
|
130
|
+
# @option opts [Number] :range_lte find range keys less than or equal to this
|
131
|
+
#
|
132
|
+
# @return [Array] an array of all matching items
|
133
|
+
#
|
134
|
+
# @since 0.2.0
|
72
135
|
def query(table_name, opts = {})
|
73
136
|
id = opts[:hash_value]
|
74
137
|
range_key = data[table_name][:range_key]
|
@@ -87,16 +150,22 @@ module Dynamoid
|
|
87
150
|
end
|
88
151
|
end
|
89
152
|
|
90
|
-
# Scan
|
153
|
+
# Scan the hash.
|
154
|
+
#
|
155
|
+
# @param [String] table_name the name of the table
|
156
|
+
# @param [Hash] scan_hash a hash of attributes: matching records will be returned by the scan
|
157
|
+
#
|
158
|
+
# @return [Array] an array of all matching items
|
159
|
+
#
|
160
|
+
# @since 0.2.0
|
91
161
|
def scan(table_name, scan_hash)
|
92
162
|
return [] if data[table_name].nil?
|
93
163
|
data[table_name][:data].values.flatten.select{|d| scan_hash.all?{|k, v| !d[k].nil? && d[k] == v}}
|
94
164
|
end
|
95
165
|
|
96
|
-
# UpdateItem
|
97
|
-
|
98
|
-
# UpdateTable
|
166
|
+
# @todo Add an UpdateItem method.
|
99
167
|
|
168
|
+
# @todo Add an UpdateTable method.
|
100
169
|
end
|
101
170
|
end
|
102
171
|
end
|
@@ -1,16 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'dynamoid/associations/association'
|
2
3
|
require 'dynamoid/associations/has_many'
|
3
4
|
require 'dynamoid/associations/belongs_to'
|
4
5
|
require 'dynamoid/associations/has_one'
|
5
6
|
require 'dynamoid/associations/has_and_belongs_to_many'
|
6
7
|
|
7
|
-
|
8
|
-
module Dynamoid #:nodoc:
|
8
|
+
module Dynamoid
|
9
9
|
|
10
|
-
# Connects models together through the magic of associations.
|
10
|
+
# Connects models together through the magic of associations. We enjoy four different kinds of associations presently:
|
11
|
+
# * belongs_to
|
12
|
+
# * has_and_belongs_to_many
|
13
|
+
# * has_many
|
14
|
+
# * has_one
|
11
15
|
module Associations
|
12
16
|
extend ActiveSupport::Concern
|
13
17
|
|
18
|
+
# Create the association tracking attribute and initialize it to an empty hash.
|
14
19
|
included do
|
15
20
|
class_attribute :associations
|
16
21
|
|
@@ -18,24 +23,68 @@ module Dynamoid #:nodoc:
|
|
18
23
|
end
|
19
24
|
|
20
25
|
module ClassMethods
|
26
|
+
|
27
|
+
# create a has_many association for this document.
|
28
|
+
#
|
29
|
+
# @param [Symbol] name the name of the association
|
30
|
+
# @param [Hash] options options to pass to the association constructor
|
31
|
+
# @option options [Class] :class the target class of the has_many association; that is, the belongs_to class
|
32
|
+
# @option options [Symbol] :class_name the name of the target class of the association; that is, the name of the belongs_to class
|
33
|
+
# @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
|
34
|
+
#
|
35
|
+
# @since 0.2.0
|
21
36
|
def has_many(name, options = {})
|
22
37
|
association(:has_many, name, options)
|
23
38
|
end
|
24
39
|
|
40
|
+
# create a has_one association for this document.
|
41
|
+
#
|
42
|
+
# @param [Symbol] name the name of the association
|
43
|
+
# @param [Hash] options options to pass to the association constructor
|
44
|
+
# @option options [Class] :class the target class of the has_one association; that is, the belongs_to class
|
45
|
+
# @option options [Symbol] :class_name the name of the target class of the association; that is, the name of the belongs_to class
|
46
|
+
# @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
|
47
|
+
#
|
48
|
+
# @since 0.2.0
|
25
49
|
def has_one(name, options = {})
|
26
50
|
association(:has_one, name, options)
|
27
51
|
end
|
28
52
|
|
53
|
+
# create a belongs_to association for this document.
|
54
|
+
#
|
55
|
+
# @param [Symbol] name the name of the association
|
56
|
+
# @param [Hash] options options to pass to the association constructor
|
57
|
+
# @option options [Class] :class the target class of the has_one association; that is, the has_many or has_one class
|
58
|
+
# @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
|
59
|
+
# @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
|
60
|
+
#
|
61
|
+
# @since 0.2.0
|
29
62
|
def belongs_to(name, options = {})
|
30
63
|
association(:belongs_to, name, options)
|
31
64
|
end
|
32
65
|
|
66
|
+
# create a has_and_belongs_to_many association for this document.
|
67
|
+
#
|
68
|
+
# @param [Symbol] name the name of the association
|
69
|
+
# @param [Hash] options options to pass to the association constructor
|
70
|
+
# @option options [Class] :class the target class of the has_and_belongs_to_many association; that is, the belongs_to class
|
71
|
+
# @option options [Symbol] :class_name the name of the target class of the association; that is, the name of the belongs_to class
|
72
|
+
# @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
|
73
|
+
#
|
74
|
+
# @since 0.2.0
|
33
75
|
def has_and_belongs_to_many(name, options = {})
|
34
76
|
association(:has_and_belongs_to_many, name, options)
|
35
77
|
end
|
36
78
|
|
37
79
|
private
|
38
|
-
|
80
|
+
|
81
|
+
# create getters and setters for an association.
|
82
|
+
#
|
83
|
+
# @param [Symbol] symbol the type (:has_one, :has_many, :has_and_belongs_to_many, :belongs_to) of the association
|
84
|
+
# @param [Symbol] name the name of the association
|
85
|
+
# @param [Hash] options options to pass to the association constructor; see above for all valid options
|
86
|
+
#
|
87
|
+
# @since 0.2.0
|
39
88
|
def association(type, name, options = {})
|
40
89
|
field "#{name}_ids".to_sym, :set
|
41
90
|
self.associations[name] = options.merge(:type => type)
|
@@ -1,12 +1,29 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Dynamoid #:nodoc:
|
3
3
|
|
4
|
-
# The base association module.
|
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.
|
5
7
|
module Associations
|
6
8
|
module Association
|
7
9
|
attr_accessor :name, :options, :source, :query
|
8
10
|
include Enumerable
|
9
11
|
|
12
|
+
# Delegate methods to the records the association represents.
|
13
|
+
delegate :first, :last, :empty?, :size, :to => :records
|
14
|
+
|
15
|
+
# Create a new association.
|
16
|
+
#
|
17
|
+
# @param [Class] source the source record of the association; that is, the record that you already have
|
18
|
+
# @param [Symbol] name the name of the association
|
19
|
+
# @param [Hash] options optional parameters for the association
|
20
|
+
# @option options [Class] :class the target class of the association; that is, the class to which the association objects belong
|
21
|
+
# @option options [Symbol] :class_name the name of the target class of the association; only this or Class is necessary
|
22
|
+
# @option options [Symbol] :inverse_of the name of the association on the target class
|
23
|
+
#
|
24
|
+
# @return [Dynamoid::Association] the actual association instance itself
|
25
|
+
#
|
26
|
+
# @since 0.2.0
|
10
27
|
def initialize(source, name, options)
|
11
28
|
@name = name
|
12
29
|
@options = options
|
@@ -14,62 +31,148 @@ module Dynamoid #:nodoc:
|
|
14
31
|
@query = {}
|
15
32
|
end
|
16
33
|
|
17
|
-
|
18
|
-
results = target_class.find(source_ids.to_a)
|
19
|
-
results = results.nil? ? [] : Array(results)
|
20
|
-
return results if query.empty?
|
21
|
-
results_with_query(results)
|
22
|
-
end
|
23
|
-
alias :all :records
|
24
|
-
|
25
|
-
def empty?
|
26
|
-
records.empty?
|
27
|
-
end
|
34
|
+
# Alias convenience methods for the associations.
|
28
35
|
alias :nil? :empty?
|
36
|
+
alias :count :size
|
29
37
|
|
30
|
-
|
31
|
-
|
38
|
+
# The records associated to the source.
|
39
|
+
#
|
40
|
+
# @return the association records; depending on which association this is, either a single instance or an array
|
41
|
+
#
|
42
|
+
# @since 0.2.0
|
43
|
+
def records
|
44
|
+
results = Array(target_class.find(source_ids.to_a))
|
45
|
+
|
46
|
+
if query.empty?
|
47
|
+
results
|
48
|
+
else
|
49
|
+
results_with_query(results)
|
50
|
+
end
|
32
51
|
end
|
33
|
-
alias :
|
52
|
+
alias :all :records
|
34
53
|
|
54
|
+
# Delegate include? to the records.
|
35
55
|
def include?(object)
|
36
56
|
records.include?(object)
|
37
57
|
end
|
38
58
|
|
59
|
+
# @todo Improve the two methods below to not have quite so much duplicated code.
|
60
|
+
|
61
|
+
# Deletes an object or array of objects from the association. This removes their records from the association field on the source,
|
62
|
+
# and attempts to remove the source from the target association if it is detected to exist.
|
63
|
+
#
|
64
|
+
# @param [Dynamoid::Document] object the object (or array of objects) to remove from the association
|
65
|
+
#
|
66
|
+
# @return [Dynamoid::Document] the deleted object
|
67
|
+
#
|
68
|
+
# @since 0.2.0
|
39
69
|
def delete(object)
|
40
70
|
source.update_attribute(source_attribute, source_ids - Array(object).collect(&:id))
|
41
71
|
Array(object).collect{|o| self.send(:disassociate_target, o)} if target_association
|
42
72
|
object
|
43
73
|
end
|
44
|
-
|
74
|
+
|
75
|
+
# Add an object or array of objects to an association. This preserves the current records in the association (if any)
|
76
|
+
# and adds the object to 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
|
45
83
|
def <<(object)
|
46
84
|
source.update_attribute(source_attribute, source_ids.merge(Array(object).collect(&:id)))
|
47
85
|
Array(object).collect{|o| self.send(:associate_target, o)} if target_association
|
48
86
|
object
|
49
87
|
end
|
50
|
-
|
88
|
+
|
89
|
+
# Replace an association with object or array of objects. This removes all of the existing associated records and replaces them with
|
90
|
+
# the passed object(s), and associates the target association if it is detected to exist.
|
91
|
+
#
|
92
|
+
# @param [Dynamoid::Document] object the object (or array of objects) to add to the association
|
93
|
+
#
|
94
|
+
# @return [Dynamoid::Document] the added object
|
95
|
+
#
|
96
|
+
# @since 0.2.0
|
51
97
|
def setter(object)
|
52
|
-
|
53
|
-
|
98
|
+
records.each {|o| delete(o)}
|
99
|
+
self << (object)
|
54
100
|
object
|
55
101
|
end
|
56
102
|
|
103
|
+
# Create a new instance of the target class and add it directly to the association.
|
104
|
+
#
|
105
|
+
# @param [Hash] attribute hash for the new object
|
106
|
+
#
|
107
|
+
# @return [Dynamoid::Document] the newly-created object
|
108
|
+
#
|
109
|
+
# @since 0.2.0
|
57
110
|
def create(attributes = {})
|
58
|
-
|
59
|
-
|
111
|
+
self << target_class.create(attributes)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Create a new instance of the target class and add it directly to the association. If the create fails an exception will be raised.
|
115
|
+
#
|
116
|
+
# @param [Hash] attribute hash for the new object
|
117
|
+
#
|
118
|
+
# @return [Dynamoid::Document] the newly-created object
|
119
|
+
#
|
120
|
+
# @since 0.2.0
|
121
|
+
def create!(attributes = {})
|
122
|
+
self << target_class.create!(attributes)
|
60
123
|
end
|
61
124
|
|
125
|
+
|
126
|
+
# Naive association filtering.
|
127
|
+
#
|
128
|
+
# @param [Hash] A hash of attributes; each must match every returned object's attribute exactly.
|
129
|
+
#
|
130
|
+
# @return [Dynamoid::Association] the association this method was called on (for chaining purposes)
|
131
|
+
#
|
132
|
+
# @since 0.2.0
|
62
133
|
def where(args)
|
63
134
|
args.each {|k, v| query[k] = v}
|
64
135
|
self
|
65
136
|
end
|
66
137
|
|
138
|
+
# Create a new instance of the target class and add it directly to the association. If the create fails an exception will be raised.
|
139
|
+
#
|
140
|
+
# @param [Hash] attribute hash for the new object
|
141
|
+
#
|
142
|
+
# @return [Dynamoid::Document] the newly-created object
|
143
|
+
#
|
144
|
+
# @since 0.2.0
|
67
145
|
def each(&block)
|
68
146
|
records.each(&block)
|
69
147
|
end
|
148
|
+
|
149
|
+
# Destroys all members of the association and removes them from the association.
|
150
|
+
#
|
151
|
+
# @since 0.2.0
|
152
|
+
def destroy_all
|
153
|
+
objs = records
|
154
|
+
source.update_attribute(source_attribute, nil)
|
155
|
+
objs.each(&:destroy)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Deletes all members of the association and removes them from the association.
|
159
|
+
#
|
160
|
+
# @since 0.2.0
|
161
|
+
def delete_all
|
162
|
+
objs = records
|
163
|
+
source.update_attribute(source_attribute, nil)
|
164
|
+
objs.each(&:delete)
|
165
|
+
end
|
70
166
|
|
71
167
|
private
|
72
168
|
|
169
|
+
# If a query exists, filter all existing results based on that query.
|
170
|
+
#
|
171
|
+
# @param [Array] results the raw results for the association
|
172
|
+
#
|
173
|
+
# @return [Array] the filtered results for the query
|
174
|
+
#
|
175
|
+
# @since 0.2.0
|
73
176
|
def results_with_query(results)
|
74
177
|
results.find_all do |result|
|
75
178
|
query.all? do |attribute, value|
|
@@ -77,27 +180,52 @@ module Dynamoid #:nodoc:
|
|
77
180
|
end
|
78
181
|
end
|
79
182
|
end
|
80
|
-
|
183
|
+
|
184
|
+
# The target class name, either inferred through the association's name or specified in options.
|
185
|
+
#
|
186
|
+
# @since 0.2.0
|
187
|
+
def target_class_name
|
188
|
+
options[:class_name] || name.to_s.classify
|
189
|
+
end
|
190
|
+
|
191
|
+
# The target class, either inferred through the association's name or specified in options.
|
192
|
+
#
|
193
|
+
# @since 0.2.0
|
81
194
|
def target_class
|
82
|
-
|
195
|
+
options[:class] || target_class_name.constantize
|
83
196
|
end
|
84
197
|
|
198
|
+
# The target attribute: that is, the attribute on each object of the association that should reference the source.
|
199
|
+
#
|
200
|
+
# @since 0.2.0
|
85
201
|
def target_attribute
|
86
202
|
"#{target_association}_ids".to_sym if target_association
|
87
203
|
end
|
88
|
-
|
204
|
+
|
205
|
+
# The ids in the target association.
|
206
|
+
#
|
207
|
+
# @since 0.2.0
|
89
208
|
def target_ids
|
90
209
|
target.send(target_attribute) || Set.new
|
91
210
|
end
|
92
|
-
|
211
|
+
|
212
|
+
# The ids in the target association.
|
213
|
+
#
|
214
|
+
# @since 0.2.0
|
93
215
|
def source_class
|
94
216
|
source.class
|
95
217
|
end
|
96
218
|
|
219
|
+
# The source's association attribute: the name of the association with _ids afterwards, like "users_ids".
|
220
|
+
#
|
221
|
+
# @since 0.2.0
|
97
222
|
def source_attribute
|
98
223
|
"#{name}_ids".to_sym
|
99
224
|
end
|
100
225
|
|
226
|
+
# The ids in the source association.
|
227
|
+
#
|
228
|
+
# @since 0.2.0
|
101
229
|
def source_ids
|
102
230
|
source.send(source_attribute) || Set.new
|
103
231
|
end
|
@@ -105,4 +233,4 @@ module Dynamoid #:nodoc:
|
|
105
233
|
end
|
106
234
|
end
|
107
235
|
|
108
|
-
end
|
236
|
+
end
|