simple_record 2.1.10 → 2.1.11
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.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
|