appoxy-simple_record 1.0.10 → 1.0.15
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/{README.txt → README.markdown} +0 -0
- data/lib/simple_record.rb +901 -0
- data/test/my_child_model.rb +5 -5
- data/test/my_model.rb +10 -10
- data/test/temp_test.rb +63 -63
- metadata +5 -4
|
File without changes
|
|
@@ -0,0 +1,901 @@
|
|
|
1
|
+
# Usage:
|
|
2
|
+
# require 'simple_record'
|
|
3
|
+
#
|
|
4
|
+
# class MyModel < SimpleRecord::Base
|
|
5
|
+
#
|
|
6
|
+
# has_attributes :name, :age
|
|
7
|
+
# are_ints :age
|
|
8
|
+
#
|
|
9
|
+
# end
|
|
10
|
+
#
|
|
11
|
+
# AWS_ACCESS_KEY_ID='XXXXX'
|
|
12
|
+
# AWS_SECRET_ACCESS_KEY='YYYYY'
|
|
13
|
+
# RightAws::ActiveSdb.establish_connection(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY)
|
|
14
|
+
# # Save an object
|
|
15
|
+
# mm = MyModel.new
|
|
16
|
+
# mm.name = "Travis"
|
|
17
|
+
# mm.age = 32
|
|
18
|
+
# mm.save
|
|
19
|
+
# id = mm.id
|
|
20
|
+
# # Get the object back
|
|
21
|
+
# mm2 = MyModel.select(id)
|
|
22
|
+
# puts 'got=' + mm2.name + ' and he/she is ' + mm.age.to_s + ' years old'
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
require 'right_aws'
|
|
27
|
+
require 'sdb/active_sdb'
|
|
28
|
+
|
|
29
|
+
module SimpleRecord
|
|
30
|
+
|
|
31
|
+
VERSION = '1.0.9'
|
|
32
|
+
|
|
33
|
+
class Base < RightAws::ActiveSdb::Base
|
|
34
|
+
|
|
35
|
+
attr_accessor :errors
|
|
36
|
+
@@domain_prefix = ''
|
|
37
|
+
@domain_name_for_class = nil
|
|
38
|
+
|
|
39
|
+
@@cache_store = nil
|
|
40
|
+
# Set the cache to use
|
|
41
|
+
def self.cache_store=(cache)
|
|
42
|
+
@@cache_store = cache
|
|
43
|
+
end
|
|
44
|
+
def self.cache_store
|
|
45
|
+
return @@cache_store
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# If you want a domain prefix for all your models, set it here.
|
|
49
|
+
def self.set_domain_prefix(prefix)
|
|
50
|
+
@@domain_prefix = prefix
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Same as set_table_name
|
|
54
|
+
def self.set_table_name(table_name)
|
|
55
|
+
set_domain_name table_name
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Sets the domain name for this class
|
|
59
|
+
def self.set_domain_name(table_name)
|
|
60
|
+
# puts 'setting domain name for class ' + self.inspect + '=' + table_name
|
|
61
|
+
@domain_name_for_class = table_name
|
|
62
|
+
super
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.get_domain_name
|
|
66
|
+
# puts 'returning domain_name=' + @domain_name_for_class.to_s
|
|
67
|
+
return @domain_name_for_class
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def domain
|
|
72
|
+
super # super.domain
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.domain
|
|
76
|
+
return self.get_domain_name unless self.get_domain_name.nil?
|
|
77
|
+
d = super
|
|
78
|
+
domain_name_for_class = @@domain_prefix + d.to_s
|
|
79
|
+
self.set_domain_name(domain_name_for_class)
|
|
80
|
+
domain_name_for_class
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
#this bit of code creates a "run_blank" function for everything value in the @@callbacks array.
|
|
84
|
+
#this function can then be inserted in the appropriate place in the save, new, destroy, etc overrides
|
|
85
|
+
#basically, this is how we recreate the callback functions
|
|
86
|
+
@@callbacks=["before_save", "before_create", "after_create", "before_update", "after_update", "after_save", "after_destroy"]
|
|
87
|
+
@@callbacks.each do |callback|
|
|
88
|
+
#we first have to make an initialized array for each of the callbacks, to prevent problems if they are not called
|
|
89
|
+
eval %{
|
|
90
|
+
@@#{callback}_names=[]
|
|
91
|
+
|
|
92
|
+
def self.#{callback}(*args)
|
|
93
|
+
args.each do |arg|
|
|
94
|
+
@@#{callback}_names << arg.to_s if @@#{callback}_names.index(arg.to_s).nil?
|
|
95
|
+
end
|
|
96
|
+
# asdf @@#{callback}_names=args.map{|arg| arg.to_s}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def run_#{callback}
|
|
100
|
+
@@#{callback}_names.each { |name|
|
|
101
|
+
unless eval(name)
|
|
102
|
+
return false
|
|
103
|
+
end
|
|
104
|
+
}
|
|
105
|
+
return true
|
|
106
|
+
end
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def self.has_attributes(*args)
|
|
111
|
+
@@attributes = args
|
|
112
|
+
args.each do |arg|
|
|
113
|
+
# define reader method
|
|
114
|
+
send :define_method, arg do
|
|
115
|
+
ret = nil
|
|
116
|
+
if self[arg.to_s].class==Array
|
|
117
|
+
if self[arg.to_s].length==1
|
|
118
|
+
ret = self[arg.to_s][0]
|
|
119
|
+
else
|
|
120
|
+
ret = self[arg.to_s]
|
|
121
|
+
end
|
|
122
|
+
else
|
|
123
|
+
ret = self[arg.to_s]
|
|
124
|
+
end
|
|
125
|
+
return nil if ret.nil?
|
|
126
|
+
return un_offset_if_int(arg, ret)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# define writer method
|
|
130
|
+
method_name = (arg.to_s+"=")
|
|
131
|
+
send(:define_method, method_name) do |value|
|
|
132
|
+
self[arg.to_s]=value# end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
@@ints = []
|
|
138
|
+
def self.are_ints(*args)
|
|
139
|
+
# puts 'calling are_ints: ' + args.inspect
|
|
140
|
+
args.each do |arg|
|
|
141
|
+
# todo: maybe @@ints and @@dates should be maps for quicker lookups
|
|
142
|
+
@@ints << arg if @@ints.index(arg).nil?
|
|
143
|
+
end
|
|
144
|
+
# @@ints = args
|
|
145
|
+
# puts 'ints=' + @@ints.inspect
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
@@dates = []
|
|
149
|
+
def self.are_dates(*args)
|
|
150
|
+
args.each do |arg|
|
|
151
|
+
@@dates << arg if @@dates.index(arg).nil?
|
|
152
|
+
end
|
|
153
|
+
# @@dates = args
|
|
154
|
+
# puts 'dates=' + @@dates.inspect
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
@@booleans = []
|
|
158
|
+
def self.are_booleans(*args)
|
|
159
|
+
args.each do |arg|
|
|
160
|
+
@@booleans << arg if @@booleans.index(arg).nil?
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
@@virtuals=[]
|
|
165
|
+
def self.has_virtuals(*args)
|
|
166
|
+
@@virtuals = args
|
|
167
|
+
args.each do |arg|
|
|
168
|
+
#we just create the accessor functions here, the actual instance variable is created during initialize
|
|
169
|
+
attr_accessor(arg)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
@@belongs_to_map = {}
|
|
174
|
+
# One belongs_to association per call. Call multiple times if there are more than one.
|
|
175
|
+
#
|
|
176
|
+
# This method will also create an {association)_id method that will return the ID of the foreign object
|
|
177
|
+
# without actually materializing it.
|
|
178
|
+
def self.belongs_to(association_id, options = {})
|
|
179
|
+
@@belongs_to_map[association_id] = options
|
|
180
|
+
arg = association_id
|
|
181
|
+
arg_id = arg.to_s + '_id'
|
|
182
|
+
|
|
183
|
+
# todo: should also handle foreign_key http://74.125.95.132/search?q=cache:KqLkxuXiBBQJ:wiki.rubyonrails.org/rails/show/belongs_to+rails+belongs_to&hl=en&ct=clnk&cd=1&gl=us
|
|
184
|
+
# puts "arg_id=#{arg}_id"
|
|
185
|
+
# puts "is defined? " + eval("(defined? #{arg}_id)").to_s
|
|
186
|
+
# puts 'atts=' + @attributes.inspect
|
|
187
|
+
|
|
188
|
+
# Define reader method
|
|
189
|
+
send(:define_method, arg) do
|
|
190
|
+
options2 = @@belongs_to_map[arg]
|
|
191
|
+
class_name = options2[:class_name] || arg.to_s[0...1].capitalize + arg.to_s[1...arg.to_s.length]
|
|
192
|
+
# puts "attr=" + @attributes[arg_id].inspect
|
|
193
|
+
# puts 'val=' + @attributes[arg_id][0].inspect unless @attributes[arg_id].nil?
|
|
194
|
+
ret = nil
|
|
195
|
+
arg_id = arg.to_s + '_id'
|
|
196
|
+
if !@attributes[arg_id].nil? && @attributes[arg_id].size > 0 && @attributes[arg_id][0] != nil && @attributes[arg_id][0] != ''
|
|
197
|
+
if !@@cache_store.nil?
|
|
198
|
+
arg_id_val = @attributes[arg_id][0]
|
|
199
|
+
cache_key = self.class.cache_key(class_name, arg_id_val)
|
|
200
|
+
# puts 'cache_key=' + cache_key
|
|
201
|
+
ret = @@cache_store.read(cache_key)
|
|
202
|
+
# puts 'belongs_to incache=' + ret.inspect
|
|
203
|
+
end
|
|
204
|
+
if ret.nil?
|
|
205
|
+
to_eval = "#{class_name}.find(@attributes['#{arg_id}'][0], :auto_load=>true)"
|
|
206
|
+
# puts 'to eval=' + to_eval
|
|
207
|
+
begin
|
|
208
|
+
ret = eval(to_eval) # (defined? #{arg}_id)
|
|
209
|
+
rescue RightAws::ActiveSdb::ActiveSdbError
|
|
210
|
+
if $!.message.include? "Couldn't find"
|
|
211
|
+
ret = nil
|
|
212
|
+
else
|
|
213
|
+
raise $!
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
# puts 'ret=' + ret.inspect
|
|
220
|
+
return ret
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Define reader ID method
|
|
224
|
+
send(:define_method, arg_id) do
|
|
225
|
+
if !@attributes[arg_id].nil? && @attributes[arg_id].size > 0 && @attributes[arg_id][0] != nil && @attributes[arg_id][0] != ''
|
|
226
|
+
return @attributes[arg_id][0]
|
|
227
|
+
end
|
|
228
|
+
return nil
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Define writer method
|
|
232
|
+
send(:define_method, arg.to_s + "=") do |value|
|
|
233
|
+
arg_id = arg.to_s + '_id'
|
|
234
|
+
if value.nil?
|
|
235
|
+
self[arg_id]=nil unless self[arg_id].nil? # if it went from something to nil, then we have to remember and remove attribute on save
|
|
236
|
+
else
|
|
237
|
+
self[arg_id]=value.id
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
send(:define_method, "create_"+arg.to_s) do |*params|
|
|
242
|
+
newsubrecord=eval(arg.to_s.classify).new(*params)
|
|
243
|
+
newsubrecord.save
|
|
244
|
+
arg_id = arg.to_s + '_id'
|
|
245
|
+
self[arg_id]=newsubrecord.id
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def self.has_many(*args)
|
|
250
|
+
args.each do |arg|
|
|
251
|
+
#okay, this creates an instance method with the pluralized name of the symbol passed to belongs_to
|
|
252
|
+
send(:define_method, arg) do
|
|
253
|
+
#when called, the method creates a new, very temporary instance of the Activerecordtosdb_subrecord class
|
|
254
|
+
#It is passed the three initializers it needs:
|
|
255
|
+
#note the first parameter is just a string by time new gets it, like "user"
|
|
256
|
+
#the second and third parameters are still a variable when new gets it, like user_id
|
|
257
|
+
return eval(%{Activerecordtosdb_subrecord_array.new('#{arg}', self.class.name ,id)})
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
#Disclaimer: this whole funciton just seems crazy to me, and a bit inefficient. But it was the clearest way I could think to do it code wise.
|
|
261
|
+
#It's bad programming form (imo) to have a class method require something that isn't passed to it through it's variables.
|
|
262
|
+
#I couldn't pass the id when calling find, since the original find doesn't work that way, so I was left with this.
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def self.has_one(*args)
|
|
266
|
+
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
has_attributes :created, :updated
|
|
270
|
+
before_create :set_created, :set_updated
|
|
271
|
+
before_update :set_updated
|
|
272
|
+
are_dates :created, :updated
|
|
273
|
+
|
|
274
|
+
def set_created
|
|
275
|
+
# puts 'SETTING CREATED'
|
|
276
|
+
# @created = DateTime.now
|
|
277
|
+
self[:created] = DateTime.now
|
|
278
|
+
# @tester = 'some test value'
|
|
279
|
+
# self[:tester] = 'some test value'
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def set_updated
|
|
283
|
+
# puts 'SETTING UPDATED'
|
|
284
|
+
# @updated = DateTime.now
|
|
285
|
+
self[:updated] = DateTime.now
|
|
286
|
+
# @tester = 'some test value updated'
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def initialize(*params)
|
|
290
|
+
if params[0]
|
|
291
|
+
#we have to handle the virtuals. Right now, this assumes that all parameters are passed from inside an array
|
|
292
|
+
#this is the usually the case when the parameters are passed passed via POST and obtained from the params array
|
|
293
|
+
@@virtuals.each do |virtual|
|
|
294
|
+
#we first copy the information for the virtual to an instance variable of the same name
|
|
295
|
+
eval("@#{virtual}=params[0]['#{virtual}']")
|
|
296
|
+
#and then remove the parameter before it is passed to initialize, so that it is NOT sent to SimpleDB
|
|
297
|
+
eval("params[0].delete('#{virtual}')")
|
|
298
|
+
end
|
|
299
|
+
super(*params)
|
|
300
|
+
else
|
|
301
|
+
super()
|
|
302
|
+
end
|
|
303
|
+
@errors=SimpleRecord_errors.new
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@@offset = 9223372036854775808
|
|
308
|
+
@@padding = 20
|
|
309
|
+
@@date_format = "%Y-%m-%dT%H:%M:%S"; # Time to second precision
|
|
310
|
+
|
|
311
|
+
def self.pad_and_offset(x)
|
|
312
|
+
# todo: add Float, etc
|
|
313
|
+
# puts 'padding=' + x.class.name + " -- " + x.inspect
|
|
314
|
+
if x.kind_of? Integer
|
|
315
|
+
x += @@offset
|
|
316
|
+
x_str = x.to_s
|
|
317
|
+
# pad
|
|
318
|
+
x_str = '0' + x_str while x_str.size < 20
|
|
319
|
+
return x_str
|
|
320
|
+
elsif x.respond_to?(:iso8601)
|
|
321
|
+
# puts x.class.name + ' responds to iso8601'
|
|
322
|
+
#
|
|
323
|
+
# There is an issue here where Time.iso8601 on an incomparable value to DateTime.iso8601.
|
|
324
|
+
# Amazon suggests: 2008-02-10T16:52:01.000-05:00
|
|
325
|
+
# "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
|
|
326
|
+
#
|
|
327
|
+
if x.is_a? DateTime
|
|
328
|
+
x_str = x.new_offset(0).strftime(@@date_format)
|
|
329
|
+
else
|
|
330
|
+
x_str = x.getutc.strftime(@@date_format)
|
|
331
|
+
end
|
|
332
|
+
# puts 'utc=' + x_str
|
|
333
|
+
return x_str
|
|
334
|
+
else
|
|
335
|
+
return x
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def domain_ok(ex)
|
|
340
|
+
if (ex.message().index("NoSuchDomain") != nil)
|
|
341
|
+
puts "Creating new SimpleDB Domain: " + domain
|
|
342
|
+
self.class.create_domain
|
|
343
|
+
return true
|
|
344
|
+
end
|
|
345
|
+
return false
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
@create_domain_called = false
|
|
349
|
+
|
|
350
|
+
def save(*params)
|
|
351
|
+
# puts 'SAVING: ' + self.inspect
|
|
352
|
+
is_create = self[:id].nil?
|
|
353
|
+
ok = pre_save(*params)
|
|
354
|
+
if ok
|
|
355
|
+
begin
|
|
356
|
+
# puts 'is frozen? ' + self.frozen?.to_s + ' - ' + self.inspect
|
|
357
|
+
to_delete = get_atts_to_delete
|
|
358
|
+
if super(*params)
|
|
359
|
+
# puts 'SAVED super'
|
|
360
|
+
self.class.cache_results(self)
|
|
361
|
+
delete_niled(to_delete)
|
|
362
|
+
if run_after_save && is_create ? run_after_create : run_after_update
|
|
363
|
+
return true
|
|
364
|
+
else
|
|
365
|
+
#I thought about calling destroy here, but rails doesn't behave that way, so neither will I
|
|
366
|
+
return false
|
|
367
|
+
end
|
|
368
|
+
else
|
|
369
|
+
return false
|
|
370
|
+
end
|
|
371
|
+
rescue RightAws::AwsError
|
|
372
|
+
# puts "RESCUED in save: " + $!
|
|
373
|
+
if (domain_ok($!))
|
|
374
|
+
if !@create_domain_called
|
|
375
|
+
@create_domain_called = true
|
|
376
|
+
save(*params)
|
|
377
|
+
else
|
|
378
|
+
raise $!
|
|
379
|
+
end
|
|
380
|
+
else
|
|
381
|
+
raise $!
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
else
|
|
385
|
+
#@debug = "not saved"
|
|
386
|
+
return false
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def pad_and_offset_ints_to_sdb()
|
|
391
|
+
if !@@ints.nil?
|
|
392
|
+
for i in @@ints
|
|
393
|
+
# puts 'int encoding: ' + i.to_s
|
|
394
|
+
if !self[i.to_s].nil?
|
|
395
|
+
# puts 'before: ' + self[i.to_s].inspect
|
|
396
|
+
# puts @attributes.inspect
|
|
397
|
+
# puts @attributes[i.to_s].inspect
|
|
398
|
+
arr = @attributes[i.to_s]
|
|
399
|
+
arr.collect!{ |x| self.class.pad_and_offset(x) }
|
|
400
|
+
@attributes[i.to_s] = arr
|
|
401
|
+
# puts 'after: ' + @attributes[i.to_s].inspect
|
|
402
|
+
else
|
|
403
|
+
# puts 'was nil'
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
def convert_dates_to_sdb()
|
|
409
|
+
if !@@dates.nil?
|
|
410
|
+
for i in @@dates
|
|
411
|
+
# puts 'int encoding: ' + i.to_s
|
|
412
|
+
if !self[i.to_s].nil?
|
|
413
|
+
# puts 'before: ' + self[i.to_s].inspect
|
|
414
|
+
# puts @attributes.inspect
|
|
415
|
+
# puts @attributes[i.to_s].inspect
|
|
416
|
+
arr = @attributes[i.to_s]
|
|
417
|
+
#puts 'padding date=' + i.to_s
|
|
418
|
+
arr.collect!{ |x| self.class.pad_and_offset(x) }
|
|
419
|
+
@attributes[i.to_s] = arr
|
|
420
|
+
# puts 'after: ' + @attributes[i.to_s].inspect
|
|
421
|
+
else
|
|
422
|
+
# puts 'was nil'
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
def pre_save(*params)
|
|
429
|
+
if respond_to?('validate')
|
|
430
|
+
validate
|
|
431
|
+
# puts 'AFTER VALIDATIONS, ERRORS=' + errors.inspect
|
|
432
|
+
if (!@errors.nil? && @errors.length > 0 )
|
|
433
|
+
# puts 'THERE ARE ERRORS, returning false'
|
|
434
|
+
return false
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
is_create = self[:id].nil?
|
|
439
|
+
ok = respond_to?('before_save') ? before_save : true
|
|
440
|
+
if ok
|
|
441
|
+
if is_create && respond_to?('before_create')
|
|
442
|
+
ok = before_create
|
|
443
|
+
elsif !is_create && respond_to?('before_update')
|
|
444
|
+
ok = before_update
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
if ok
|
|
448
|
+
ok = run_before_save && is_create ? run_before_create : run_before_update
|
|
449
|
+
end
|
|
450
|
+
if ok
|
|
451
|
+
# puts 'ABOUT TO SAVE: ' + self.inspect
|
|
452
|
+
# First we gotta pad and offset
|
|
453
|
+
pad_and_offset_ints_to_sdb()
|
|
454
|
+
convert_dates_to_sdb()
|
|
455
|
+
end
|
|
456
|
+
ok
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def save_attributes(*params)
|
|
460
|
+
ret = super(*params)
|
|
461
|
+
if ret
|
|
462
|
+
self.class.cache_results(self)
|
|
463
|
+
end
|
|
464
|
+
ret
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
def get_atts_to_delete
|
|
468
|
+
to_delete = []
|
|
469
|
+
@attributes.each do |key, value|
|
|
470
|
+
# puts 'value=' + value.inspect
|
|
471
|
+
if value.nil? || (value.is_a?(Array) && value.size == 0)
|
|
472
|
+
to_delete << key
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
return to_delete
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
# Run pre_save on each object, then runs batch_put_attributes
|
|
479
|
+
# Returns
|
|
480
|
+
def self.batch_save(objects)
|
|
481
|
+
results = []
|
|
482
|
+
to_save = []
|
|
483
|
+
if objects && objects.size > 0
|
|
484
|
+
objects.each do |o|
|
|
485
|
+
ok = o.pre_save
|
|
486
|
+
raise "Pre save failed on object [" + o.inspect + "]" if !ok
|
|
487
|
+
results << ok
|
|
488
|
+
next if !ok
|
|
489
|
+
o.pre_save2
|
|
490
|
+
to_save << RightAws::SdbInterface::Item.new(o.id, o.attributes, true)
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
connection.batch_put_attributes(domain, to_save)
|
|
494
|
+
results
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
#
|
|
498
|
+
# Usage: ClassName.delete id
|
|
499
|
+
# todo: move to RightAWS
|
|
500
|
+
#
|
|
501
|
+
def self.delete(id)
|
|
502
|
+
connection.delete_attributes(domain, id)
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def delete_niled(to_delete)
|
|
506
|
+
if to_delete.size > 0
|
|
507
|
+
# puts 'Deleting attributes=' + to_delete.inspect
|
|
508
|
+
delete_attributes to_delete
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def un_offset_if_int(arg, x)
|
|
513
|
+
if !@@ints.nil?
|
|
514
|
+
for i in @@ints
|
|
515
|
+
# puts 'unpadding: ' + i.to_s
|
|
516
|
+
# unpad and unoffset
|
|
517
|
+
if i == arg
|
|
518
|
+
# puts 'unoffsetting ' + x.to_s
|
|
519
|
+
x = un_offset_int(x)
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
if !@@dates.nil?
|
|
524
|
+
for d in @@dates
|
|
525
|
+
# puts 'converting created: ' + self['created'].inspect
|
|
526
|
+
if d == arg
|
|
527
|
+
x = to_date(x)
|
|
528
|
+
end
|
|
529
|
+
# if !self[d].nil?
|
|
530
|
+
# self[d].collect!{ |d2|
|
|
531
|
+
# if d2.is_a?(String)
|
|
532
|
+
# DateTime.parse(d2)
|
|
533
|
+
# else
|
|
534
|
+
# d2
|
|
535
|
+
# end
|
|
536
|
+
# }
|
|
537
|
+
# end
|
|
538
|
+
# puts 'after=' + self['created'].inspect
|
|
539
|
+
end
|
|
540
|
+
end
|
|
541
|
+
if !@@booleans.nil?
|
|
542
|
+
for b in @@booleans
|
|
543
|
+
# puts 'converting created: ' + self['created'].inspect
|
|
544
|
+
if b == arg
|
|
545
|
+
x = to_bool(x)
|
|
546
|
+
end
|
|
547
|
+
# if !self[d].nil?
|
|
548
|
+
# self[d].collect!{ |d2|
|
|
549
|
+
# if d2.is_a?(String)
|
|
550
|
+
# DateTime.parse(d2)
|
|
551
|
+
# else
|
|
552
|
+
# d2
|
|
553
|
+
# end
|
|
554
|
+
# }
|
|
555
|
+
# end
|
|
556
|
+
# puts 'after=' + self['created'].inspect
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
x
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
def to_date(x)
|
|
564
|
+
if x.is_a?(String)
|
|
565
|
+
DateTime.parse(x)
|
|
566
|
+
else
|
|
567
|
+
x
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
def to_bool(x)
|
|
573
|
+
if x.is_a?(String)
|
|
574
|
+
x == "true"
|
|
575
|
+
else
|
|
576
|
+
x
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
def un_offset_int(x)
|
|
582
|
+
if x.is_a?(String)
|
|
583
|
+
x2 = x.to_i
|
|
584
|
+
# puts 'to_i=' + x2.to_s
|
|
585
|
+
x2 -= @@offset
|
|
586
|
+
# puts 'after subtracting offset='+ x2.to_s
|
|
587
|
+
x2
|
|
588
|
+
else
|
|
589
|
+
x
|
|
590
|
+
end
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
def unpad(i, attributes)
|
|
594
|
+
if !attributes[i].nil?
|
|
595
|
+
# puts 'before=' + self[i].inspect
|
|
596
|
+
attributes[i].collect!{ |x|
|
|
597
|
+
un_offset_int(x)
|
|
598
|
+
|
|
599
|
+
}
|
|
600
|
+
# for x in self[i]
|
|
601
|
+
# x = self[i][0].to_i
|
|
602
|
+
# x -= @@offset
|
|
603
|
+
# self[i] = x
|
|
604
|
+
# end
|
|
605
|
+
end
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
def unpad_self
|
|
609
|
+
if !@@ints.nil?
|
|
610
|
+
for i in @@ints
|
|
611
|
+
# puts 'unpadding: ' + i.to_s
|
|
612
|
+
# unpad and unoffset
|
|
613
|
+
|
|
614
|
+
unpad(i, @attributes)
|
|
615
|
+
end
|
|
616
|
+
end
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
def reload
|
|
620
|
+
super()
|
|
621
|
+
# puts 'decoding...'
|
|
622
|
+
|
|
623
|
+
=begin
|
|
624
|
+
This is done on getters now
|
|
625
|
+
if !@@dates.nil?
|
|
626
|
+
for d in @@dates
|
|
627
|
+
# puts 'converting created: ' + self['created'].inspect
|
|
628
|
+
if !self[d].nil?
|
|
629
|
+
self[d].collect!{ |d2|
|
|
630
|
+
if d2.is_a?(String)
|
|
631
|
+
DateTime.parse(d2)
|
|
632
|
+
else
|
|
633
|
+
d2
|
|
634
|
+
end
|
|
635
|
+
}
|
|
636
|
+
end
|
|
637
|
+
# puts 'after=' + self['created'].inspect
|
|
638
|
+
end
|
|
639
|
+
end
|
|
640
|
+
=end
|
|
641
|
+
|
|
642
|
+
# unpad_self
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
def update_attributes(*params)
|
|
646
|
+
return save_attributes(*params)
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
def destroy(*params)
|
|
650
|
+
if super(*params)
|
|
651
|
+
if run_after_destroy
|
|
652
|
+
return true
|
|
653
|
+
else
|
|
654
|
+
return false
|
|
655
|
+
end
|
|
656
|
+
else
|
|
657
|
+
return false
|
|
658
|
+
end
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
def self.quote_regexp(a, re)
|
|
662
|
+
a =~ re
|
|
663
|
+
#was there a match?
|
|
664
|
+
if $&
|
|
665
|
+
before=$`
|
|
666
|
+
middle=$&
|
|
667
|
+
after=$'
|
|
668
|
+
|
|
669
|
+
before =~ /'$/ #is there already a quote immediately before the match?
|
|
670
|
+
unless $&
|
|
671
|
+
return "#{before}'#{middle}'#{quote_regexp(after, re)}" #if not, put quotes around the match
|
|
672
|
+
else
|
|
673
|
+
return "#{before}#{middle}#{quote_regexp(after, re)}" #if so, assume it is quoted already and move on
|
|
674
|
+
end
|
|
675
|
+
else
|
|
676
|
+
#no match, just return the string
|
|
677
|
+
return a
|
|
678
|
+
end
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
def self.find(*params)
|
|
682
|
+
reload=true
|
|
683
|
+
first=false
|
|
684
|
+
all=false
|
|
685
|
+
select=false
|
|
686
|
+
select_attributes=[]
|
|
687
|
+
|
|
688
|
+
if params.size > 0
|
|
689
|
+
all = params[0] == :all
|
|
690
|
+
first = params[0] == :first
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
# Pad and Offset number attributes
|
|
695
|
+
options = params[1]
|
|
696
|
+
puts 'options=' + options.inspect
|
|
697
|
+
convert_condition_params(options)
|
|
698
|
+
puts 'after collect=' + options.inspect
|
|
699
|
+
|
|
700
|
+
results = all ? [] : nil
|
|
701
|
+
begin
|
|
702
|
+
results=super(*params)
|
|
703
|
+
cache_results(results)
|
|
704
|
+
rescue RightAws::AwsError, RightAws::ActiveSdb::ActiveSdbError
|
|
705
|
+
puts "RESCUED: " + $!
|
|
706
|
+
if ($!.message().index("NoSuchDomain") != nil)
|
|
707
|
+
# this is ok
|
|
708
|
+
elsif ($!.message() =~ @@regex_no_id)
|
|
709
|
+
results = nil
|
|
710
|
+
else
|
|
711
|
+
raise $!
|
|
712
|
+
end
|
|
713
|
+
end
|
|
714
|
+
return results
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
@@regex_no_id = /.*Couldn't find.*with ID.*/
|
|
718
|
+
def self.select(*params)
|
|
719
|
+
first=false
|
|
720
|
+
all=false
|
|
721
|
+
select=false
|
|
722
|
+
select_attributes=[]
|
|
723
|
+
|
|
724
|
+
if params.size > 0
|
|
725
|
+
all = params[0] == :all
|
|
726
|
+
first = params[0] == :first
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
options = params[1]
|
|
730
|
+
convert_condition_params(options)
|
|
731
|
+
|
|
732
|
+
results = all ? [] : nil
|
|
733
|
+
begin
|
|
734
|
+
results=super(*params)
|
|
735
|
+
cache_results(results)
|
|
736
|
+
rescue RightAws::AwsError, RightAws::ActiveSdb::ActiveSdbError
|
|
737
|
+
if ($!.message().index("NoSuchDomain") != nil)
|
|
738
|
+
# this is ok
|
|
739
|
+
elsif ($!.message() =~ @@regex_no_id)
|
|
740
|
+
results = nil
|
|
741
|
+
else
|
|
742
|
+
raise $!
|
|
743
|
+
end
|
|
744
|
+
end
|
|
745
|
+
return results
|
|
746
|
+
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
def self.convert_condition_params(options)
|
|
750
|
+
if !options.nil? && options.size > 0
|
|
751
|
+
conditions = options[:conditions]
|
|
752
|
+
if !conditions.nil? && conditions.size > 1
|
|
753
|
+
# all after first are values
|
|
754
|
+
conditions.collect! { |x|
|
|
755
|
+
self.pad_and_offset(x)
|
|
756
|
+
}
|
|
757
|
+
end
|
|
758
|
+
end
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
def self.cache_results(results)
|
|
762
|
+
if !@@cache_store.nil? && !results.nil?
|
|
763
|
+
if results.is_a?(Array)
|
|
764
|
+
# todo: cache each result
|
|
765
|
+
else
|
|
766
|
+
class_name = results.class.name
|
|
767
|
+
id = results.id
|
|
768
|
+
cache_key = self.cache_key(class_name, id)
|
|
769
|
+
# puts 'caching result at ' + cache_key + ': ' + results.inspect
|
|
770
|
+
@@cache_store.write(cache_key, results, :expires_in =>10*60)
|
|
771
|
+
end
|
|
772
|
+
end
|
|
773
|
+
end
|
|
774
|
+
|
|
775
|
+
def self.cache_key(class_name, id)
|
|
776
|
+
return class_name + "/" + id.to_s
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
@@debug=""
|
|
782
|
+
def self.debug
|
|
783
|
+
@@debug
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
def self.sanitize_sql(*params)
|
|
787
|
+
return ActiveRecord::Base.sanitize_sql(*params)
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
def self.table_name
|
|
791
|
+
return @@domain_prefix + self.class.name.tableize
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
class SimpleRecord_errors
|
|
797
|
+
def initialize(*params)
|
|
798
|
+
super(*params)
|
|
799
|
+
@errors=[]
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
def add_to_base(value)
|
|
803
|
+
@errors+=[value]
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
def add(attribute, value)
|
|
807
|
+
@errors+=["#{attribute.to_s} #{value}"]
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
def count
|
|
811
|
+
return length
|
|
812
|
+
end
|
|
813
|
+
|
|
814
|
+
def length
|
|
815
|
+
return @errors.length
|
|
816
|
+
end
|
|
817
|
+
|
|
818
|
+
def size
|
|
819
|
+
return length
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
def full_messages
|
|
823
|
+
return @errors
|
|
824
|
+
end
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
class Activerecordtosdb_subrecord_array
|
|
828
|
+
def initialize(subname, referencename, referencevalue)
|
|
829
|
+
@subname=subname.classify
|
|
830
|
+
@referencename=referencename.tableize.singularize + "_id"
|
|
831
|
+
@referencevalue=referencevalue
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
# Performance optimization if you know the array should be empty
|
|
835
|
+
|
|
836
|
+
def init_empty
|
|
837
|
+
@records = []
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
def load
|
|
841
|
+
if @records.nil?
|
|
842
|
+
@records = find_all
|
|
843
|
+
end
|
|
844
|
+
return @records
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
def [](key)
|
|
848
|
+
return load[key]
|
|
849
|
+
end
|
|
850
|
+
|
|
851
|
+
def <<(ob)
|
|
852
|
+
return load << ob
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
def each(*params, &block)
|
|
856
|
+
return load.each(*params){|record| block.call(record)}
|
|
857
|
+
end
|
|
858
|
+
|
|
859
|
+
def find_all(*params)
|
|
860
|
+
find(:all, *params)
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
def build(*params)
|
|
864
|
+
params[0][@referencename]=@referencevalue
|
|
865
|
+
eval(@subname).new(*params)
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
def create(*params)
|
|
869
|
+
params[0][@referencename]=@referencevalue
|
|
870
|
+
record = eval(@subname).new(*params)
|
|
871
|
+
record.save
|
|
872
|
+
end
|
|
873
|
+
|
|
874
|
+
def find(*params)
|
|
875
|
+
query=[:first, {}]
|
|
876
|
+
#{:conditions=>"id=>1"}
|
|
877
|
+
if params[0]
|
|
878
|
+
if params[0]==:all
|
|
879
|
+
query[0]=:all
|
|
880
|
+
end
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
if params[1]
|
|
884
|
+
query[1]=params[1]
|
|
885
|
+
if query[1][:conditions]
|
|
886
|
+
query[1][:conditions]=SimpleRecord::Base.sanitize_sql(query[1][:conditions])+" AND "+ SimpleRecord::Base.sanitize_sql(["#{@referencename} = ?", @referencevalue])
|
|
887
|
+
#query[1][:conditions]=Activerecordtosdb.sanitize_sql(query[1][:conditions])+" AND id='#{@id}'"
|
|
888
|
+
else
|
|
889
|
+
query[1][:conditions]=["#{@referencename} = ?", @referencevalue]
|
|
890
|
+
#query[1][:conditions]="id='#{@id}'"
|
|
891
|
+
end
|
|
892
|
+
else
|
|
893
|
+
query[1][:conditions]=["#{@referencename} = ?", @referencevalue]
|
|
894
|
+
#query[1][:conditions]="id='#{@id}'"
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
return eval(@subname).find(*query)
|
|
898
|
+
end
|
|
899
|
+
|
|
900
|
+
end
|
|
901
|
+
end
|
data/test/my_child_model.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
|
|
2
|
-
|
|
3
|
-
class MyChildModel < SimpleRecord::Base
|
|
4
|
-
belongs_to :my_model
|
|
5
|
-
has_attributes :name
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
|
|
2
|
+
|
|
3
|
+
class MyChildModel < SimpleRecord::Base
|
|
4
|
+
belongs_to :my_model
|
|
5
|
+
has_attributes :name
|
|
6
6
|
end
|
data/test/my_model.rb
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
|
|
2
|
-
|
|
3
|
-
class MyModel < SimpleRecord::Base
|
|
4
|
-
|
|
5
|
-
has_attributes :created, :updated, :name, :age, :cool, :birthday
|
|
6
|
-
are_ints :age
|
|
7
|
-
are_booleans :cool
|
|
8
|
-
are_dates :created, :updated, :birthday
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
|
|
2
|
+
|
|
3
|
+
class MyModel < SimpleRecord::Base
|
|
4
|
+
|
|
5
|
+
has_attributes :created, :updated, :name, :age, :cool, :birthday
|
|
6
|
+
are_ints :age
|
|
7
|
+
are_booleans :cool
|
|
8
|
+
are_dates :created, :updated, :birthday
|
|
9
|
+
|
|
10
|
+
|
|
11
11
|
end
|
data/test/temp_test.rb
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
# rubymine won't run 1.9 tests
|
|
2
|
-
|
|
3
|
-
require 'minitest/unit'
|
|
4
|
-
require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
|
|
5
|
-
require "yaml"
|
|
6
|
-
require 'right_aws'
|
|
7
|
-
require 'my_model'
|
|
8
|
-
require 'my_child_model'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def setup
|
|
12
|
-
@config = YAML::load(File.read('test-config.yml'))
|
|
13
|
-
puts 'akey=' + @config['amazon']['access_key']
|
|
14
|
-
puts 'skey=' + @config['amazon']['secret_key']
|
|
15
|
-
RightAws::ActiveSdb.establish_connection(@config['amazon']['access_key'], @config['amazon']['secret_key'], :port=>80, :protocol=>"http")
|
|
16
|
-
SimpleRecord::Base.set_domain_prefix("simplerecord_tests_")
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def teardown
|
|
20
|
-
RightAws::ActiveSdb.close_connection()
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def test_dates
|
|
24
|
-
mm = MyModel.new
|
|
25
|
-
mm.name = "Travis"
|
|
26
|
-
mm.age = 32
|
|
27
|
-
mm.cool = true
|
|
28
|
-
mm.created = DateTime.now - 10
|
|
29
|
-
mm.updated = DateTime.now
|
|
30
|
-
mm.birthday = Time.now - (3600 * 24 * 365 * 10)
|
|
31
|
-
puts 'before save=' + mm.inspect
|
|
32
|
-
mm.save
|
|
33
|
-
puts 'after save=' + mm.inspect
|
|
34
|
-
|
|
35
|
-
mms = MyModel.find(:all, :conditions => ["created > ?", DateTime.now - 1])
|
|
36
|
-
puts 'mms=' + mms.inspect
|
|
37
|
-
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def test_date_comparisons
|
|
41
|
-
|
|
42
|
-
t = SimpleRecord::Base.pad_and_offset(Time.now)
|
|
43
|
-
puts t
|
|
44
|
-
dt = SimpleRecord::Base.pad_and_offset(DateTime.now)
|
|
45
|
-
puts dt
|
|
46
|
-
dt_tomorrow = SimpleRecord::Base.pad_and_offset(DateTime.now + 1)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
puts 'compare=' + (t <=> dt).to_s
|
|
50
|
-
puts 'compare=' + (t <=> dt_tomorrow).to_s
|
|
51
|
-
|
|
52
|
-
dts = DateTime.parse(dt_tomorrow)
|
|
53
|
-
puts dts.to_s
|
|
54
|
-
ts = Time.parse(dt)
|
|
55
|
-
puts ts.to_s
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
setup
|
|
59
|
-
|
|
60
|
-
#test_dates
|
|
61
|
-
test_date_comparisons
|
|
62
|
-
|
|
63
|
-
teardown
|
|
1
|
+
# rubymine won't run 1.9 tests
|
|
2
|
+
|
|
3
|
+
require 'minitest/unit'
|
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
|
|
5
|
+
require "yaml"
|
|
6
|
+
require 'right_aws'
|
|
7
|
+
require 'my_model'
|
|
8
|
+
require 'my_child_model'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def setup
|
|
12
|
+
@config = YAML::load(File.read('test-config.yml'))
|
|
13
|
+
puts 'akey=' + @config['amazon']['access_key']
|
|
14
|
+
puts 'skey=' + @config['amazon']['secret_key']
|
|
15
|
+
RightAws::ActiveSdb.establish_connection(@config['amazon']['access_key'], @config['amazon']['secret_key'], :port=>80, :protocol=>"http")
|
|
16
|
+
SimpleRecord::Base.set_domain_prefix("simplerecord_tests_")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def teardown
|
|
20
|
+
RightAws::ActiveSdb.close_connection()
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_dates
|
|
24
|
+
mm = MyModel.new
|
|
25
|
+
mm.name = "Travis"
|
|
26
|
+
mm.age = 32
|
|
27
|
+
mm.cool = true
|
|
28
|
+
mm.created = DateTime.now - 10
|
|
29
|
+
mm.updated = DateTime.now
|
|
30
|
+
mm.birthday = Time.now - (3600 * 24 * 365 * 10)
|
|
31
|
+
puts 'before save=' + mm.inspect
|
|
32
|
+
mm.save
|
|
33
|
+
puts 'after save=' + mm.inspect
|
|
34
|
+
|
|
35
|
+
mms = MyModel.find(:all, :conditions => ["created > ?", DateTime.now - 1])
|
|
36
|
+
puts 'mms=' + mms.inspect
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_date_comparisons
|
|
41
|
+
|
|
42
|
+
t = SimpleRecord::Base.pad_and_offset(Time.now)
|
|
43
|
+
puts t
|
|
44
|
+
dt = SimpleRecord::Base.pad_and_offset(DateTime.now)
|
|
45
|
+
puts dt
|
|
46
|
+
dt_tomorrow = SimpleRecord::Base.pad_and_offset(DateTime.now + 1)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
puts 'compare=' + (t <=> dt).to_s
|
|
50
|
+
puts 'compare=' + (t <=> dt_tomorrow).to_s
|
|
51
|
+
|
|
52
|
+
dts = DateTime.parse(dt_tomorrow)
|
|
53
|
+
puts dts.to_s
|
|
54
|
+
ts = Time.parse(dt)
|
|
55
|
+
puts ts.to_s
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
setup
|
|
59
|
+
|
|
60
|
+
#test_dates
|
|
61
|
+
test_date_comparisons
|
|
62
|
+
|
|
63
|
+
teardown
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appoxy-simple_record
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Travis Reeder
|
|
@@ -10,7 +10,7 @@ autorequire:
|
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
12
|
|
|
13
|
-
date: 2009-06-
|
|
13
|
+
date: 2009-06-16 00:00:00 -07:00
|
|
14
14
|
default_executable: simple_record
|
|
15
15
|
dependencies: []
|
|
16
16
|
|
|
@@ -21,9 +21,10 @@ executables:
|
|
|
21
21
|
extensions: []
|
|
22
22
|
|
|
23
23
|
extra_rdoc_files:
|
|
24
|
-
- README.
|
|
24
|
+
- README.markdown
|
|
25
25
|
files:
|
|
26
|
-
-
|
|
26
|
+
- lib/simple_record.rb
|
|
27
|
+
- README.markdown
|
|
27
28
|
has_rdoc: true
|
|
28
29
|
homepage: http://github.com/appoxy/simple_record/
|
|
29
30
|
post_install_message:
|