simple_record 2.1.10 → 2.1.11
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/simple_record.rb +95 -95
- data/lib/simple_record/attributes.rb +48 -41
- data/lib/simple_record/validations.rb +31 -2
- metadata +2 -5
data/lib/simple_record.rb
CHANGED
@@ -62,18 +62,18 @@ module SimpleRecord
|
|
62
62
|
class << self;
|
63
63
|
attr_accessor :aws_access_key, :aws_secret_key
|
64
64
|
|
65
|
-
|
65
|
+
# Deprecated
|
66
66
|
def enable_logging
|
67
67
|
@@logging = true
|
68
68
|
@@logger.level = Logger::DEBUG
|
69
69
|
end
|
70
70
|
|
71
|
-
|
71
|
+
# Deprecated
|
72
72
|
def disable_logging
|
73
73
|
@@logging = false
|
74
74
|
end
|
75
75
|
|
76
|
-
|
76
|
+
# Deprecated
|
77
77
|
def logging?
|
78
78
|
@@logging
|
79
79
|
end
|
@@ -82,9 +82,9 @@ module SimpleRecord
|
|
82
82
|
@@logger
|
83
83
|
end
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
# This can be used to log queries and what not to a file.
|
86
|
+
# Params:
|
87
|
+
# :select=>{:filename=>"file_to_write_to", :format=>"csv"}
|
88
88
|
def log_usage(types={})
|
89
89
|
@usage_logging_options = {} unless @usage_logging_options
|
90
90
|
return if types.nil?
|
@@ -109,26 +109,26 @@ module SimpleRecord
|
|
109
109
|
end
|
110
110
|
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
112
|
+
# Create a new handle to an Sdb account. All handles share the same per process or per thread
|
113
|
+
# HTTP connection to Amazon Sdb. Each handle is for a specific account.
|
114
|
+
# The +params+ are passed through as-is to Aws::SdbInterface.new
|
115
|
+
# Params:
|
116
|
+
# { :server => 'sdb.amazonaws.com' # Amazon service host: 'sdb.amazonaws.com'(default)
|
117
|
+
# :port => 443 # Amazon service port: 80(default) or 443
|
118
|
+
# :protocol => 'https' # Amazon service protocol: 'http'(default) or 'https'
|
119
|
+
# :signature_version => '0' # The signature version : '0' or '1'(default)
|
120
|
+
# :connection_mode => :default # options are
|
121
|
+
# :default (will use best known safe (as in won't need explicit close) option, may change in the future)
|
122
|
+
# :per_request (opens and closes a connection on every request to SDB)
|
123
|
+
# :single (one thread across entire app)
|
124
|
+
# :per_thread (one connection per thread)
|
125
|
+
# :pool (uses a connection pool with a maximum number of connections - NOT IMPLEMENTED YET)
|
126
|
+
# :logger => Logger Object # Logger instance: logs to STDOUT if omitted
|
127
127
|
def establish_connection(aws_access_key=nil, aws_secret_key=nil, options={})
|
128
128
|
@aws_access_key = aws_access_key
|
129
129
|
@aws_secret_key = aws_secret_key
|
130
130
|
@@options.merge!(options)
|
131
|
-
|
131
|
+
#puts 'SimpleRecord.establish_connection with options: ' + @@options.inspect
|
132
132
|
SimpleRecord::ActiveSdb.establish_connection(aws_access_key, aws_secret_key, @@options)
|
133
133
|
if options[:connection_mode] == :per_thread
|
134
134
|
@@auto_close_s3 = true
|
@@ -147,17 +147,17 @@ module SimpleRecord
|
|
147
147
|
|
148
148
|
end
|
149
149
|
|
150
|
-
|
151
|
-
|
152
|
-
|
150
|
+
# Call this to close the connection to SimpleDB.
|
151
|
+
# If you're using this in Rails with per_thread connection mode, you should do this in
|
152
|
+
# an after_filter for each request.
|
153
153
|
def close_connection()
|
154
154
|
SimpleRecord::ActiveSdb.close_connection
|
155
155
|
@@s3.close_connection if @@auto_close_s3
|
156
156
|
end
|
157
157
|
|
158
|
-
|
159
|
-
|
160
|
-
|
158
|
+
# If you'd like to specify the s3 connection to use for LOBs, you can pass it in here.
|
159
|
+
# We recommend that this connection matches the type of connection you're using for SimpleDB,
|
160
|
+
# at least if you're using per_thread connection mode.
|
161
161
|
def s3=(s3)
|
162
162
|
@@s3 = s3
|
163
163
|
end
|
@@ -196,7 +196,7 @@ module SimpleRecord
|
|
196
196
|
include SimpleRecord::Callbacks
|
197
197
|
end
|
198
198
|
include SimpleRecord::Validations
|
199
|
-
|
199
|
+
extend SimpleRecord::Validations::ClassMethods
|
200
200
|
|
201
201
|
include SimpleRecord::Translations
|
202
202
|
# include SimpleRecord::Attributes
|
@@ -217,7 +217,7 @@ module SimpleRecord
|
|
217
217
|
|
218
218
|
initialize_base(attrs)
|
219
219
|
|
220
|
-
|
220
|
+
# Convert attributes to sdb values
|
221
221
|
attrs.each_pair do |name, value|
|
222
222
|
set(name, value, true)
|
223
223
|
end
|
@@ -226,7 +226,7 @@ module SimpleRecord
|
|
226
226
|
def initialize_base(attrs={})
|
227
227
|
|
228
228
|
#we have to handle the virtuals.
|
229
|
-
|
229
|
+
handle_virtuals(attrs)
|
230
230
|
|
231
231
|
clear_errors
|
232
232
|
|
@@ -278,10 +278,10 @@ module SimpleRecord
|
|
278
278
|
attr_accessor :domain_prefix
|
279
279
|
end
|
280
280
|
|
281
|
-
|
281
|
+
#@domain_name_for_class = nil
|
282
282
|
|
283
283
|
@@cache_store = nil
|
284
|
-
|
284
|
+
# Set the cache to use
|
285
285
|
def self.cache_store=(cache)
|
286
286
|
@@cache_store = cache
|
287
287
|
end
|
@@ -290,18 +290,18 @@ module SimpleRecord
|
|
290
290
|
return @@cache_store
|
291
291
|
end
|
292
292
|
|
293
|
-
|
293
|
+
# If you want a domain prefix for all your models, set it here.
|
294
294
|
def self.set_domain_prefix(prefix)
|
295
295
|
#puts 'set_domain_prefix=' + prefix
|
296
296
|
self.domain_prefix = prefix
|
297
297
|
end
|
298
298
|
|
299
|
-
|
299
|
+
# Same as set_table_name
|
300
300
|
def self.set_table_name(table_name)
|
301
301
|
set_domain_name table_name
|
302
302
|
end
|
303
303
|
|
304
|
-
|
304
|
+
# Sets the domain name for this class
|
305
305
|
def self.set_domain_name(table_name)
|
306
306
|
super
|
307
307
|
end
|
@@ -405,12 +405,12 @@ module SimpleRecord
|
|
405
405
|
set(SimpleRecord.options[:updated_col] || :updated, Time.now)
|
406
406
|
end
|
407
407
|
|
408
|
-
|
408
|
+
# an aliased method since many people use created_at/updated_at naming convention
|
409
409
|
def created_at
|
410
410
|
self.created
|
411
411
|
end
|
412
412
|
|
413
|
-
|
413
|
+
# an aliased method since many people use created_at/updated_at naming convention
|
414
414
|
def updated_at
|
415
415
|
self.updated
|
416
416
|
end
|
@@ -438,17 +438,17 @@ module SimpleRecord
|
|
438
438
|
|
439
439
|
@create_domain_called = false
|
440
440
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
441
|
+
# Options:
|
442
|
+
# - :except => Array of attributes to NOT save
|
443
|
+
# - :dirty => true - Will only store attributes that were modified. To make it save regardless and have it update the :updated value, include this and set it to false.
|
444
|
+
# - :domain => Explicitly define domain to use.
|
445
|
+
#
|
446
446
|
|
447
447
|
def save(options={})
|
448
448
|
puts 'SAVING: ' + self.inspect if SimpleRecord.logging?
|
449
|
-
|
449
|
+
# todo: Clean out undefined values in @attributes (in case someone set the attributes hash with values that they hadn't defined)
|
450
450
|
clear_errors
|
451
|
-
|
451
|
+
# todo: decide whether this should go before pre_save or after pre_save? pre_save dirties "updated" and perhaps other items due to callbacks
|
452
452
|
if options[:dirty]
|
453
453
|
# puts '@dirtyA=' + @dirty.inspect
|
454
454
|
return true if @dirty.size == 0 # Nothing to save so skip it
|
@@ -470,7 +470,7 @@ module SimpleRecord
|
|
470
470
|
is_create = new_record? # self[:id].nil?
|
471
471
|
|
472
472
|
dirty = @dirty
|
473
|
-
# puts 'dirty before=' + @dirty.inspect
|
473
|
+
# puts 'dirty before=' + @dirty.inspect
|
474
474
|
if options[:dirty]
|
475
475
|
# puts '@dirty=' + @dirty.inspect
|
476
476
|
return true if @dirty.size == 0 # This should probably never happen because after pre_save, created/updated dates are changed
|
@@ -500,7 +500,7 @@ module SimpleRecord
|
|
500
500
|
# end
|
501
501
|
|
502
502
|
def create_or_update(options) #:nodoc:
|
503
|
-
# puts 'create_or_update'
|
503
|
+
# puts 'create_or_update'
|
504
504
|
ret = true
|
505
505
|
_run_save_callbacks do
|
506
506
|
result = new_record? ? create(options) : update(options)
|
@@ -538,7 +538,7 @@ module SimpleRecord
|
|
538
538
|
save(options) || raise(RecordNotSaved.new(self))
|
539
539
|
end
|
540
540
|
|
541
|
-
|
541
|
+
# this is a bit wonky, save! should call this, not sure why it's here.
|
542
542
|
def save_with_validation!(options={})
|
543
543
|
save!
|
544
544
|
end
|
@@ -642,21 +642,21 @@ module SimpleRecord
|
|
642
642
|
|
643
643
|
def is_dirty?(name)
|
644
644
|
# todo: should change all the dirty stuff to symbols?
|
645
|
-
# puts '@dirty=' + @dirty.inspect
|
646
|
-
# puts 'name=' +name.to_s
|
645
|
+
# puts '@dirty=' + @dirty.inspect
|
646
|
+
# puts 'name=' +name.to_s
|
647
647
|
@dirty.include? name.to_s
|
648
648
|
end
|
649
649
|
|
650
650
|
def s3
|
651
651
|
|
652
652
|
return SimpleRecord.s3 if SimpleRecord.s3
|
653
|
-
|
654
|
-
|
653
|
+
# todo: should optimize this somehow, like use the same connection_mode as used in SR
|
654
|
+
# or keep open while looping in ResultsArray.
|
655
655
|
Aws::S3.new(SimpleRecord.aws_access_key, SimpleRecord.aws_secret_key)
|
656
656
|
end
|
657
657
|
|
658
|
-
|
659
|
-
|
658
|
+
# options:
|
659
|
+
# :s3_bucket => :old/:new/"#{any_bucket_name}". :new if want to use new bucket. Defaults to :old for backwards compatability.
|
660
660
|
def s3_bucket(create=false, options={})
|
661
661
|
s3.bucket(s3_bucket_name(options[:s3_bucket]), create)
|
662
662
|
end
|
@@ -725,7 +725,7 @@ module SimpleRecord
|
|
725
725
|
return false unless ok
|
726
726
|
end
|
727
727
|
|
728
|
-
|
728
|
+
# Now for callbacks
|
729
729
|
unless @@active_model
|
730
730
|
ok = respond_to?(:before_save) ? before_save : true
|
731
731
|
if ok
|
@@ -766,8 +766,8 @@ module SimpleRecord
|
|
766
766
|
return to_delete
|
767
767
|
end
|
768
768
|
|
769
|
-
|
770
|
-
|
769
|
+
# Run pre_save on each object, then runs batch_put_attributes
|
770
|
+
# Returns
|
771
771
|
def self.batch_save(objects, options={})
|
772
772
|
options[:create_domain] = true if options[:create_domain].nil?
|
773
773
|
results = []
|
@@ -793,7 +793,7 @@ module SimpleRecord
|
|
793
793
|
results
|
794
794
|
end
|
795
795
|
|
796
|
-
|
796
|
+
# Pass in an array of objects
|
797
797
|
def self.batch_delete(objects, options={})
|
798
798
|
if objects
|
799
799
|
# 25 item limit, we should maybe handle this limit in here.
|
@@ -801,15 +801,15 @@ module SimpleRecord
|
|
801
801
|
end
|
802
802
|
end
|
803
803
|
|
804
|
-
|
805
|
-
|
806
|
-
|
804
|
+
#
|
805
|
+
# Usage: ClassName.delete id
|
806
|
+
#
|
807
807
|
def self.delete(id)
|
808
808
|
connection.delete_attributes(domain, id)
|
809
809
|
@deleted = true
|
810
810
|
end
|
811
811
|
|
812
|
-
|
812
|
+
# Pass in the same OPTIONS you'd pass into a find(:all, OPTIONS)
|
813
813
|
def self.delete_all(options={})
|
814
814
|
# could make this quicker by just getting item_names and deleting attributes rather than creating objects
|
815
815
|
obs = self.find(:all, options)
|
@@ -821,7 +821,7 @@ module SimpleRecord
|
|
821
821
|
return i
|
822
822
|
end
|
823
823
|
|
824
|
-
|
824
|
+
# Pass in the same OPTIONS you'd pass into a find(:all, OPTIONS)
|
825
825
|
def self.destroy_all(options={})
|
826
826
|
obs = self.find(:all, options)
|
827
827
|
i = 0
|
@@ -838,7 +838,7 @@ module SimpleRecord
|
|
838
838
|
end
|
839
839
|
super(options)
|
840
840
|
|
841
|
-
|
841
|
+
# delete lobs now too
|
842
842
|
delete_lobs
|
843
843
|
end
|
844
844
|
|
@@ -885,7 +885,7 @@ module SimpleRecord
|
|
885
885
|
|
886
886
|
def self.quote_regexp(a, re)
|
887
887
|
a =~ re
|
888
|
-
|
888
|
+
#was there a match?
|
889
889
|
if $&
|
890
890
|
before=$`
|
891
891
|
middle=$&
|
@@ -905,19 +905,19 @@ module SimpleRecord
|
|
905
905
|
|
906
906
|
@@regex_no_id = /.*Couldn't find.*with ID.*/
|
907
907
|
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
908
|
+
#
|
909
|
+
# Usage:
|
910
|
+
# Find by ID:
|
911
|
+
# MyModel.find(ID)
|
912
|
+
#
|
913
|
+
# Query example:
|
914
|
+
# MyModel.find(:all, :conditions=>["name = ?", name], :order=>"created desc", :limit=>10)
|
915
|
+
#
|
916
|
+
# Extra options:
|
917
|
+
# :per_token => the number of results to return per next_token, max is 2500.
|
918
|
+
# :consistent_read => true/false -- as per http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3572
|
919
|
+
# :retries => maximum number of times to retry this query on an error response.
|
920
|
+
# :shard => shard name or array of shard names to use on this query.
|
921
921
|
def self.find(*params)
|
922
922
|
#puts 'params=' + params.inspect
|
923
923
|
|
@@ -941,12 +941,12 @@ module SimpleRecord
|
|
941
941
|
return find_sharded(*params)
|
942
942
|
end
|
943
943
|
|
944
|
-
|
944
|
+
# Pad and Offset number attributes
|
945
945
|
params_dup = params.dup
|
946
946
|
if params.size > 1
|
947
947
|
options = params[1]
|
948
|
-
|
949
|
-
|
948
|
+
#puts 'options=' + options.inspect
|
949
|
+
#puts 'after collect=' + options.inspect
|
950
950
|
convert_condition_params(options)
|
951
951
|
per_token = options[:per_token]
|
952
952
|
consistent_read = options[:consistent_read]
|
@@ -957,20 +957,20 @@ module SimpleRecord
|
|
957
957
|
params_dup[1] = op_dup
|
958
958
|
end
|
959
959
|
end
|
960
|
-
# puts 'params2=' + params.inspect
|
960
|
+
# puts 'params2=' + params.inspect
|
961
961
|
|
962
962
|
ret = q_type == :all ? [] : nil
|
963
963
|
begin
|
964
964
|
results=find_with_metadata(*params_dup)
|
965
965
|
#puts "RESULT=" + results.inspect
|
966
966
|
write_usage(:select, domain, q_type, options, results)
|
967
|
-
|
967
|
+
#puts 'params3=' + params.inspect
|
968
968
|
SimpleRecord.stats.selects += 1
|
969
969
|
if q_type == :count
|
970
970
|
ret = results[:count]
|
971
971
|
elsif q_type == :first
|
972
972
|
ret = results[:items].first
|
973
|
-
|
973
|
+
# todo: we should store request_id and box_usage with the object maybe?
|
974
974
|
cache_results(ret)
|
975
975
|
elsif results[:single_only]
|
976
976
|
ret = results[:single]
|
@@ -987,14 +987,14 @@ module SimpleRecord
|
|
987
987
|
#puts "RESCUED: " + ex.message
|
988
988
|
if (ex.message().index("NoSuchDomain") != nil)
|
989
989
|
# this is ok
|
990
|
-
# elsif (ex.message() =~ @@regex_no_id) This is RecordNotFound now
|
991
|
-
# ret = nil
|
990
|
+
# elsif (ex.message() =~ @@regex_no_id) This is RecordNotFound now
|
991
|
+
# ret = nil
|
992
992
|
else
|
993
993
|
#puts 're-raising'
|
994
994
|
raise ex
|
995
995
|
end
|
996
996
|
end
|
997
|
-
# puts 'single2=' + ret.inspect
|
997
|
+
# puts 'single2=' + ret.inspect
|
998
998
|
return ret
|
999
999
|
end
|
1000
1000
|
|
@@ -1014,8 +1014,8 @@ module SimpleRecord
|
|
1014
1014
|
find(:count, *args)
|
1015
1015
|
end
|
1016
1016
|
|
1017
|
-
|
1018
|
-
|
1017
|
+
# This gets less and less efficient the higher the page since SimpleDB has no way
|
1018
|
+
# to start at a specific row. So it will iterate from the first record and pull out the specific pages.
|
1019
1019
|
def self.paginate(options={})
|
1020
1020
|
# options = args.pop
|
1021
1021
|
# puts 'paginate options=' + options.inspect if SimpleRecord.logging?
|
@@ -1053,14 +1053,14 @@ module SimpleRecord
|
|
1053
1053
|
class_name = item.class.name
|
1054
1054
|
id = item.id
|
1055
1055
|
cache_key = self.cache_key(class_name, id)
|
1056
|
-
|
1056
|
+
#puts 'caching result at ' + cache_key + ': ' + results.inspect
|
1057
1057
|
cache_store.write(cache_key, item, :expires_in =>30)
|
1058
1058
|
end
|
1059
1059
|
else
|
1060
1060
|
class_name = results.class.name
|
1061
1061
|
id = results.id
|
1062
1062
|
cache_key = self.cache_key(class_name, id)
|
1063
|
-
|
1063
|
+
#puts 'caching result at ' + cache_key + ': ' + results.inspect
|
1064
1064
|
cache_store.write(cache_key, results, :expires_in =>30)
|
1065
1065
|
end
|
1066
1066
|
end
|
@@ -1094,7 +1094,7 @@ module SimpleRecord
|
|
1094
1094
|
|
1095
1095
|
def changes
|
1096
1096
|
ret = {}
|
1097
|
-
|
1097
|
+
#puts 'in CHANGES=' + @dirty.inspect
|
1098
1098
|
@dirty.each_pair { |key, value| ret[key] = [value, get_attribute(key)] }
|
1099
1099
|
return ret
|
1100
1100
|
end
|
@@ -1119,7 +1119,7 @@ module SimpleRecord
|
|
1119
1119
|
@referencevalue=referencevalue
|
1120
1120
|
end
|
1121
1121
|
|
1122
|
-
|
1122
|
+
# Performance optimization if you know the array should be empty
|
1123
1123
|
|
1124
1124
|
def init_empty
|
1125
1125
|
@records = []
|
@@ -1177,7 +1177,7 @@ module SimpleRecord
|
|
1177
1177
|
|
1178
1178
|
def find(*params)
|
1179
1179
|
query=[:first, {}]
|
1180
|
-
|
1180
|
+
#{:conditions=>"id=>1"}
|
1181
1181
|
if params[0]
|
1182
1182
|
if params[0]==:all
|
1183
1183
|
query[0]=:all
|
@@ -1203,7 +1203,7 @@ module SimpleRecord
|
|
1203
1203
|
|
1204
1204
|
end
|
1205
1205
|
|
1206
|
-
|
1206
|
+
# This is simply a place holder so we don't keep doing gets to s3 or simpledb if already checked.
|
1207
1207
|
class RemoteNil
|
1208
1208
|
|
1209
1209
|
end
|
@@ -58,14 +58,14 @@ module SimpleRecord
|
|
58
58
|
attr = Attribute.new(type, arg_options)
|
59
59
|
defined_attributes[arg] = attr if defined_attributes[arg].nil?
|
60
60
|
|
61
|
-
|
61
|
+
# define reader method
|
62
62
|
arg_s = arg.to_s # to get rid of all the to_s calls
|
63
63
|
send(:define_method, arg) do
|
64
64
|
ret = get_attribute(arg)
|
65
65
|
return ret
|
66
66
|
end
|
67
67
|
|
68
|
-
|
68
|
+
# define writer method
|
69
69
|
send(:define_method, arg_s+"=") do |value|
|
70
70
|
set(arg, value)
|
71
71
|
end
|
@@ -81,13 +81,13 @@ module SimpleRecord
|
|
81
81
|
@dirty.has_key?(sdb_att_name(arg_s))
|
82
82
|
end
|
83
83
|
|
84
|
-
|
84
|
+
# define change method
|
85
85
|
send(:define_method, arg_s + "_change") do
|
86
86
|
old_val = @dirty[sdb_att_name(arg_s)]
|
87
87
|
[old_val, get_attribute(arg_s)]
|
88
88
|
end
|
89
89
|
|
90
|
-
|
90
|
+
# define was method
|
91
91
|
send(:define_method, arg_s + "_was") do
|
92
92
|
old_val = @dirty[sdb_att_name(arg_s)]
|
93
93
|
old_val
|
@@ -149,21 +149,26 @@ module SimpleRecord
|
|
149
149
|
|
150
150
|
end
|
151
151
|
|
152
|
+
def virtuals
|
153
|
+
@virtuals ||= []
|
154
|
+
@virtuals
|
155
|
+
end
|
156
|
+
|
152
157
|
def has_virtuals(*args)
|
153
|
-
|
158
|
+
virtuals.concat(args)
|
154
159
|
args.each do |arg|
|
155
160
|
#we just create the accessor functions here, the actual instance variable is created during initialize
|
156
161
|
attr_accessor(arg)
|
157
162
|
end
|
158
163
|
end
|
159
164
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
165
|
+
# One belongs_to association per call. Call multiple times if there are more than one.
|
166
|
+
#
|
167
|
+
# This method will also create an {association)_id method that will return the ID of the foreign object
|
168
|
+
# without actually materializing it.
|
169
|
+
#
|
170
|
+
# options:
|
171
|
+
# :class_name=>"User" - to change the default class to use
|
167
172
|
def belongs_to(association_id, options = {})
|
168
173
|
arg = association_id
|
169
174
|
arg_s = arg.to_s
|
@@ -171,29 +176,29 @@ module SimpleRecord
|
|
171
176
|
attribute = Attribute.new(:belongs_to, options)
|
172
177
|
defined_attributes[arg] = attribute
|
173
178
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
179
|
+
# 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
|
180
|
+
# puts "arg_id=#{arg}_id"
|
181
|
+
# puts "is defined? " + eval("(defined? #{arg}_id)").to_s
|
182
|
+
# puts 'atts=' + @attributes.inspect
|
178
183
|
|
179
|
-
|
184
|
+
# Define reader method
|
180
185
|
send(:define_method, arg) do
|
181
186
|
return get_attribute(arg)
|
182
187
|
end
|
183
188
|
|
184
189
|
|
185
|
-
|
190
|
+
# Define writer method
|
186
191
|
send(:define_method, arg.to_s + "=") do |value|
|
187
192
|
set(arg, value)
|
188
193
|
end
|
189
194
|
|
190
195
|
|
191
|
-
|
196
|
+
# Define ID reader method for reading the associated objects id without getting the entire object
|
192
197
|
send(:define_method, arg_id) do
|
193
198
|
get_attribute_sdb(arg_s)
|
194
199
|
end
|
195
200
|
|
196
|
-
|
201
|
+
# Define writer method for setting the _id directly without the associated object
|
197
202
|
send(:define_method, arg_id + "=") do |value|
|
198
203
|
# rb_att_name = arg_s # n2 = name.to_s[0, name.length-3]
|
199
204
|
set(arg_id, value)
|
@@ -237,14 +242,16 @@ module SimpleRecord
|
|
237
242
|
|
238
243
|
end
|
239
244
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
#
|
247
|
-
|
245
|
+
def handle_virtuals(attrs)
|
246
|
+
puts 'handle_virtuals'
|
247
|
+
self.class.virtuals.each do |virtual|
|
248
|
+
puts 'virtual=' + virtual.inspect
|
249
|
+
#we first copy the information for the virtual to an instance variable of the same name
|
250
|
+
send("#{virtual}=", attrs[virtual])
|
251
|
+
#eval("@#{virtual}=attrs['#{virtual}']")
|
252
|
+
#and then remove the parameter before it is passed to initialize, so that it is NOT sent to SimpleDB
|
253
|
+
attrs.delete(virtual)
|
254
|
+
#eval("attrs.delete('#{virtual}')")
|
248
255
|
end
|
249
256
|
end
|
250
257
|
|
@@ -289,17 +296,17 @@ module SimpleRecord
|
|
289
296
|
attname = name.to_s
|
290
297
|
attvalue = att_meta.init_value(value)
|
291
298
|
# attvalue = value
|
292
|
-
|
299
|
+
#puts 'converted ' + value.inspect + ' to ' + attvalue.inspect
|
293
300
|
end
|
294
301
|
end
|
295
302
|
attvalue = strip_array(attvalue)
|
296
303
|
make_dirty(name, attvalue) if dirtify
|
297
|
-
# puts "ARG=#{attname.to_s} setting to #{attvalue}"
|
304
|
+
# puts "ARG=#{attname.to_s} setting to #{attvalue}"
|
298
305
|
sdb_val = ruby_to_sdb(name, attvalue)
|
299
|
-
# puts "sdb_val=" + sdb_val.to_s
|
306
|
+
# puts "sdb_val=" + sdb_val.to_s
|
300
307
|
@attributes[attname] = sdb_val
|
301
|
-
# attvalue = wrap_if_required(name, attvalue, sdb_val)
|
302
|
-
# puts 'attvalue2=' + attvalue.to_s
|
308
|
+
# attvalue = wrap_if_required(name, attvalue, sdb_val)
|
309
|
+
# puts 'attvalue2=' + attvalue.to_s
|
303
310
|
|
304
311
|
if store_rb_val
|
305
312
|
@attributes_rb[name.to_s] = value
|
@@ -321,11 +328,11 @@ module SimpleRecord
|
|
321
328
|
return ret
|
322
329
|
end
|
323
330
|
|
324
|
-
|
325
|
-
|
331
|
+
# Since SimpleDB supports multiple attributes per value, the values are an array.
|
332
|
+
# This method will return the value unwrapped if it's the only, otherwise it will return the array.
|
326
333
|
def get_attribute(name)
|
327
334
|
# puts "get_attribute #{name}"
|
328
|
-
|
335
|
+
# Check if this arg is already converted
|
329
336
|
name_s = name.to_s
|
330
337
|
name = name.to_sym
|
331
338
|
att_meta = get_att_meta(name)
|
@@ -340,7 +347,7 @@ module SimpleRecord
|
|
340
347
|
return ret
|
341
348
|
end
|
342
349
|
end
|
343
|
-
|
350
|
+
# get it from s3
|
344
351
|
unless new_record?
|
345
352
|
if self.class.get_sr_config[:single_clob]
|
346
353
|
begin
|
@@ -362,7 +369,7 @@ module SimpleRecord
|
|
362
369
|
else
|
363
370
|
begin
|
364
371
|
ret = s3_bucket.get(s3_lob_id(name))
|
365
|
-
|
372
|
+
# puts 'got from s3 ' + ret.inspect
|
366
373
|
SimpleRecord.stats.s3_gets += 1
|
367
374
|
rescue Aws::AwsError => ex
|
368
375
|
if ex.include?(/NoSuchKey/) || ex.include?(/NoSuchBucket/)
|
@@ -386,9 +393,9 @@ module SimpleRecord
|
|
386
393
|
return ret unless ret.nil?
|
387
394
|
return nil if ret.is_a? RemoteNil
|
388
395
|
ret = get_attribute_sdb(name)
|
389
|
-
# p ret
|
396
|
+
# p ret
|
390
397
|
ret = sdb_to_ruby(name, ret)
|
391
|
-
# p ret
|
398
|
+
# p ret
|
392
399
|
@attributes_rb[name_s] = ret
|
393
400
|
return ret
|
394
401
|
end
|
@@ -404,7 +411,7 @@ module SimpleRecord
|
|
404
411
|
end
|
405
412
|
|
406
413
|
|
407
|
-
|
414
|
+
# Holds information about an attribute
|
408
415
|
class Attribute
|
409
416
|
attr_accessor :type, :options
|
410
417
|
|
@@ -17,6 +17,20 @@ module SimpleRecord
|
|
17
17
|
# end
|
18
18
|
end
|
19
19
|
|
20
|
+
module ClassMethods
|
21
|
+
|
22
|
+
def uniques
|
23
|
+
@uniques ||= {}
|
24
|
+
@uniques
|
25
|
+
end
|
26
|
+
|
27
|
+
# only supporting single attr name right now
|
28
|
+
def validates_uniqueness_of(attr)
|
29
|
+
uniques[attr] = true
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
20
34
|
def valid?
|
21
35
|
# puts 'in rails2 valid?'
|
22
36
|
errors.clear
|
@@ -26,9 +40,9 @@ module SimpleRecord
|
|
26
40
|
am_valid?
|
27
41
|
end
|
28
42
|
|
29
|
-
|
43
|
+
# run_callbacks(:validate)
|
30
44
|
validate
|
31
|
-
|
45
|
+
validate_uniques
|
32
46
|
|
33
47
|
if new_record?
|
34
48
|
# run_callbacks(:validate_on_create)
|
@@ -51,6 +65,21 @@ module SimpleRecord
|
|
51
65
|
@attributes[key.to_s]
|
52
66
|
end
|
53
67
|
|
68
|
+
def validate_uniques
|
69
|
+
puts 'uniques=' + self.class.uniques.inspect
|
70
|
+
self.class.uniques.each_pair do |k, v|
|
71
|
+
val = self.send(k)
|
72
|
+
puts 'val=' + val.inspect
|
73
|
+
if val
|
74
|
+
ret = self.class.find(:first, :conditions=>["#{k}=?", val])
|
75
|
+
puts 'ret=' + ret.inspect
|
76
|
+
if ret
|
77
|
+
errors.add(k, "must be unique.")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
54
83
|
def validate
|
55
84
|
true
|
56
85
|
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.1.
|
5
|
+
version: 2.1.11
|
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-06 00:00:00 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: aws
|
@@ -75,9 +75,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
75
|
requirements:
|
76
76
|
- - ">="
|
77
77
|
- !ruby/object:Gem::Version
|
78
|
-
hash: 2579069880692294424
|
79
|
-
segments:
|
80
|
-
- 0
|
81
78
|
version: "0"
|
82
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
80
|
none: false
|