dynamoid 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/Dynamoid.gemspec +3 -2
  2. data/README.markdown +39 -3
  3. data/VERSION +1 -1
  4. data/lib/dynamoid.rb +2 -0
  5. data/lib/dynamoid/adapter.rb +9 -8
  6. data/lib/dynamoid/adapter/aws_sdk.rb +15 -9
  7. data/lib/dynamoid/adapter/local.rb +39 -14
  8. data/lib/dynamoid/associations.rb +5 -6
  9. data/lib/dynamoid/associations/association.rb +23 -1
  10. data/lib/dynamoid/associations/belongs_to.rb +0 -1
  11. data/lib/dynamoid/associations/has_and_belongs_to_many.rb +0 -1
  12. data/lib/dynamoid/associations/has_many.rb +0 -1
  13. data/lib/dynamoid/associations/many_association.rb +10 -7
  14. data/lib/dynamoid/associations/single_association.rb +2 -1
  15. data/lib/dynamoid/components.rb +1 -0
  16. data/lib/dynamoid/config.rb +1 -0
  17. data/lib/dynamoid/criteria.rb +2 -2
  18. data/lib/dynamoid/criteria/chain.rb +118 -43
  19. data/lib/dynamoid/document.rb +58 -6
  20. data/lib/dynamoid/fields.rb +18 -3
  21. data/lib/dynamoid/finders.rb +14 -7
  22. data/lib/dynamoid/indexes.rb +3 -2
  23. data/lib/dynamoid/indexes/index.rb +2 -2
  24. data/lib/dynamoid/persistence.rb +29 -14
  25. data/spec/app/models/address.rb +4 -0
  26. data/spec/app/models/camel_case.rb +13 -0
  27. data/spec/app/models/tweet.rb +9 -0
  28. data/spec/dynamoid/adapter/aws_sdk_spec.rb +5 -5
  29. data/spec/dynamoid/adapter/local_spec.rb +79 -79
  30. data/spec/dynamoid/adapter_spec.rb +6 -6
  31. data/spec/dynamoid/associations/association_spec.rb +26 -12
  32. data/spec/dynamoid/criteria/chain_spec.rb +64 -21
  33. data/spec/dynamoid/criteria_spec.rb +28 -0
  34. data/spec/dynamoid/document_spec.rb +29 -0
  35. data/spec/dynamoid/fields_spec.rb +5 -0
  36. data/spec/dynamoid/finders_spec.rb +6 -1
  37. data/spec/dynamoid/indexes/index_spec.rb +1 -1
  38. data/spec/dynamoid/persistence_spec.rb +9 -17
  39. data/spec/spec_helper.rb +1 -0
  40. metadata +4 -3
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "dynamoid"
8
- s.version = "0.3.2"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Josh Symonds"]
12
- s.date = "2012-04-13"
12
+ s.date = "2012-04-26"
13
13
  s.description = "Dynamoid is an ORM for Amazon's DynamoDB that supports offline development, associations, querying, and everything else you'd expect from an ActiveRecord-style replacement."
14
14
  s.email = "josh@joshsymonds.com"
