simple_record 2.1.12 → 2.2.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/lib/simple_record/active_sdb.rb +352 -335
- metadata +2 -2
@@ -99,23 +99,23 @@ module SimpleRecord
|
|
99
99
|
@connection || raise(ActiveSdbError.new('Connection to SDB is not established'))
|
100
100
|
end
|
101
101
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
102
|
+
# Create a new handle to an Sdb account. All handles share the same per process or per thread
|
103
|
+
# HTTP connection to Amazon Sdb. Each handle is for a specific account.
|
104
|
+
# The +params+ are passed through as-is to Aws::SdbInterface.new
|
105
|
+
# Params:
|
106
|
+
# { :server => 'sdb.amazonaws.com' # Amazon service host: 'sdb.amazonaws.com'(default)
|
107
|
+
# :port => 443 # Amazon service port: 80 or 443(default)
|
108
|
+
# :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default)
|
109
|
+
# :signature_version => '2' # The signature version : '0', '1' or '2' (default)
|
110
|
+
# DEPRECATED :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default)
|
111
|
+
# :connection_mode => :default # options are :default (will use best known option, may change in the future)
|
112
|
+
# :per_request (opens and closes a connection on every request to SDB)
|
113
|
+
# :single (same as old multi_thread=>false)
|
114
|
+
# :per_thread (same as old multi_thread=>true)
|
115
|
+
# :pool (uses a connection pool with a maximum number of connections - NOT IMPLEMENTED YET)
|
116
|
+
# :logger => Logger Object # Logger instance: logs to STDOUT if omitted
|
117
|
+
# :nil_representation => 'mynil'} # interpret Ruby nil as this string value; i.e. use this string in SDB to represent Ruby nils (default is the string 'nil')
|
118
|
+
# :service_endpoint => '/' # Set this to /mdb/request.mgwsi for usage with M/DB
|
119
119
|
|
120
120
|
def establish_connection(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
|
121
121
|
@connection = Aws::SdbInterface.new(aws_access_key_id, aws_secret_access_key, params)
|
@@ -132,28 +132,28 @@ module SimpleRecord
|
|
132
132
|
class << self
|
133
133
|
include ActiveSdbConnect
|
134
134
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
135
|
+
# Retreive a list of domains.
|
136
|
+
#
|
137
|
+
# put Aws::ActiveSdb.domains #=> ['co-workers','family','friends','clients']
|
138
|
+
#
|
139
139
|
def domains
|
140
140
|
connection.list_domains[:domains]
|
141
141
|
end
|
142
142
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
143
|
+
# Create new domain.
|
144
|
+
# Raises no errors if the domain already exists.
|
145
|
+
#
|
146
|
+
# Aws::ActiveSdb.create_domain('alpha') #=> {:request_id=>"6fc652a0-0000-41d5-91f4-3ed390a3d3b2", :box_usage=>"0.0055590278"}
|
147
|
+
#
|
148
148
|
def create_domain(domain_name)
|
149
149
|
connection.create_domain(domain_name)
|
150
150
|
end
|
151
151
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
152
|
+
# Remove domain from SDB.
|
153
|
+
# Raises no errors if the domain does not exist.
|
154
|
+
#
|
155
|
+
# Aws::ActiveSdb.create_domain('alpha') #=> {:request_id=>"6fc652a0-0000-41c6-91f4-3ed390a3d3b2", :box_usage=>"0.0055590001"}
|
156
|
+
#
|
157
157
|
def delete_domain(domain_name)
|
158
158
|
connection.delete_domain(domain_name)
|
159
159
|
end
|
@@ -164,54 +164,54 @@ module SimpleRecord
|
|
164
164
|
class << self
|
165
165
|
include ActiveSdbConnect
|
166
166
|
|
167
|
-
|
167
|
+
# next_token value returned by last find: is useful to continue finding
|
168
168
|
attr_accessor :next_token
|
169
169
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
170
|
+
# Returns a Aws::SdbInterface object
|
171
|
+
#
|
172
|
+
# class A < Aws::ActiveSdb::Base
|
173
|
+
# end
|
174
|
+
#
|
175
|
+
# class B < Aws::ActiveSdb::Base
|
176
|
+
# end
|
177
|
+
#
|
178
|
+
# class C < Aws::ActiveSdb::Base
|
179
|
+
# end
|
180
|
+
#
|
181
|
+
# Aws::ActiveSdb.establish_connection 'key_id_1', 'secret_key_1'
|
182
|
+
#
|
183
|
+
# C.establish_connection 'key_id_2', 'secret_key_2'
|
184
|
+
#
|
185
|
+
# # A and B uses the default connection, C - uses its own
|
186
|
+
# puts A.connection #=> #<Aws::SdbInterface:0xb76d6d7c>
|
187
|
+
# puts B.connection #=> #<Aws::SdbInterface:0xb76d6d7c>
|
188
|
+
# puts C.connection #=> #<Aws::SdbInterface:0xb76d6ca0>
|
189
|
+
#
|
190
190
|
def connection
|
191
191
|
@connection || ActiveSdb::connection
|
192
192
|
end
|
193
193
|
|
194
194
|
@domain = nil
|
195
195
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
196
|
+
# Current domain name.
|
197
|
+
#
|
198
|
+
# # if 'ActiveSupport' is not loaded then class name converted to downcase
|
199
|
+
# class Client < Aws::ActiveSdb::Base
|
200
|
+
# end
|
201
|
+
# puts Client.domain #=> 'client'
|
202
|
+
#
|
203
|
+
# # if 'ActiveSupport' is loaded then class name being tableized
|
204
|
+
# require 'activesupport'
|
205
|
+
# class Client < Aws::ActiveSdb::Base
|
206
|
+
# end
|
207
|
+
# puts Client.domain #=> 'clients'
|
208
|
+
#
|
209
|
+
# # Explicit domain name definition
|
210
|
+
# class Client < Aws::ActiveSdb::Base
|
211
|
+
# set_domain_name :foreign_clients
|
212
|
+
# end
|
213
|
+
# puts Client.domain #=> 'foreign_clients'
|
214
|
+
#
|
215
215
|
def domain
|
216
216
|
unless @domain
|
217
217
|
if defined? ActiveSupport::CoreExtensions::String::Inflections
|
@@ -223,45 +223,45 @@ module SimpleRecord
|
|
223
223
|
@domain
|
224
224
|
end
|
225
225
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
226
|
+
# Change the default domain name to user defined.
|
227
|
+
#
|
228
|
+
# class Client < Aws::ActiveSdb::Base
|
229
|
+
# set_domain_name :foreign_clients
|
230
|
+
# end
|
231
|
+
#
|
232
232
|
def set_domain_name(domain)
|
233
233
|
@domain = domain.to_s
|
234
234
|
end
|
235
235
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
236
|
+
# Create domain at SDB.
|
237
|
+
# Raises no errors if the domain already exists.
|
238
|
+
#
|
239
|
+
# class Client < Aws::ActiveSdb::Base
|
240
|
+
# end
|
241
|
+
# Client.create_domain #=> {:request_id=>"6fc652a0-0000-41d5-91f4-3ed390a3d3b2", :box_usage=>"0.0055590278"}
|
242
|
+
#
|
243
243
|
def create_domain(dom=nil)
|
244
244
|
dom = domain if dom.nil?
|
245
245
|
puts "Creating new SimpleDB Domain: " + dom
|
246
246
|
connection.create_domain(dom)
|
247
247
|
end
|
248
248
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
249
|
+
# Remove domain from SDB.
|
250
|
+
# Raises no errors if the domain does not exist.
|
251
|
+
#
|
252
|
+
# class Client < Aws::ActiveSdb::Base
|
253
|
+
# end
|
254
|
+
# Client.delete_domain #=> {:request_id=>"e14d90d3-0000-4898-9995-0de28cdda270", :box_usage=>"0.0055590278"}
|
255
|
+
#
|
256
256
|
def delete_domain(dom=nil)
|
257
257
|
dom = domain if dom.nil?
|
258
258
|
puts "!!! DELETING SimpleDB Domain: " + dom
|
259
259
|
connection.delete_domain(dom)
|
260
260
|
end
|
261
261
|
|
262
|
-
|
263
|
-
|
264
|
-
|
262
|
+
#
|
263
|
+
# See select(), original find with QUERY syntax is deprecated so now find and select are synonyms.
|
264
|
+
#
|
265
265
|
def find(*args)
|
266
266
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
267
267
|
case args.first
|
@@ -281,9 +281,9 @@ module SimpleRecord
|
|
281
281
|
end
|
282
282
|
end
|
283
283
|
|
284
|
-
|
285
|
-
|
286
|
-
|
284
|
+
#
|
285
|
+
# Same as find, but will return SimpleDB metadata like :request_id and :box_usage
|
286
|
+
#
|
287
287
|
def find_with_metadata(*args)
|
288
288
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
289
289
|
case args.first
|
@@ -301,55 +301,55 @@ module SimpleRecord
|
|
301
301
|
end
|
302
302
|
end
|
303
303
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
304
|
+
# Perform a SQL-like select request.
|
305
|
+
#
|
306
|
+
# Single record:
|
307
|
+
#
|
308
|
+
# Client.select(:first)
|
309
|
+
# Client.select(:first, :conditions=> [ "name=? AND wife=?", "Jon", "Sandy"])
|
310
|
+
# Client.select(:first, :conditions=> { :name=>"Jon", :wife=>"Sandy" }, :select => :girfriends)
|
311
|
+
#
|
312
|
+
# Bunch of records:
|
313
|
+
#
|
314
|
+
# Client.select(:all)
|
315
|
+
# Client.select(:all, :limit => 10)
|
316
|
+
# Client.select(:all, :conditions=> [ "name=? AND 'girlfriend'=?", "Jon", "Judy"])
|
317
|
+
# Client.select(:all, :conditions=> { :name=>"Sandy" }, :limit => 3)
|
318
|
+
#
|
319
|
+
# Records by ids:
|
320
|
+
#
|
321
|
+
# Client.select('1')
|
322
|
+
# Client.select('1234987b4583475347523948')
|
323
|
+
# Client.select('1','2','3','4', :conditions=> ["toys=?", "beer"])
|
324
|
+
#
|
325
|
+
# Find helpers: Aws::ActiveSdb::Base.select_by_... and Aws::ActiveSdb::Base.select_all_by_...
|
326
|
+
#
|
327
|
+
# Client.select_by_name('Matias Rust')
|
328
|
+
# Client.select_by_name_and_city('Putin','Moscow')
|
329
|
+
# Client.select_by_name_and_city_and_post('Medvedev','Moscow','president')
|
330
|
+
#
|
331
|
+
# Client.select_all_by_author('G.Bush jr')
|
332
|
+
# Client.select_all_by_age_and_gender_and_ethnicity('34','male','russian')
|
333
|
+
# Client.select_all_by_gender_and_country('male', 'Russia', :order => 'name')
|
334
|
+
#
|
335
|
+
# Continue listing:
|
336
|
+
#
|
337
|
+
# # initial listing
|
338
|
+
# Client.select(:all, :limit => 10)
|
339
|
+
# # continue listing
|
340
|
+
# begin
|
341
|
+
# Client.select(:all, :limit => 10, :next_token => Client.next_token)
|
342
|
+
# end while Client.next_token
|
343
|
+
#
|
344
|
+
# Sort oder:
|
345
|
+
# If :order=>'attribute' option is specified then result response (ordered by 'attribute') will contain only items where attribute is defined (is not null).
|
346
|
+
#
|
347
|
+
# Client.select(:all) # returns all records
|
348
|
+
# Client.select(:all, :order => 'gender') # returns all records ordered by gender where gender attribute exists
|
349
|
+
# Client.select(:all, :order => 'name desc') # returns all records ordered by name in desc order where name attribute exists
|
350
|
+
#
|
351
|
+
# see http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?UsingSelect.html
|
352
|
+
#
|
353
353
|
def select(*args)
|
354
354
|
find(*args)
|
355
355
|
end
|
@@ -364,28 +364,28 @@ module SimpleRecord
|
|
364
364
|
SimpleRecord.logger
|
365
365
|
end
|
366
366
|
|
367
|
-
|
367
|
+
# Select
|
368
368
|
|
369
369
|
def select_from_ids(args, options) # :nodoc:
|
370
370
|
cond = []
|
371
|
-
|
371
|
+
# detect amount of records requested
|
372
372
|
bunch_of_records_requested = args.size > 1 || args.first.is_a?(Array)
|
373
|
-
|
373
|
+
# flatten ids
|
374
374
|
args = args.to_a.flatten
|
375
375
|
args.each { |id| cond << "itemName() = #{self.connection.escape(id)}" }
|
376
376
|
ids_cond = "(#{cond.join(' OR ')})"
|
377
|
-
|
377
|
+
# user defined :conditions to string (if it was defined)
|
378
378
|
options[:conditions] = build_conditions(options[:conditions])
|
379
|
-
|
379
|
+
# join ids condition and user defined conditions
|
380
380
|
options[:conditions] = options[:conditions].blank? ? ids_cond : "(#{options[:conditions]}) AND #{ids_cond}"
|
381
|
-
|
381
|
+
#puts 'options=' + options.inspect
|
382
382
|
result = sql_select(options)
|
383
|
-
|
384
|
-
|
383
|
+
#puts 'select_from_ids result=' + result.inspect
|
384
|
+
# if one record was requested then return it
|
385
385
|
unless bunch_of_records_requested
|
386
386
|
result[:single_only] = true
|
387
387
|
record = result[:items].first
|
388
|
-
|
388
|
+
# railse if nothing was found
|
389
389
|
raise SimpleRecord::RecordNotFound.new("Couldn't find #{name} with ID #{args}") unless record || is_sharded?
|
390
390
|
result[:single] = record
|
391
391
|
else
|
@@ -405,21 +405,38 @@ module SimpleRecord
|
|
405
405
|
|
406
406
|
def sql_select(options) # :nodoc:
|
407
407
|
count = options[:count] || false
|
408
|
-
|
408
|
+
#puts 'count? ' + count.to_s
|
409
409
|
@next_token = options[:next_token]
|
410
410
|
@consistent_read = options[:consistent_read]
|
411
411
|
select_expression = build_select(options)
|
412
412
|
logger.debug 'SELECT=' + select_expression
|
413
|
-
|
414
|
-
|
415
|
-
# puts 'QR=' + query_result.inspect
|
416
|
-
@next_token = query_result[:next_token]
|
413
|
+
# request items
|
414
|
+
|
417
415
|
ret = {}
|
418
416
|
if count
|
419
|
-
|
420
|
-
|
417
|
+
# we'll keep going to get full count
|
418
|
+
total_count = 0
|
419
|
+
total_box_usage = 0
|
420
|
+
query_result = self.connection.select(select_expression, options) do |result|
|
421
|
+
#puts 'result=' + result.inspect
|
422
|
+
total_count += result[:items][0]["Domain"]["Count"][0].to_i # result.delete(:items)[0]["Domain"]["Count"][0].to_i
|
423
|
+
total_box_usage += result[:box_usage].to_i
|
424
|
+
true #continue loop
|
425
|
+
end
|
426
|
+
ret[:count] = total_count
|
427
|
+
ret[:box_usage] = total_box_usage
|
421
428
|
return ret
|
429
|
+
else
|
430
|
+
query_result = self.connection.select(select_expression, options)
|
431
|
+
@next_token = query_result[:next_token]
|
422
432
|
end
|
433
|
+
# puts 'QR=' + query_result.inspect
|
434
|
+
|
435
|
+
#if count
|
436
|
+
#ret[:count] = query_result.delete(:items)[0]["Domain"]["Count"][0].to_i
|
437
|
+
#ret.merge!(query_result)
|
438
|
+
#return ret
|
439
|
+
#end
|
423
440
|
|
424
441
|
items = query_result.delete(:items).map do |hash|
|
425
442
|
id, attributes = hash.shift
|
@@ -433,7 +450,7 @@ module SimpleRecord
|
|
433
450
|
ret
|
434
451
|
end
|
435
452
|
|
436
|
-
|
453
|
+
# select_by helpers
|
437
454
|
def select_all_by_(format_str, args, options) # :nodoc:
|
438
455
|
fields = format_str.to_s.sub(/^select_(all_)?by_/, '').split('_and_')
|
439
456
|
conditions = fields.map { |field| "#{field}=?" }.join(' AND ')
|
@@ -446,11 +463,11 @@ module SimpleRecord
|
|
446
463
|
select_all_by_(format_str, args, options).first
|
447
464
|
end
|
448
465
|
|
449
|
-
|
466
|
+
# Query
|
450
467
|
|
451
|
-
|
452
|
-
|
453
|
-
|
468
|
+
# Returns an array of query attributes.
|
469
|
+
# Query_expression must be a well formated SDB query string:
|
470
|
+
# query_attributes("['title' starts-with 'O\\'Reily'] intersection ['year' = '2007']") #=> ["title", "year"]
|
454
471
|
def query_attributes(query_expression) # :nodoc:
|
455
472
|
attrs = []
|
456
473
|
array = query_expression.scan(/['"](.*?[^\\])['"]/).flatten
|
@@ -461,33 +478,33 @@ module SimpleRecord
|
|
461
478
|
attrs
|
462
479
|
end
|
463
480
|
|
464
|
-
|
481
|
+
# Returns an array of [attribute_name, 'asc'|'desc']
|
465
482
|
def sort_options(sort_string)
|
466
483
|
sort_string[/['"]?(\w+)['"]? *(asc|desc)?/i]
|
467
484
|
[$1, ($2 || 'asc')]
|
468
485
|
end
|
469
486
|
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
487
|
+
# Perform a query request.
|
488
|
+
#
|
489
|
+
# Options
|
490
|
+
# :query_expression nil | string | array
|
491
|
+
# :max_number_of_items nil | integer
|
492
|
+
# :next_token nil | string
|
493
|
+
# :sort_option nil | string "name desc|asc"
|
494
|
+
#
|
478
495
|
def query(options) # :nodoc:
|
479
496
|
@next_token = options[:next_token]
|
480
497
|
@consistent_read = options[:consistent_read]
|
481
498
|
query_expression = build_conditions(options[:query_expression])
|
482
|
-
|
499
|
+
# add sort_options to the query_expression
|
483
500
|
if options[:sort_option]
|
484
501
|
sort_by, sort_order = sort_options(options[:sort_option])
|
485
502
|
sort_query_expression = "['#{sort_by}' starts-with '']"
|
486
503
|
sort_by_expression = " sort '#{sort_by}' #{sort_order}"
|
487
|
-
|
504
|
+
# make query_expression to be a string (it may be null)
|
488
505
|
query_expression = query_expression.to_s
|
489
|
-
|
490
|
-
|
506
|
+
# quote from Amazon:
|
507
|
+
# The sort attribute must be present in at least one of the predicates of the query expression.
|
491
508
|
if query_expression.blank?
|
492
509
|
query_expression = sort_query_expression
|
493
510
|
elsif !query_attributes(query_expression).include?(sort_by)
|
@@ -495,7 +512,7 @@ module SimpleRecord
|
|
495
512
|
end
|
496
513
|
query_expression += sort_by_expression
|
497
514
|
end
|
498
|
-
|
515
|
+
# request items
|
499
516
|
query_result = self.connection.query(domain, query_expression, options[:max_number_of_items], @next_token, @consistent_read)
|
500
517
|
@next_token = query_result[:next_token]
|
501
518
|
items = query_result[:items].map do |name|
|
@@ -507,7 +524,7 @@ module SimpleRecord
|
|
507
524
|
items
|
508
525
|
end
|
509
526
|
|
510
|
-
|
527
|
+
# reload a record unless it is nil
|
511
528
|
def reload_if_exists(record) # :nodoc:
|
512
529
|
record && record.reload
|
513
530
|
end
|
@@ -533,21 +550,21 @@ module SimpleRecord
|
|
533
550
|
|
534
551
|
def find_from_ids(args, options) # :nodoc:
|
535
552
|
cond = []
|
536
|
-
|
553
|
+
# detect amount of records requested
|
537
554
|
bunch_of_records_requested = args.size > 1 || args.first.is_a?(Array)
|
538
|
-
|
555
|
+
# flatten ids
|
539
556
|
args = args.to_a.flatten
|
540
557
|
args.each { |id| cond << "'id'=#{self.connection.escape(id)}" }
|
541
558
|
ids_cond = "[#{cond.join(' OR ')}]"
|
542
|
-
|
559
|
+
# user defined :conditions to string (if it was defined)
|
543
560
|
options[:conditions] = build_conditions(options[:conditions])
|
544
|
-
|
561
|
+
# join ids condition and user defined conditions
|
545
562
|
options[:conditions] = options[:conditions].blank? ? ids_cond : "#{options[:conditions]} intersection #{ids_cond}"
|
546
563
|
result = find_every(options)
|
547
|
-
|
564
|
+
# if one record was requested then return it
|
548
565
|
unless bunch_of_records_requested
|
549
566
|
record = result.first
|
550
|
-
|
567
|
+
# railse if nothing was found
|
551
568
|
raise ActiveSdbError.new("Couldn't find #{name} with ID #{args}") unless record
|
552
569
|
options[:auto_load] ? reload_all_records(record).first : record
|
553
570
|
else
|
@@ -562,7 +579,7 @@ module SimpleRecord
|
|
562
579
|
end
|
563
580
|
end
|
564
581
|
|
565
|
-
|
582
|
+
# find_by helpers
|
566
583
|
def find_all_by_(format_str, args, options) # :nodoc:
|
567
584
|
fields = format_str.to_s.sub(/^find_(all_)?by_/, '').split('_and_')
|
568
585
|
conditions = fields.map { |field| "['#{field}'=?]" }.join(' intersection ')
|
@@ -575,7 +592,7 @@ module SimpleRecord
|
|
575
592
|
find_all_by_(format_str, args, options).first
|
576
593
|
end
|
577
594
|
|
578
|
-
|
595
|
+
# Misc
|
579
596
|
|
580
597
|
def method_missing(method, *args) # :nodoc:
|
581
598
|
if method.to_s[/^(find_all_by_|find_by_|select_all_by_|select_by_)/]
|
@@ -598,13 +615,13 @@ module SimpleRecord
|
|
598
615
|
def build_select(options) # :nodoc:
|
599
616
|
select = options[:select] || '*'
|
600
617
|
select = options[:count] ? "count(*)" : select
|
601
|
-
|
618
|
+
#puts 'select=' + select.to_s
|
602
619
|
from = options[:from] || domain
|
603
620
|
condition_fields = parse_condition_fields(options[:conditions])
|
604
621
|
conditions = options[:conditions] ? "#{build_conditions(options[:conditions])}" : ''
|
605
622
|
order = options[:order] ? " ORDER BY #{options[:order]}" : ''
|
606
623
|
limit = options[:limit] ? " LIMIT #{options[:limit]}" : ''
|
607
|
-
|
624
|
+
# mix sort by argument (it must present in response)
|
608
625
|
unless order.blank?
|
609
626
|
sort_by, sort_order = sort_options(options[:order])
|
610
627
|
if condition_fields.nil? || !condition_fields.include?(sort_by)
|
@@ -616,7 +633,7 @@ module SimpleRecord
|
|
616
633
|
|
617
634
|
end
|
618
635
|
conditions = conditions.blank? ? "" : " WHERE #{conditions}"
|
619
|
-
# puts 'CONDITIONS=' + conditions
|
636
|
+
# puts 'CONDITIONS=' + conditions
|
620
637
|
"SELECT #{select} FROM `#{from}`#{conditions}#{order}#{limit}"
|
621
638
|
end
|
622
639
|
|
@@ -631,7 +648,7 @@ module SimpleRecord
|
|
631
648
|
end
|
632
649
|
end
|
633
650
|
|
634
|
-
|
651
|
+
# This will currently return and's, or's and betweens. Doesn't hurt anything, but could remove.
|
635
652
|
def parse_condition_fields(conditions)
|
636
653
|
return nil unless conditions && conditions.present? && conditions.is_a?(Array)
|
637
654
|
rx = /\b(\w*)[\s|>=|<=|!=|=|>|<|like|between]/
|
@@ -644,71 +661,71 @@ module SimpleRecord
|
|
644
661
|
|
645
662
|
public
|
646
663
|
|
647
|
-
|
664
|
+
# instance attributes
|
648
665
|
attr_accessor :attributes
|
649
666
|
|
650
|
-
|
667
|
+
# item name
|
651
668
|
attr_accessor :id
|
652
669
|
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
670
|
+
# Create new Item instance.
|
671
|
+
# +attrs+ is a hash: { attribute1 => values1, ..., attributeN => valuesN }.
|
672
|
+
#
|
673
|
+
# item = Client.new('name' => 'Jon', 'toys' => ['girls', 'beer', 'pub'])
|
674
|
+
# puts item.inspect #=> #<Client:0xb77a2698 @new_record=true, @attributes={"name"=>["Jon"], "toys"=>["girls", "beer", "pub"]}>
|
675
|
+
# item.save #=> {"name"=>["Jon"], "id"=>"c03edb7e-e45c-11dc-bede-001bfc466dd7", "toys"=>["girls", "beer", "pub"]}
|
676
|
+
# puts item.inspect #=> #<Client:0xb77a2698 @new_record=false, @attributes={"name"=>["Jon"], "id"=>"c03edb7e-e45c-11dc-bede-001bfc466dd7", "toys"=>["girls", "beer", "pub"]}>
|
677
|
+
#
|
661
678
|
def initialize(attrs={})
|
662
679
|
@attributes = uniq_values(attrs)
|
663
680
|
@new_record = true
|
664
681
|
end
|
665
682
|
|
666
|
-
|
683
|
+
# This is to separate initialization from user vs coming from db (ie: find())
|
667
684
|
def initialize_from_db(attrs={})
|
668
685
|
initialize(attrs)
|
669
686
|
end
|
670
687
|
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
688
|
+
# Create and save new Item instance.
|
689
|
+
# +Attributes+ is a hash: { attribute1 => values1, ..., attributeN => valuesN }.
|
690
|
+
#
|
691
|
+
# item = Client.create('name' => 'Cat', 'toys' => ['Jons socks', 'mice', 'clew'])
|
692
|
+
# puts item.inspect #=> #<Client:0xb77a0a78 @new_record=false, @attributes={"name"=>["Cat"], "id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "toys"=>["Jons socks", "mice", "clew"]}>
|
693
|
+
#
|
677
694
|
def self.create(attributes={})
|
678
695
|
item = self.new(attributes)
|
679
696
|
item.save
|
680
697
|
item
|
681
698
|
end
|
682
699
|
|
683
|
-
|
700
|
+
# Returns an item id. Same as: item['id'] or item.attributes['id']
|
684
701
|
def id
|
685
702
|
@attributes['id']
|
686
703
|
end
|
687
704
|
|
688
|
-
|
705
|
+
# Sets an item id.
|
689
706
|
def id=(id)
|
690
707
|
@attributes['id'] = id.to_s
|
691
708
|
end
|
692
709
|
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
710
|
+
# Returns a hash of all the attributes.
|
711
|
+
#
|
712
|
+
# puts item.attributes.inspect #=> {"name"=>["Cat"], "id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "toys"=>["Jons socks", "clew", "mice"]}
|
713
|
+
#
|
697
714
|
def attributes
|
698
715
|
@attributes.dup
|
699
716
|
end
|
700
717
|
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
718
|
+
# Allows one to set all the attributes at once by passing in a hash with keys matching the attribute names.
|
719
|
+
# if '+id+' attribute is not set in new attributes has then it being derived from old attributes.
|
720
|
+
#
|
721
|
+
# puts item.attributes.inspect #=> {"name"=>["Cat"], "id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "toys"=>["Jons socks", "clew", "mice"]}
|
722
|
+
# # set new attributes ('id' is missed)
|
723
|
+
# item.attributes = { 'name'=>'Dog', 'toys'=>['bones','cats'] }
|
724
|
+
# puts item.attributes.inspect #=> {"name"=>["Dog"], "id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "toys"=>["bones", "cats"]}
|
725
|
+
# # set new attributes ('id' is set)
|
726
|
+
# item.attributes = { 'id' => 'blah-blah', 'name'=>'Birds', 'toys'=>['seeds','dogs tail'] }
|
727
|
+
# puts item.attributes.inspect #=> {"name"=>["Birds"], "id"=>"blah-blah", "toys"=>["seeds", "dogs tail"]}
|
728
|
+
#
|
712
729
|
def attributes=(attrs)
|
713
730
|
old_id = @attributes['id']
|
714
731
|
@attributes = uniq_values(attrs)
|
@@ -720,36 +737,36 @@ module SimpleRecord
|
|
720
737
|
self.class.connection
|
721
738
|
end
|
722
739
|
|
723
|
-
|
740
|
+
# Item domain name.
|
724
741
|
def domain
|
725
742
|
self.class.domain
|
726
743
|
end
|
727
744
|
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
745
|
+
# Returns the values of the attribute identified by +attribute+.
|
746
|
+
#
|
747
|
+
# puts item['Cat'].inspect #=> ["Jons socks", "clew", "mice"]
|
748
|
+
#
|
732
749
|
def [](attribute)
|
733
750
|
@attributes[attribute.to_s]
|
734
751
|
end
|
735
752
|
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
753
|
+
# Updates the attribute identified by +attribute+ with the specified +values+.
|
754
|
+
#
|
755
|
+
# puts item['Cat'].inspect #=> ["Jons socks", "clew", "mice"]
|
756
|
+
# item['Cat'] = ["Whiskas", "chicken"]
|
757
|
+
# puts item['Cat'].inspect #=> ["Whiskas", "chicken"]
|
758
|
+
#
|
742
759
|
def []=(attribute, values)
|
743
760
|
attribute = attribute.to_s
|
744
761
|
@attributes[attribute] = attribute == 'id' ? values.to_s : values.is_a?(Array) ? values.uniq : [values]
|
745
762
|
|
746
763
|
end
|
747
764
|
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
765
|
+
# Reload attributes from SDB. Replaces in-memory attributes.
|
766
|
+
#
|
767
|
+
# item = Client.find_by_name('Cat') #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7"}, @new_record=false>
|
768
|
+
# item.reload #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "name"=>["Cat"], "toys"=>["Jons socks", "clew", "mice"]}, @new_record=false>
|
769
|
+
#
|
753
770
|
def reload
|
754
771
|
raise_on_id_absence
|
755
772
|
old_id = id
|
@@ -763,16 +780,16 @@ module SimpleRecord
|
|
763
780
|
@attributes
|
764
781
|
end
|
765
782
|
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
783
|
+
# Reload a set of attributes from SDB. Adds the loaded list to in-memory data.
|
784
|
+
# +attrs_list+ is an array or comma separated list of attributes names.
|
785
|
+
# Returns a hash of loaded attributes.
|
786
|
+
#
|
787
|
+
# This is not the best method to get a bunch of attributes because
|
788
|
+
# a web service call is being performed for every attribute.
|
789
|
+
#
|
790
|
+
# item = Client.find_by_name('Cat')
|
791
|
+
# item.reload_attributes('toys', 'name') #=> {"name"=>["Cat"], "toys"=>["Jons socks", "clew", "mice"]}
|
792
|
+
#
|
776
793
|
def reload_attributes(*attrs_list)
|
777
794
|
raise_on_id_absence
|
778
795
|
attrs_list = attrs_list.flatten.map { |attribute| attribute.to_s }
|
@@ -791,21 +808,21 @@ module SimpleRecord
|
|
791
808
|
result
|
792
809
|
end
|
793
810
|
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
811
|
+
# Stores in-memory attributes to SDB.
|
812
|
+
# Adds the attributes values to already stored at SDB.
|
813
|
+
# Returns a hash of stored attributes.
|
814
|
+
#
|
815
|
+
# sandy = Client.new(:name => 'Sandy') #=> #<Client:0xb775a7a8 @attributes={"name"=>["Sandy"]}, @new_record=true>
|
816
|
+
# sandy['toys'] = 'boys'
|
817
|
+
# sandy.put
|
818
|
+
# sandy['toys'] = 'patchwork'
|
819
|
+
# sandy.put
|
820
|
+
# sandy['toys'] = 'kids'
|
821
|
+
# sandy.put
|
822
|
+
# puts sandy.attributes.inspect #=> {"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["kids"]}
|
823
|
+
# sandy.reload #=> {"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids", "patchwork"]}
|
824
|
+
#
|
825
|
+
# compare to +save+ method
|
809
826
|
def put
|
810
827
|
@attributes = uniq_values(@attributes)
|
811
828
|
prepare_for_update
|
@@ -817,19 +834,19 @@ module SimpleRecord
|
|
817
834
|
@attributes
|
818
835
|
end
|
819
836
|
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
837
|
+
# Stores specified attributes.
|
838
|
+
# +attrs+ is a hash: { attribute1 => values1, ..., attributeN => valuesN }.
|
839
|
+
# Returns a hash of saved attributes.
|
840
|
+
#
|
841
|
+
# see to +put+ method
|
825
842
|
def put_attributes(attrs)
|
826
843
|
attrs = uniq_values(attrs)
|
827
844
|
prepare_for_update
|
828
|
-
|
829
|
-
|
845
|
+
# if 'id' is present in attrs hash:
|
846
|
+
# replace internal 'id' attribute and remove it from the attributes to be sent
|
830
847
|
@attributes['id'] = attrs['id'] unless attrs['id'].blank?
|
831
848
|
attrs.delete('id')
|
832
|
-
|
849
|
+
# add new values to all attributes from list
|
833
850
|
connection.put_attributes(domain, id, attrs) unless attrs.blank?
|
834
851
|
connection.put_attributes(domain, id, {'id' => id}, :replace)
|
835
852
|
attrs.each do |attribute, values|
|
@@ -841,42 +858,42 @@ module SimpleRecord
|
|
841
858
|
attributes
|
842
859
|
end
|
843
860
|
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
861
|
+
# Store in-memory attributes to SDB.
|
862
|
+
# Replaces the attributes values already stored at SDB by in-memory data.
|
863
|
+
# Returns a hash of stored attributes.
|
864
|
+
#
|
865
|
+
# sandy = Client.new(:name => 'Sandy') #=> #<Client:0xb775a7a8 @attributes={"name"=>["Sandy"]}, @new_record=true>
|
866
|
+
# sandy['toys'] = 'boys'
|
867
|
+
# sandy.save
|
868
|
+
# sandy['toys'] = 'patchwork'
|
869
|
+
# sandy.save
|
870
|
+
# sandy['toys'] = 'kids'
|
871
|
+
# sandy.save
|
872
|
+
# puts sandy.attributes.inspect #=> {"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["kids"]}
|
873
|
+
# sandy.reload #=> {"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["kids"]}
|
874
|
+
#
|
875
|
+
# Options:
|
876
|
+
# - :except => Array of attributes to NOT save
|
877
|
+
#
|
878
|
+
# compare to +put+ method
|
862
879
|
def save2(options={})
|
863
880
|
options[:create_domain] = true if options[:create_domain].nil?
|
864
881
|
pre_save2
|
865
882
|
atts_to_save = @attributes.dup
|
866
|
-
|
867
|
-
|
883
|
+
#puts 'atts_to_save=' + atts_to_save.inspect
|
884
|
+
#options = params.first.is_a?(Hash) ? params.pop : {}
|
868
885
|
if options[:except]
|
869
886
|
options[:except].each do |e|
|
870
887
|
atts_to_save.delete(e).inspect
|
871
888
|
end
|
872
889
|
end
|
873
890
|
if options[:dirty] # Only used in simple_record right now
|
874
|
-
|
891
|
+
# only save if the attribute is dirty
|
875
892
|
dirty_atts = options[:dirty_atts]
|
876
893
|
atts_to_save.delete_if { |key, value| !dirty_atts.has_key?(key) }
|
877
894
|
end
|
878
895
|
dom = options[:domain] || domain
|
879
|
-
|
896
|
+
#puts 'atts_to_save2=' + atts_to_save.inspect
|
880
897
|
connection.put_attributes(dom, id, atts_to_save, :replace, options)
|
881
898
|
apres_save2
|
882
899
|
@attributes
|
@@ -891,16 +908,16 @@ module SimpleRecord
|
|
891
908
|
mark_as_old
|
892
909
|
end
|
893
910
|
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
911
|
+
# Replaces the attributes at SDB by the given values.
|
912
|
+
# +Attrs+ is a hash: { attribute1 => values1, ..., attributeN => valuesN }.
|
913
|
+
# The other in-memory attributes are not being saved.
|
914
|
+
# Returns a hash of stored attributes.
|
915
|
+
#
|
916
|
+
# see +save+ method
|
900
917
|
def save_attributes(attrs)
|
901
918
|
prepare_for_update
|
902
919
|
attrs = uniq_values(attrs)
|
903
|
-
|
920
|
+
# if 'id' is present in attrs hash then replace internal 'id' attribute
|
904
921
|
unless attrs['id'].blank?
|
905
922
|
@attributes['id'] = attrs['id']
|
906
923
|
else
|
@@ -912,15 +929,15 @@ module SimpleRecord
|
|
912
929
|
attrs
|
913
930
|
end
|
914
931
|
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
932
|
+
# Remove specified values from corresponding attributes.
|
933
|
+
# +attrs+ is a hash: { attribute1 => values1, ..., attributeN => valuesN }.
|
934
|
+
#
|
935
|
+
# sandy = Client.find_by_name 'Sandy'
|
936
|
+
# sandy.reload
|
937
|
+
# puts sandy.inspect #=> #<Client:0xb77b48fc @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids", "patchwork"]}>
|
938
|
+
# puts sandy.delete_values('toys' => 'patchwork') #=> { 'toys' => ['patchwork'] }
|
939
|
+
# puts sandy.inspect #=> #<Client:0xb77b48fc @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids"]}>
|
940
|
+
#
|
924
941
|
def delete_values(attrs)
|
925
942
|
raise_on_id_absence
|
926
943
|
attrs = uniq_values(attrs)
|
@@ -940,16 +957,16 @@ module SimpleRecord
|
|
940
957
|
attrs
|
941
958
|
end
|
942
959
|
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
960
|
+
# Removes specified attributes from the item.
|
961
|
+
# +attrs_list+ is an array or comma separated list of attributes names.
|
962
|
+
# Returns the list of deleted attributes.
|
963
|
+
#
|
964
|
+
# sandy = Client.find_by_name 'Sandy'
|
965
|
+
# sandy.reload
|
966
|
+
# puts sandy.inspect #=> #<Client:0xb7761d28 @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids", "patchwork"}>
|
967
|
+
# puts sandy.delete_attributes('toys') #=> ['toys']
|
968
|
+
# puts sandy.inspect #=> #<Client:0xb7761d28 @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7"}>
|
969
|
+
#
|
953
970
|
def delete_attributes(*attrs_list)
|
954
971
|
raise_on_id_absence
|
955
972
|
attrs_list = attrs_list.flatten.map { |attribute| attribute.to_s }
|
@@ -961,21 +978,21 @@ module SimpleRecord
|
|
961
978
|
attrs_list
|
962
979
|
end
|
963
980
|
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
981
|
+
# Delete the Item entirely from SDB.
|
982
|
+
#
|
983
|
+
# sandy = Client.find_by_name 'Sandy'
|
984
|
+
# sandy.reload
|
985
|
+
# sandy.inspect #=> #<Client:0xb7761d28 @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids", "patchwork"}>
|
986
|
+
# puts sandy.delete
|
987
|
+
# sandy.reload
|
988
|
+
# puts sandy.inspect #=> #<Client:0xb7761d28 @attributes={}, @new_record=false>
|
989
|
+
#
|
973
990
|
def delete(options={})
|
974
991
|
raise_on_id_absence
|
975
992
|
connection.delete_attributes(options[:domain] || domain, id)
|
976
993
|
end
|
977
994
|
|
978
|
-
|
995
|
+
# Returns true if this object hasn�t been saved yet.
|
979
996
|
def new_record?
|
980
997
|
@new_record
|
981
998
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: simple_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 2.
|
5
|
+
version: 2.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Travis Reeder
|
@@ -12,7 +12,7 @@ autorequire:
|
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
14
|
|
15
|
-
date: 2011-07-
|
15
|
+
date: 2011-07-08 00:00:00 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: aws
|