15
15
  s.extra_rdoc_files = [
@@ -106,6 +106,7 @@ Gem::Specification.new do |s|
106
106
  "spec/app/models/magazine.rb",
107
107
  "spec/app/models/sponsor.rb",
108
108
  "spec/app/models/subscription.rb",
109
+ "spec/app/models/tweet.rb",
109
110
  "spec/app/models/user.rb",
110
111
  "spec/dynamoid/adapter/aws_sdk_spec.rb",
111
112
  "spec/dynamoid/adapter/local_spec.rb",
@@ -28,6 +28,7 @@ Then you need to initialize it to get it going. Put code similar to this somewhe
28
28
  config.partition_size = 200 # Determine the key space size that writes are randomly spread across.
29
29
  config.read_capacity = 100 # Read capacity for your tables
30
30
  config.write_capacity = 20 # Write capacity for your tables
31
+ config.endpoint = 'dynamodb.us-east-1.amazonaws.com' # Set the regional endpoint
31
32
  end
32
33
 
33
34
  ```
@@ -45,6 +46,20 @@ class User
45
46
  end
46
47
  ```
47
48
 
49
+ ### Table
50
+
51
+ Dynamoid has some sensible defaults for you when you create a new table, including the table name and the primary key column. But you can change those if you like on table creation.
52
+
53
+ ```ruby
54
+ class User
55
+ include Dynamoid::Document
56
+
57
+ table :name => :awesome_users, :key => :user_id, :read_capacity => 400, :write_capacity => 400
58
+ end
59
+ ```
60
+
61
+ These fields will not change an existing table: so specifying a new read_capacity and write_capacity here only works correctly for entirely new tables. Similarly, while Dynamoid will look for a table named `awesome_users` in your namespace, it won't change any existing tables to use that name; and if it does find a table with the correct name, it won't change its hash key, which it expects will be user_id. If this table doesn't exist yet, however, Dynamoid will create it with these options.
62
+
48
63
  ### Fields
49
64
 
50
65
  You'll have to define all the fields on the model and the data type of each field. Every field on the object must be included here; if you miss any they'll be completely bypassed during DynamoDB's initialization and will not appear on the model objects.
@@ -79,7 +94,7 @@ class User
79
94
  index :email
80
95
  index [:name, :email]
81
96
  index :created_at, :range => true
82
- index :name, :range => :joined_at
97
+ index :name, :range_key => :joined_at
83
98
 
84
99
  end
85
100
  ```
@@ -152,7 +167,9 @@ end
152
167
 
153
168
  ## Usage
154
169
 
155
- Dynamoid's syntax is very similar to ActiveRecord's.
170
+ ### Object Creation
171
+
172
+ Dynamoid's syntax is generally very similar to ActiveRecord's. Making new objects is simple:
156
173
 
157
174
  ```ruby
158
175
  u = User.new(:name => 'Josh')
@@ -174,6 +191,8 @@ address.city = 'Chicago'
174
191
  address.save
175
192
  ```
176
193
 
194
+ ### Querying
195
+
177
196
  Querying can be done in one of three ways:
178
197
 
179
198
  ```ruby
@@ -190,6 +209,23 @@ u.addresses.where(:city => 'Chicago').all
190
209
 
191
210
  But keep in mind Dynamoid -- and document-based storage systems in general -- are not drop-in replacements for existing relational databases. The above query does not efficiently perform a conditional join, but instead finds all the user's addresses and naively filters them in Ruby. For large associations this is a performance hit compared to relational database engines.
192
211
 
212
+ You can also limit returned results, or select a record from which to start, to support pagination:
213
+
214
+ ```ruby
215
+ Address.limit(5).start(address) # Only 5 addresses.
216
+ ```
217
+
218
+ ### Consistent Reads
219
+
220
+ Querying supports consistent reading. By default, DynamoDB reads are eventually consistent: if you do a write and then a read immediately afterwards, the results of the previous write may not be reflected. If you need to do a consistent read (that is, you need to read the results of a write immediately) you can do so, but keep in mind that consistent reads are twice as expensive as regular reads for DynamoDB.
221
+
222
+ ```ruby
223
+ Address.find(address.id, :consistent_read => true) # Find an address, ensure the read is consistent.
224
+ Address.where(:city => 'Chicago').consistent.all # Find all addresses where the city is Chicago, with a consistent read.
225
+ ```
226
+
227
+ ### Range Finding
228
+
193
229
  If you have a range index, Dynamoid provides a number of additional other convenience methods to make your life a little easier:
194
230
 
195
231
  ```ruby
@@ -205,7 +241,7 @@ DynamoDB achieves much of its speed by relying on a random pattern of writes and
205
241
 
206
242
  Dynamoid attempts to obviate this problem transparently by employing a partitioning strategy to divide up keys randomly across DynamoDB's servers. Each ID is assigned an additional number (by default 0 to 199, but you can increase the partition size in Dynamoid's configuration) upon save; when read, all 200 hashes are retrieved simultaneously and the most recently updated one is returned to the application. This results in a significant net performance increase, and is usually invisible to the application itself. It does, however, bring up the important issue of provisioning your DynamoDB tables correctly.
207
243
 
208
- When your read or write provisioning exceed your table's allowed throughput, DynamoDB will wait on connections until throughput is available again. This will appear as very, very slow requests and can be somewhat frustrating. Partitioning significantly increases the amount of throughput tables will experience; though DynamoDB will ignore keys that don't exist, if you have 20 partitioned keys representing one object, all will be retrieved every time the object is requested. Ensure that your tables are set up for this kind of throughput, or turn provisioning off, to make sure that DynamoDB doesn't throttle your requests.
244
+ When your read or write throughput exceed your table's allowed provisioning, DynamoDB will wait on connections until throughput is available again. This will appear as very, very slow requests and can be somewhat frustrating. Partitioning significantly increases the amount of throughput tables will experience; though DynamoDB will ignore keys that don't exist, if you have 20 partitioned keys representing one object, all will be retrieved every time the object is requested. Ensure that your tables are set up for this kind of throughput, or turn provisioning off, to make sure that DynamoDB doesn't throttle your requests.
209
245
 
210
246
  ## Credits
211
247
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.2
1
+ 0.4.0
@@ -23,6 +23,8 @@ require 'dynamoid/adapter'
23
23
 
24
24
  module Dynamoid
25
25
  extend self
26
+
27
+ MAX_ITEM_SIZE = 65_536
26
28
 
27
29
  def configure
28
30
  block_given? ? yield(Dynamoid::Config) : Dynamoid::Config
@@ -67,7 +67,8 @@ module Dynamoid
67
67
  # @param [Number] range_key the range key of the record
68
68
  #
69
69
  # @since 0.2.0
70
- def read(table, ids, range_key = nil)
70
+ def read(table, ids, options = {})
71
+ range_key = options[:range_key]
71
72
  if ids.respond_to?(:each)
72
73
  ids = ids.collect{|id| range_key ? [id, range_key] : id}
73
74
  if Dynamoid::Config.partitioning?
@@ -82,7 +83,7 @@ module Dynamoid
82
83
  results = benchmark('Partitioned Get Item', ids) {batch_get_item(table => id_with_partitions(ids))}
83
84
  result_for_partition(results[table]).first
84
85
  else
85
- benchmark('Get Item', ids) {get_item(table, ids, range_key)}
86
+ benchmark('Get Item', ids) {get_item(table, ids, options)}
86
87
  end
87
88
  end
88
89
  end
@@ -94,13 +95,13 @@ module Dynamoid
94
95
  # @param [Number] range_key the range key of the record
95
96
  #
96
97
  # @since 0.2.0
97
- def delete(table, id, range_key = nil)
98
+ def delete(table, id, options = {})
98
99
  if Dynamoid::Config.partitioning?
99
100
  benchmark('Delete Item', id) do
100
- id_with_partitions(id).each {|i| delete_item(table, i, range_key)}
101
+ id_with_partitions(id).each {|i| delete_item(table, i, options)}
101
102
  end
102
103
  else
103
- benchmark('Delete Item', id) {delete_item(table, id, range_key)}
104
+ benchmark('Delete Item', id) {delete_item(table, id, options)}
104
105
  end
105
106
  end
106
107
 
@@ -110,12 +111,12 @@ module Dynamoid
110
111
  # @param [Hash] scan_hash a hash of attributes: matching records will be returned by the scan
111
112
  #
112
113
  # @since 0.2.0
113
- def scan(table, query)
114
+ def scan(table, query, opts = {})
114
115
  if Dynamoid::Config.partitioning?
115
- results = benchmark('Scan', table, query) {adapter.scan(table, query)}
116
+ results = benchmark('Scan', table, query) {adapter.scan(table, query, opts)}
116
117
  result_for_partition(results)
117
118
  else
118
- adapter.scan(table, query)
119
+ adapter.scan(table, query, opts)
119
120
  end
120
121
  end
121
122
 
@@ -18,7 +18,7 @@ module Dynamoid
18
18
  #
19
19
  # @since 0.2.0
20
20
  def connect!
21
- @@connection = AWS::DynamoDB.new(:access_key_id => Dynamoid::Config.access_key, :secret_access_key => Dynamoid::Config.secret_key)
21
+ @@connection = AWS::DynamoDB.new(:access_key_id => Dynamoid::Config.access_key, :secret_access_key => Dynamoid::Config.secret_key, :dynamo_db_endpoint => Dynamoid::Config.endpoint)
22
22
  end
23
23
 
24
24
  # Return the established connection.
@@ -64,7 +64,6 @@ module Dynamoid
64
64
  # @since 0.2.0
65
65
  def create_table(table_name, key = :id, options = {})
66
66
  options[:hash_key] ||= {key.to_sym => :string}
67
- options[:range_key] = {options[:range_key].to_sym => :number} if options[:range_key]
68
67
  read_capacity = options[:read_capacity] || Dynamoid::Config.read_capacity
69
68
  write_capacity = options[:write_capacity] || Dynamoid::Config.write_capacity
70
69
  table = @@connection.tables.create(table_name, read_capacity, write_capacity, options)
@@ -79,7 +78,8 @@ module Dynamoid
79
78
  # @param [Number] range_key the range key of the item to delete, required if the table has a composite key
80
79
  #
81
80
  # @since 0.2.0
82
- def delete_item(table_name, key, range_key = nil)
81
+ def delete_item(table_name, key, options = {})
82
+ range_key = options.delete(:range_key)
83
83
  table = get_table(table_name)
84
84
  result = if table.composite_key?
85
85
  table.items.at(key, range_key)
@@ -111,13 +111,18 @@ module Dynamoid
111
111
  # @return [Hash] a hash representing the raw item in DynamoDB
112
112
  #
113
113
  # @since 0.2.0
114
- def get_item(table_name, key, range_key = nil)
114
+
115
+
116
+
117
+ def get_item(table_name, key, options = {})
118
+ range_key = options.delete(:range_key)
115
119
  table = get_table(table_name)
120
+
116
121
  result = if table.composite_key?
117
122
  table.items.at(key, range_key)
118
123
  else
119
124
  table.items[key]
120
- end.attributes.to_h
125
+ end.attributes.to_h(options)
121
126
  if result.empty?
122
127
  nil
123
128
  else
@@ -161,10 +166,11 @@ module Dynamoid
161
166
  # @since 0.2.0
162
167
  def query(table_name, opts = {})
163
168
  table = get_table(table_name)
164
-
169
+
170
+ consistent_opts = { :consistent_read => opts[:consistent_read] || false }
165
171
  if table.composite_key?
166
172
  results = []
167
- table.items.query(opts).each {|data| results << data.attributes.to_h.symbolize_keys!}
173
+ table.items.query(opts).each {|data| results << data.attributes.to_h(consistent_opts).symbolize_keys!}
168
174
  results
169
175
  else
170
176
  get_item(table_name, opts[:hash_value])
@@ -180,10 +186,10 @@ module Dynamoid
180
186
  # @return [Array] an array of all matching items
181
187
  #
182
188
  # @since 0.2.0
183
- def scan(table_name, scan_hash)
189
+ def scan(table_name, scan_hash, select_opts)
184
190
  table = get_table(table_name)
185
191
  results = []
186
- table.items.where(scan_hash).select do |data|
192
+ table.items.where(scan_hash).select(select_opts) do |data|
187
193
  results << data.attributes.symbolize_keys!
188
194
  end
189
195
  results
@@ -38,7 +38,7 @@ module Dynamoid
38
38
  table = data[table_name]
39
39
  if table[:range_key]
40
40
  Array(keys).each do |hash_key, range_key|
41
- hash[table_name] << get_item(table_name, hash_key, range_key)
41
+ hash[table_name] << get_item(table_name, hash_key, :range_key => range_key)
42
42
  end
43
43
  else
44
44
  Array(keys).each do |key|
@@ -57,7 +57,8 @@ module Dynamoid
57
57
  #
58
58
  # @since 0.2.0
59
59
  def create_table(table_name, key, options = {})
60
- data[table_name] = {:hash_key => key, :range_key => options[:range_key], :data => {}}
60
+ range_key = options[:range_key] && options[:range_key].keys.first
61
+ data[table_name] = {:hash_key => key, :range_key => range_key, :data => {}}
61
62
  end
62
63
 
63
64
  # Removes an item from the hash.
@@ -67,7 +68,8 @@ module Dynamoid
67
68
  # @param [Number] range_key the range key of the item to delete, required if the table has a composite key
68
69
  #
69
70
  # @since 0.2.0
70
- def delete_item(table_name, key, range_key = nil)
71
+ def delete_item(table_name, key, options = {})
72
+ range_key = options.delete(:range_key)
71
73
  data[table_name][:data].delete("#{key}.#{range_key}")
72
74
  end
73
75
 
@@ -91,7 +93,8 @@ module Dynamoid
91
93
  # @return [Hash] a hash representing the raw item
92
94
  #
93
95
  # @since 0.2.0
94
- def get_item(table_name, key, range_key = nil)
96
+ def get_item(table_name, key, options = {})
97
+ range_key = options[:range_key]
95
98
  if data[table_name][:data]
96
99
  data[table_name][:data]["#{key}.#{range_key}"]
97
100
  else
@@ -116,6 +119,8 @@ module Dynamoid
116
119
  table = data[table_name]
117
120
  table[:data][object[table[:hash_key]]]
118
121
  table[:data]["#{object[table[:hash_key]]}.#{object[table[:range_key]]}"] = object.delete_if{|k, v| v.nil? || (v.respond_to?(:empty?) && v.empty?)}
122
+ rescue
123
+ raise data.inspect
119
124
  end
120
125
 
121
126
  # Query the hash.
@@ -134,20 +139,26 @@ module Dynamoid
134
139
  # @since 0.2.0
135
140
  def query(table_name, opts = {})
136
141
  id = opts[:hash_value]
142
+ hash_key = data[table_name][:hash_key]
137
143
  range_key = data[table_name][:range_key]
138
- if opts[:range_value]
139
- data[table_name][:data].values.find_all{|v| v[:id] == id && !v[range_key].nil? && opts[:range_value].include?(v[range_key])}
144
+
145
+ results = if opts[:range_value]
146
+ data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && opts[:range_value].include?(v[range_key])}
140
147
  elsif opts[:range_greater_than]
141
- data[table_name][:data].values.find_all{|v| v[:id] == id && !v[range_key].nil? && v[range_key] > opts[:range_greater_than]}
148
+ data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && v[range_key] > opts[:range_greater_than]}
142
149
  elsif opts[:range_less_than]
143
- data[table_name][:data].values.find_all{|v| v[:id] == id && !v[range_key].nil? && v[range_key] < opts[:range_less_than]}
150
+ data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && v[range_key] < opts[:range_less_than]}
144
151
  elsif opts[:range_gte]
145
- data[table_name][:data].values.find_all{|v| v[:id] == id && !v[range_key].nil? && v[range_key] >= opts[:range_gte]}
152
+ data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && v[range_key] >= opts[:range_gte]}
146
153
  elsif opts[:range_lte]
147
- data[table_name][:data].values.find_all{|v| v[:id] == id && !v[range_key].nil? && v[range_key] <= opts[:range_lte]}
154
+ data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && v[range_key] <= opts[:range_lte]}
148
155
  else
149
- get_item(table_name, id)
156
+ data[table_name][:data].values.find_all{|v| v[hash_key] == id}
150
157
  end
158
+
159
+ results = drop_till_start(results, opts[:next_token], range_key, hash_key)
160
+ results = results.take(opts[:limit]) if opts[:limit]
161
+ results
151
162
  end
152
163
 
153
164
  # Scan the hash.
@@ -158,9 +169,23 @@ module Dynamoid
158
169
  # @return [Array] an array of all matching items
159
170
  #
160
171
  # @since 0.2.0
161
- def scan(table_name, scan_hash)
172
+ def scan(table_name, scan_hash, opts = {})
162
173
  return [] if data[table_name].nil?
163
- data[table_name][:data].values.flatten.select{|d| scan_hash.all?{|k, v| !d[k].nil? && d[k] == v}}
174
+ results = data[table_name][:data].values.flatten.select{|d| scan_hash.all?{|k, v| !d[k].nil? && d[k] == v}}
175
+ results = drop_till_start(results, opts[:next_token], data[table_name][:range_key], data[table_name][:hash_key])
176
+ results = results.take(opts[:limit]) if opts[:limit]
177
+ results
178
+ end
179
+
180
+ def drop_till_start(results, next_token, range_key, hash_key)
181
+ return results unless next_token
182
+
183
+ hash_value = next_token[:hash_key_element].values.first
184
+ range_value = next_token[:range_key_element].values.first if next_token[:range_key_element]
185
+
186
+ results = results.drop_while do |r|
187
+ (r[hash_key] != hash_value or r[range_key] != range_value)
188
+ end.drop(1)
164
189
  end
165
190
 
166
191
  # @todo Add an UpdateItem method.
@@ -168,4 +193,4 @@ module Dynamoid
168
193
  # @todo Add an UpdateTable method.
169
194
  end
170
195
  end
171
- end
196
+ end
@@ -91,17 +91,16 @@ module Dynamoid
91
91
  field "#{name}_ids".to_sym, :set
92
92
  self.associations[name] = options.merge(:type => type)
93
93
  define_method(name) do
94
- @associations ||= {}
95
- @associations[name] ||= Dynamoid::Associations.const_get(type.to_s.camelcase).new(self, name, options)
94
+ @associations[:"#{name}_ids"] ||= Dynamoid::Associations.const_get(type.to_s.camelcase).new(self, name, options)
96
95
  end
97
96
  define_method("#{name}=".to_sym) do |objects|
98
- @associations ||= {}
99
- @associations[name] ||= Dynamoid::Associations.const_get(type.to_s.camelcase).new(self, name, options)
100
- @associations[name].setter(objects)
97
+ @associations[:"#{name}_ids"] ||= Dynamoid::Associations.const_get(type.to_s.camelcase).new(self, name, options)
98
+ @associations[:"#{name}_ids"].setter(objects)
101
99
  end
102
100
  end
103
101
  end
104
-
102
+
103
+
105
104
  end
106
105
 
107
106
  end
@@ -6,7 +6,7 @@ module Dynamoid #:nodoc:
6
6
  # The target is the object which is referencing by this association.
7
7
  module Associations
8
8
  module Association
9
- attr_accessor :name, :options, :source
9
+ attr_accessor :name, :options, :source, :loaded
10
10
 
11
11
  # Create a new association.
12
12
  #
@@ -24,6 +24,28 @@ module Dynamoid #:nodoc:
24
24
  @name = name
25
25
  @options = options
26
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
27
49
  end
28
50
 
29
51
  private
@@ -5,7 +5,6 @@ module Dynamoid #:nodoc:
5
5
  # object to which the association object is associated.
6
6
  module Associations
7
7
  class BelongsTo
8
- include Association
9
8
  include SingleAssociation
10
9
 
11
10
  private
@@ -4,7 +4,6 @@ module Dynamoid #:nodoc:
4
4
  # The has and belongs to many association.
5
5
  module Associations
6
6
  class HasAndBelongsToMany
7
- include Association
8
7
  include ManyAssociation
9
8
 
10
9
  private
@@ -4,7 +4,6 @@ module Dynamoid #:nodoc:
4
4
  # The has_many association.
5
5
  module Associations
6
6
  class HasMany
7
- include Association
8
7
  include ManyAssociation
9
8
 
10
9
  private
@@ -3,6 +3,7 @@ module Dynamoid #:nodoc:
3
3
 
4
4
  module Associations
5
5
  module ManyAssociation
6
+ include Association
6
7
 
7
8
  attr_accessor :query
8
9
 
@@ -20,13 +21,15 @@ module Dynamoid #:nodoc:
20
21
  # @return the association records; depending on which association this is, either a single instance or an array
21
22
  #
22
23
  # @since 0.2.0
23
- def records
24
- results = Array(target_class.find(source_ids.to_a))
24
+ def find_target
25
+ Array(target_class.find(source_ids.to_a))
26
+ end
25
27
 
28
+ def records
26
29
  if query.empty?
27
- results
30
+ target
28
31
  else
29
- results_with_query(results)
32
+ results_with_query(target)
30
33
  end
31
34
  end
32
35
 
@@ -78,7 +81,7 @@ module Dynamoid #:nodoc:
78
81
  #
79
82
  # @since 0.2.0
80
83
  def setter(object)
81
- records.each {|o| delete(o)}
84
+ target.each {|o| delete(o)}
82
85
  self << (object)
83
86
  object
84
87
  end
@@ -120,7 +123,7 @@ module Dynamoid #:nodoc:
120
123
  #
121
124
  # @since 0.2.0
122
125
  def destroy_all
123
- objs = records
126
+ objs = target
124
127
  source.update_attribute(source_attribute, nil)
125
128
  objs.each(&:destroy)
126
129
  end
@@ -129,7 +132,7 @@ module Dynamoid #:nodoc:
129
132
  #
130
133
  # @since 0.2.0
131
134
  def delete_all
132
- objs = records
135
+ objs = target
133
136
  source.update_attribute(source_attribute, nil)
134
137
  objs.each(&:delete)
135
138
  end