simply_stored 0.3.9 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +38 -0
- data/README.md +45 -24
- data/lib/simply_stored/couch/association_property.rb +27 -0
- data/lib/simply_stored/couch/belongs_to.rb +5 -7
- data/lib/simply_stored/couch/finders.rb +5 -1
- data/lib/simply_stored/couch/has_and_belongs_to_many.rb +202 -0
- data/lib/simply_stored/couch/has_many.rb +6 -51
- data/lib/simply_stored/couch/has_one.rb +4 -29
- data/lib/simply_stored/couch/properties.rb +11 -0
- data/lib/simply_stored/couch.rb +38 -2
- data/lib/simply_stored/instance_methods.rb +68 -29
- data/lib/simply_stored.rb +3 -1
- data/test/{couchdb/couch_active_model_compatibility_test.rb → active_model_compatibility_test.rb} +2 -2
- data/test/{couchdb/couch_belongs_to_test.rb → belongs_to_test.rb} +13 -3
- data/test/{couchdb/couch_conflict_handling_test.rb → conflict_handling_test.rb} +3 -3
- data/test/{couchdb/couch_finder_test.rb → finder_test.rb} +8 -3
- data/test/fixtures/couch.rb +55 -0
- data/test/has_and_belongs_to_many_test.rb +639 -0
- data/test/{couchdb/couch_has_many_test.rb → has_many_test.rb} +13 -3
- data/test/{couchdb/couch_has_one_test.rb → has_one_test.rb} +13 -3
- data/test/{couchdb/couch_instance_lifecycle_test.rb → instance_lifecycle_test.rb} +3 -3
- data/test/{couchdb/couch_mass_assignment_protection_test.rb → mass_assignment_protection_test.rb} +3 -3
- data/test/{couchdb/couch_s3_test.rb → s3_test.rb} +3 -3
- data/test/{couchdb/couch_soft_deletable_test.rb → soft_deletable_test.rb} +3 -3
- data/test/test_helper.rb +1 -5
- data/test/{couchdb/couch_validations_test.rb → validations_test.rb} +3 -3
- data/test/{couchdb/custom_views_test.rb → views_test.rb} +3 -3
- metadata +36 -234
- data/lib/simply_stored/simpledb/associations.rb +0 -215
- data/lib/simply_stored/simpledb/attributes.rb +0 -173
- data/lib/simply_stored/simpledb/storag.rb +0 -85
- data/lib/simply_stored/simpledb/validations.rb +0 -88
- data/lib/simply_stored/simpledb.rb +0 -216
- data/test/fixtures/simpledb/item.rb +0 -11
- data/test/fixtures/simpledb/item_daddy.rb +0 -8
- data/test/fixtures/simpledb/log_item.rb +0 -3
- data/test/fixtures/simpledb/namespace_bar.rb +0 -5
- data/test/fixtures/simpledb/namespace_foo.rb +0 -7
- data/test/fixtures/simpledb/protected_item.rb +0 -3
- data/test/simply_stored_simpledb_test.rb +0 -1376
- data/test/vendor/dhaka-2.2.1/lib/dhaka/dot/dot.rb +0 -29
- data/test/vendor/dhaka-2.2.1/lib/dhaka/evaluator/evaluator.rb +0 -133
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/closure_hash.rb +0 -15
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar.rb +0 -240
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar_symbol.rb +0 -27
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/precedence.rb +0 -19
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/production.rb +0 -36
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/accept_actions.rb +0 -36
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/alphabet.rb +0 -21
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/compiled_lexer.rb +0 -46
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/dfa.rb +0 -121
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexeme.rb +0 -32
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer.rb +0 -70
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer_run.rb +0 -78
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_grammar.rb +0 -392
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_parser.rb +0 -2010
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_tokenizer.rb +0 -14
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/specification.rb +0 -96
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state.rb +0 -68
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state_machine.rb +0 -37
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/action.rb +0 -55
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/channel.rb +0 -58
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/compiled_parser.rb +0 -51
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/conflict.rb +0 -54
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/item.rb +0 -42
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_result.rb +0 -50
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_tree.rb +0 -66
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser.rb +0 -165
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_methods.rb +0 -11
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_run.rb +0 -39
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_state.rb +0 -74
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/token.rb +0 -22
- data/test/vendor/dhaka-2.2.1/lib/dhaka/runtime.rb +0 -51
- data/test/vendor/dhaka-2.2.1/lib/dhaka/tokenizer/tokenizer.rb +0 -190
- data/test/vendor/dhaka-2.2.1/lib/dhaka.rb +0 -62
- data/test/vendor/dhaka-2.2.1/test/all_tests.rb +0 -5
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator.rb +0 -64
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator_test.rb +0 -43
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar.rb +0 -41
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar_test.rb +0 -9
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_test_methods.rb +0 -9
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer.rb +0 -39
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer_test.rb +0 -38
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_evaluator.rb +0 -43
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar.rb +0 -24
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar_test.rb +0 -30
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_lexer_specification.rb +0 -23
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_parser_test.rb +0 -33
- data/test/vendor/dhaka-2.2.1/test/brackets/bracket_grammar.rb +0 -23
- data/test/vendor/dhaka-2.2.1/test/brackets/bracket_tokenizer.rb +0 -22
- data/test/vendor/dhaka-2.2.1/test/brackets/brackets_test.rb +0 -28
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver.rb +0 -46
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver_test.rb +0 -276
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator.rb +0 -284
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator_test.rb +0 -38
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_grammar.rb +0 -104
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer.rb +0 -109
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_specification.rb +0 -37
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_test.rb +0 -58
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser.rb +0 -879
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser_test.rb +0 -55
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_test.rb +0 -170
- data/test/vendor/dhaka-2.2.1/test/core/another_lalr_but_not_slr_grammar.rb +0 -20
- data/test/vendor/dhaka-2.2.1/test/core/compiled_parser_test.rb +0 -44
- data/test/vendor/dhaka-2.2.1/test/core/dfa_test.rb +0 -170
- data/test/vendor/dhaka-2.2.1/test/core/evaluator_test.rb +0 -22
- data/test/vendor/dhaka-2.2.1/test/core/grammar_test.rb +0 -83
- data/test/vendor/dhaka-2.2.1/test/core/lalr_but_not_slr_grammar.rb +0 -19
- data/test/vendor/dhaka-2.2.1/test/core/lexer_test.rb +0 -139
- data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar.rb +0 -7
- data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar_test.rb +0 -8
- data/test/vendor/dhaka-2.2.1/test/core/nullable_grammar.rb +0 -21
- data/test/vendor/dhaka-2.2.1/test/core/parse_result_test.rb +0 -44
- data/test/vendor/dhaka-2.2.1/test/core/parser_state_test.rb +0 -24
- data/test/vendor/dhaka-2.2.1/test/core/parser_test.rb +0 -131
- data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar.rb +0 -17
- data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar_test.rb +0 -9
- data/test/vendor/dhaka-2.2.1/test/core/rr_conflict_grammar.rb +0 -21
- data/test/vendor/dhaka-2.2.1/test/core/simple_grammar.rb +0 -22
- data/test/vendor/dhaka-2.2.1/test/core/sr_conflict_grammar.rb +0 -16
- data/test/vendor/dhaka-2.2.1/test/dhaka_test_helper.rb +0 -17
- data/test/vendor/dhaka-2.2.1/test/fake_logger.rb +0 -17
- data/test/vendor/simplerdb-0.2/lib/simplerdb/client_exception.rb +0 -10
- data/test/vendor/simplerdb-0.2/lib/simplerdb/db.rb +0 -146
- data/test/vendor/simplerdb-0.2/lib/simplerdb/query_language.rb +0 -266
- data/test/vendor/simplerdb-0.2/lib/simplerdb/server.rb +0 -33
- data/test/vendor/simplerdb-0.2/lib/simplerdb/servlet.rb +0 -191
- data/test/vendor/simplerdb-0.2/lib/simplerdb.rb +0 -3
- data/test/vendor/simplerdb-0.2/test/functional_test.rb +0 -81
- data/test/vendor/simplerdb-0.2/test/query_evaluator_test.rb +0 -73
- data/test/vendor/simplerdb-0.2/test/query_parser_test.rb +0 -64
- data/test/vendor/simplerdb-0.2/test/simplerdb_test.rb +0 -80
@@ -1,173 +0,0 @@
|
|
1
|
-
module SimplyStored
|
2
|
-
module SimpleDB
|
3
|
-
module Attributes
|
4
|
-
def self.included(base)
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
end
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
# generates an accessor for a simple attribute
|
10
|
-
def simpledb_string(*attributes)
|
11
|
-
attributes.each do |attr|
|
12
|
-
# getter
|
13
|
-
define_method attr.to_s do
|
14
|
-
self[attr.to_s].try(:first) || @_partitioned_attributes.try(:[], attr.to_s)
|
15
|
-
end
|
16
|
-
|
17
|
-
# setter
|
18
|
-
define_method "#{attr}=" do |val|
|
19
|
-
self[attr.to_s] = val
|
20
|
-
end
|
21
|
-
|
22
|
-
add_attribute_definition_to_attribute_list(attr)
|
23
|
-
add_attribute_definition_to_partition_list(attr)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def simpledb_array(*attributes)
|
28
|
-
attributes.each do |attr|
|
29
|
-
# getter
|
30
|
-
define_method attr.to_s do
|
31
|
-
self[attr.to_s] = [] unless self[attr.to_s]
|
32
|
-
self[attr.to_s]
|
33
|
-
end
|
34
|
-
|
35
|
-
# setter
|
36
|
-
define_method "#{attr}=" do |val|
|
37
|
-
self[attr.to_s] = [val].flatten
|
38
|
-
end
|
39
|
-
|
40
|
-
add_attribute_definition_to_attribute_list(attr)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def simpledb_timestamp(*attributes)
|
45
|
-
attributes.each do |attr|
|
46
|
-
# getter
|
47
|
-
define_method attr.to_s do
|
48
|
-
if self[attr.to_s]
|
49
|
-
cached = instance_variable_get("@#{attr}")
|
50
|
-
if cached
|
51
|
-
return cached
|
52
|
-
else
|
53
|
-
val = Time.parse(self[attr.to_s].first + "+0000").utc # UTC
|
54
|
-
instance_variable_set("@#{attr}", val)
|
55
|
-
return val
|
56
|
-
end
|
57
|
-
else
|
58
|
-
nil
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# setter
|
63
|
-
define_method "#{attr}=" do |val|
|
64
|
-
instance_variable_set("@#{attr}", val)
|
65
|
-
self[attr.to_s] = val.strftime("%Y%m%d%H%M%S")
|
66
|
-
end
|
67
|
-
|
68
|
-
add_attribute_definition_to_attribute_list(attr)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def simpledb_integer(*attributes)
|
73
|
-
attributes.each do |attr|
|
74
|
-
# getter
|
75
|
-
define_method attr.to_s do
|
76
|
-
if self[attr.to_s]
|
77
|
-
cached = instance_variable_get("@#{attr}")
|
78
|
-
if cached
|
79
|
-
return cached
|
80
|
-
else
|
81
|
-
val = self[attr.to_s].first.sub(/\A0+/, '').to_i
|
82
|
-
instance_variable_set("@#{attr}", val)
|
83
|
-
return val
|
84
|
-
end
|
85
|
-
else
|
86
|
-
nil
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# setter
|
91
|
-
define_method "#{attr}=" do |val|
|
92
|
-
instance_variable_set("@#{attr}", val)
|
93
|
-
self[attr.to_s] = sprintf("%016d", val.to_i)
|
94
|
-
end
|
95
|
-
|
96
|
-
add_attribute_definition_to_attribute_list(attr)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def add_attribute_definition_to_attribute_list(attr)
|
101
|
-
@_defined_attributes ||= []
|
102
|
-
@_defined_attributes << attr.to_s
|
103
|
-
end
|
104
|
-
|
105
|
-
def add_attribute_definition_to_partition_list(attr)
|
106
|
-
@_partitioned_attributes ||= []
|
107
|
-
@_partitioned_attributes << attr.to_s
|
108
|
-
end
|
109
|
-
|
110
|
-
def attr_protected(*args)
|
111
|
-
@_protected_attributes ||= []
|
112
|
-
@_protected_attributes += args.to_a
|
113
|
-
end
|
114
|
-
|
115
|
-
def attr_accessible(*args)
|
116
|
-
@_accessible_attributes ||= []
|
117
|
-
@_accessible_attributes += args.to_a
|
118
|
-
end
|
119
|
-
|
120
|
-
end
|
121
|
-
|
122
|
-
def attributes=(attr)
|
123
|
-
attr = _remove_protected_attributes(attr)
|
124
|
-
super(attr)
|
125
|
-
end
|
126
|
-
|
127
|
-
def _remove_protected_attributes(attrs)
|
128
|
-
return {} if attrs.blank?
|
129
|
-
attrs = attrs.dup.stringify_keys
|
130
|
-
(self.class.instance_variable_get(:@_protected_attributes) || []).map(&:to_s).each do |protected_attribute|
|
131
|
-
attrs.delete(protected_attribute)
|
132
|
-
end
|
133
|
-
|
134
|
-
accessible_attributes = (self.class.instance_variable_get(:@_accessible_attributes) || []).map(&:to_s)
|
135
|
-
|
136
|
-
if accessible_attributes.present?
|
137
|
-
attrs.each do |attr_key, attr_value|
|
138
|
-
attrs.delete(attr_key) unless accessible_attributes.include?(attr_key)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
attrs
|
143
|
-
end
|
144
|
-
|
145
|
-
def partition_string_attributes
|
146
|
-
(self.class.instance_variable_get(:@_partitioned_attributes) || []).each do |attr|
|
147
|
-
next if self[attr].nil?
|
148
|
-
value = self[attr].first
|
149
|
-
if value.present? && value.size > 1024
|
150
|
-
0.upto(value.size / 1024) do |i|
|
151
|
-
self["#{attr.to_s}_#{i}"] = value[(1024 * i)..(1024 * (i + 1) - 1)]
|
152
|
-
end
|
153
|
-
@_partitioned_attributes ||= {}
|
154
|
-
@_partitioned_attributes[attr] = self[attr]
|
155
|
-
send("#{attr}=", [])
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def restore_partitioned_attributes
|
161
|
-
(self.class.instance_variable_get(:@_partitioned_attributes) || []).each do |attr|
|
162
|
-
if (partitions = attributes.select{|key, value| key.match(/^#{attr}_([0-9]+)$/)}).any?
|
163
|
-
unpartitioned_value = ""
|
164
|
-
partitions.sort_by{|key, value| key.match(/^#{attr}_([0-9]+)$/); $1}.each do |partition|
|
165
|
-
unpartitioned_value << partition.last.first
|
166
|
-
end
|
167
|
-
self[attr] = unpartitioned_value
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
module SimplyStore
|
2
|
-
module Storage
|
3
|
-
def self.included(base)
|
4
|
-
base.extend(ClassMethods)
|
5
|
-
base.class_eval do
|
6
|
-
cattr_accessor :_s3_options
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def s3_connection
|
11
|
-
@_s3_connection ||= RightAws::S3.new(AWS_CONFIG[:aws_access_key_id], AWS_CONFIG[:aws_secret_access_key], :multi_thread => true)
|
12
|
-
end
|
13
|
-
|
14
|
-
def s3_bucket(name)
|
15
|
-
if !@_s3_bucket
|
16
|
-
@_s3_bucket = s3_connection.bucket(_s3_options[name][:bucket])
|
17
|
-
@_s3_bucket = s3_connection.bucket(_s3_options[name][:bucket], true, 'private') if @_s3_bucket.nil? # create it if it didn't exist, do not do it the first time as the ACL get modified
|
18
|
-
end
|
19
|
-
@_s3_bucket
|
20
|
-
rescue Exception => e
|
21
|
-
raise ArgumentError, "Could not access/create S3 bucket '#{name}': #{e} #{e.backtrace.join("\n")}"
|
22
|
-
end
|
23
|
-
|
24
|
-
def save
|
25
|
-
if ret = super
|
26
|
-
save_attachments
|
27
|
-
end
|
28
|
-
ret
|
29
|
-
end
|
30
|
-
|
31
|
-
def save_attachments
|
32
|
-
if @_attachments
|
33
|
-
@_attachments.each do |name, attachment|
|
34
|
-
if attachment[:dirty]
|
35
|
-
value = attachment[:value].is_a?(String) ? attachment[:value] : attachment[:value].to_json
|
36
|
-
s3_bucket(name).put(s3_attachment_key(name), value, {}, _s3_options[name][:permissions])
|
37
|
-
attachment[:dirty] = false
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def s3_attachment_key(name)
|
44
|
-
"#{self.class.name.tableize}/#{name}/#{id}"
|
45
|
-
end
|
46
|
-
|
47
|
-
module ClassMethods
|
48
|
-
def has_s3_attachment(name, options = {})
|
49
|
-
name = name.to_sym
|
50
|
-
raise ArgumentError, "No bucket name specified for attachment #{name}" if options[:bucket].blank?
|
51
|
-
options.update(:permissions => 'private', :ssl => true)
|
52
|
-
self._s3_options ||= {}
|
53
|
-
self._s3_options[name] = options
|
54
|
-
|
55
|
-
define_attachment_accessors(name)
|
56
|
-
attr_reader :_attachments
|
57
|
-
end
|
58
|
-
|
59
|
-
def define_attachment_accessors(name)
|
60
|
-
define_method(name) do
|
61
|
-
unless @_attachments and @_attachments[name]
|
62
|
-
@_attachments = {name => {}}
|
63
|
-
@_attachments[name][:value] = s3_bucket(name).get(s3_attachment_key(name))
|
64
|
-
end
|
65
|
-
@_attachments[name][:value]
|
66
|
-
end
|
67
|
-
|
68
|
-
define_method("#{name}=") do |value|
|
69
|
-
@_attachments ||= {}
|
70
|
-
@_attachments[name] ||= {}
|
71
|
-
@_attachments[name].update(:value => value, :dirty => true)
|
72
|
-
value
|
73
|
-
end
|
74
|
-
|
75
|
-
define_method("#{name}_url") do
|
76
|
-
if _s3_options[name][:permissions] == 'private'
|
77
|
-
RightAws::S3Generator.new(AWS_CONFIG[:aws_access_key_id], AWS_CONFIG[:aws_secret_access_key], :multi_thread => true).bucket(_s3_options[name][:bucket]).get(s3_attachment_key(name), 5.minutes)
|
78
|
-
else
|
79
|
-
"http://#{_s3_options[name][:bucket].to_s}.s3.amazonaws.com/#{s3_attachment_key(name)}"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
@@ -1,88 +0,0 @@
|
|
1
|
-
module SimplyStored
|
2
|
-
module SimpleDB
|
3
|
-
module Validations
|
4
|
-
def validate
|
5
|
-
# abstract - implement in subclass and add checks that add to errors with add_error
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.included(base)
|
9
|
-
base.extend(ClassMethods)
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
def require_attributes(*attributes)
|
14
|
-
@_required_attributes ||= []
|
15
|
-
attributes.each do |attr|
|
16
|
-
@_required_attributes << attr.to_s
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def require_inclusion_of(attr, valid_set, options = {})
|
21
|
-
options = {
|
22
|
-
:allow_blank => false
|
23
|
-
}.update(options)
|
24
|
-
@_required_inclusions ||= {}
|
25
|
-
@_required_inclusions[attr.to_s] = [valid_set, options]
|
26
|
-
end
|
27
|
-
|
28
|
-
def require_format_of(attr, valid_regex, options = {})
|
29
|
-
options = {
|
30
|
-
:allow_blank => false
|
31
|
-
}.update(options)
|
32
|
-
@_required_formats ||= {}
|
33
|
-
@_required_formats[attr.to_s] = [valid_regex, options]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def ensure_formats
|
38
|
-
list_of_format_checks = self.class.instance_variable_get("@_required_formats") || {}
|
39
|
-
list_of_format_checks.each do |attr, check_options|
|
40
|
-
valid_regex, options = check_options
|
41
|
-
add_error(attr, 'is of invalid format') unless valid_regex.match(self.send(attr)) || (self.send(attr).blank? && options[:allow_blank])
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def ensure_inclusions
|
46
|
-
list_of_inclusion_checks = self.class.instance_variable_get("@_required_inclusions") || {}
|
47
|
-
list_of_inclusion_checks.each do |attr, check_options|
|
48
|
-
valid_set, options = check_options
|
49
|
-
if self.send(attr) && self.send(attr).is_a?(Array)
|
50
|
-
self.send(attr).all? do |item|
|
51
|
-
add_error(attr, 'is not included in the valid set') unless (valid_set.include?(item) rescue false) || (self.send(attr).blank? && options[:allow_blank])
|
52
|
-
end
|
53
|
-
else
|
54
|
-
add_error(attr, 'is not included in the valid set') unless (valid_set.include?(self.send(attr)) rescue false) || (self.send(attr).blank? && options[:allow_blank])
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def add_error(attr, desc)
|
60
|
-
errors << [attr, desc]
|
61
|
-
end
|
62
|
-
|
63
|
-
def clear_errors
|
64
|
-
@errors = []
|
65
|
-
end
|
66
|
-
|
67
|
-
def ensure_no_foreign_attributes
|
68
|
-
not_allowed_attributes = self.attributes.keys.sort - (self.class.instance_variable_get("@_defined_attributes") || [])
|
69
|
-
not_allowed_attributes = not_allowed_attributes.delete_if{|attr| attr.to_s == 'id'} # the ID is an implicit attribute
|
70
|
-
not_allowed_attributes.each do |attr|
|
71
|
-
add_error(attr, 'is unknown and should not be set')
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def ensure_required_attributes_present
|
76
|
-
list_of_required_attributes = self.class.instance_variable_get("@_required_attributes") || []
|
77
|
-
list_of_required_attributes.all? do |attr|
|
78
|
-
if self.send(attr).blank?
|
79
|
-
add_error(attr, 'is missing')
|
80
|
-
false
|
81
|
-
else
|
82
|
-
true
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -1,216 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../simply_stored')
|
2
|
-
|
3
|
-
require 'sdb/right_sdb_interface'
|
4
|
-
require 'sdb/active_sdb'
|
5
|
-
require "simply_stored/simpledb/attributes"
|
6
|
-
require "simply_stored/simpledb/associations"
|
7
|
-
require "simply_stored/simpledb/validations"
|
8
|
-
|
9
|
-
module SimplyStored
|
10
|
-
class Simple < RightAws::ActiveSdb::Base
|
11
|
-
def self.aws_access_key
|
12
|
-
@_aws_access_key
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.aws_secret_access_key
|
16
|
-
@_aws_secret_access_key
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.aws_access_key=(aws_access_key)
|
20
|
-
@_aws_access_key = aws_access_key
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.aws_secret_access_key=(aws_secret_access_key)
|
24
|
-
@_aws_secret_access_key = aws_secret_access_key
|
25
|
-
end
|
26
|
-
|
27
|
-
include SimplyStored::SimpleDB::Associations
|
28
|
-
include SimplyStored::SimpleDB::Attributes
|
29
|
-
include SimplyStored::SimpleDB::Validations
|
30
|
-
extend SimplyStored::Storage::ClassMethods
|
31
|
-
|
32
|
-
alias :active_sdb_save :save
|
33
|
-
alias :active_sdb_delete :delete
|
34
|
-
alias :active_sdb_save_attributes :save_attributes
|
35
|
-
|
36
|
-
def initialize(attrs={})
|
37
|
-
attrs = _remove_protected_attributes(attrs) || {}
|
38
|
-
super(attrs)
|
39
|
-
end
|
40
|
-
|
41
|
-
def save(run_validations = true)
|
42
|
-
run_validations ? save_with_validations : save_without_validations
|
43
|
-
end
|
44
|
-
|
45
|
-
def reload
|
46
|
-
super
|
47
|
-
restore_partitioned_attributes
|
48
|
-
self
|
49
|
-
end
|
50
|
-
|
51
|
-
def save_with_validations
|
52
|
-
new_record = new_record? # save status as it changes during saving
|
53
|
-
before_create if new_record && respond_to?(:before_create)
|
54
|
-
before_save if respond_to?(:before_save)
|
55
|
-
if valid?
|
56
|
-
set_timestamps
|
57
|
-
partition_string_attributes
|
58
|
-
sdb_operation(:save)
|
59
|
-
clear_errors
|
60
|
-
after_create if new_record && respond_to?(:after_create)
|
61
|
-
after_save if respond_to?(:after_save)
|
62
|
-
true
|
63
|
-
else
|
64
|
-
false
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def save_without_validations
|
69
|
-
new_record = new_record? # save status as it changes during saving
|
70
|
-
before_create if new_record && respond_to?(:before_create)
|
71
|
-
before_save if respond_to?(:before_save)
|
72
|
-
set_timestamps
|
73
|
-
sdb_operation(:save)
|
74
|
-
clear_errors
|
75
|
-
after_create if new_record && respond_to?(:after_create)
|
76
|
-
after_save if respond_to?(:after_save)
|
77
|
-
true
|
78
|
-
end
|
79
|
-
|
80
|
-
def delete
|
81
|
-
before_delete if respond_to?(:before_delete)
|
82
|
-
sdb_operation(:delete)
|
83
|
-
after_delete if respond_to?(:after_delete)
|
84
|
-
clear_dependents_after_delete
|
85
|
-
nil
|
86
|
-
end
|
87
|
-
|
88
|
-
def valid?
|
89
|
-
clear_errors
|
90
|
-
before_validation if respond_to?(:before_validation)
|
91
|
-
ensure_no_foreign_attributes
|
92
|
-
ensure_required_attributes_present
|
93
|
-
ensure_inclusions
|
94
|
-
ensure_formats
|
95
|
-
validate
|
96
|
-
errors.empty?
|
97
|
-
end
|
98
|
-
|
99
|
-
def errors
|
100
|
-
@errors ||= []
|
101
|
-
end
|
102
|
-
|
103
|
-
def self.domain
|
104
|
-
unless @domain
|
105
|
-
if defined? ActiveSupport::CoreExtensions::String::Inflections
|
106
|
-
@domain = name.tableize.gsub('/','__').gsub('::','__')
|
107
|
-
else
|
108
|
-
@domain = name.downcase.gsub('/','__').gsub('::','__')
|
109
|
-
end
|
110
|
-
end
|
111
|
-
@domain
|
112
|
-
end
|
113
|
-
|
114
|
-
def self.foreign_key
|
115
|
-
self.name.underscore.gsub('/','__').gsub('::','__') + "_id"
|
116
|
-
end
|
117
|
-
|
118
|
-
def self.find(*args)
|
119
|
-
retries = 0
|
120
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
121
|
-
options.update(:auto_load => true)
|
122
|
-
args << options
|
123
|
-
begin
|
124
|
-
super(*args)
|
125
|
-
rescue Rightscale::AwsError => e
|
126
|
-
if (Rightscale::AwsError.system_error?(e) or e.message.match(/^RequestThrottled/)) and retries < 2
|
127
|
-
retries += 1
|
128
|
-
sleep retries * 0.5
|
129
|
-
retry
|
130
|
-
else
|
131
|
-
raise Error.new("Couldn't find item with #{args.inspect}: #{e}")
|
132
|
-
end
|
133
|
-
rescue RightAws::ActiveSdb::ActiveSdbError => e
|
134
|
-
if e.message.match(/Couldn't find #{name} with ID/)
|
135
|
-
if retries < 2
|
136
|
-
retries += 1
|
137
|
-
sleep retries * 0.5
|
138
|
-
retry
|
139
|
-
else
|
140
|
-
raise RecordNotFound, e.message
|
141
|
-
end
|
142
|
-
else
|
143
|
-
raise
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def self.all(options = {})
|
149
|
-
find(:all, options)
|
150
|
-
end
|
151
|
-
|
152
|
-
def self.first(options = {})
|
153
|
-
find(:first, options)
|
154
|
-
end
|
155
|
-
|
156
|
-
def update_attributes(*args)
|
157
|
-
# HACK in order to update attributes to nil
|
158
|
-
# thank you ActiveSDB
|
159
|
-
if (attrs = args.first).is_a?(Hash)
|
160
|
-
attrs.each do |k,v|
|
161
|
-
attrs[k] = [nil] if v.blank?
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
sdb_operation(:save_attributes, *args)
|
166
|
-
end
|
167
|
-
|
168
|
-
def to_param
|
169
|
-
id
|
170
|
-
end
|
171
|
-
|
172
|
-
# set several attrbiutes at once with a given hash
|
173
|
-
# in contrast to ActiveSDB#attributes= it doesn't nil the other attributes
|
174
|
-
def set_attributes(attrs)
|
175
|
-
attrs = _remove_protected_attributes(attrs)
|
176
|
-
|
177
|
-
attrs.each do |k,v|
|
178
|
-
self[k] = v
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
protected
|
183
|
-
|
184
|
-
def self.generate_id
|
185
|
-
UUIDTools::UUID.random_create().to_s
|
186
|
-
end
|
187
|
-
|
188
|
-
def sdb_operation(operation, *args)
|
189
|
-
retries = 0
|
190
|
-
begin
|
191
|
-
send("active_sdb_#{operation}", *args)
|
192
|
-
rescue Rightscale::AwsError => e
|
193
|
-
if (Rightscale::AwsError.system_error?(e) or e.message.match(/^RequestThrottled/)) and retries < 2
|
194
|
-
retries += 1
|
195
|
-
sleep retries * 0.5
|
196
|
-
retry
|
197
|
-
else
|
198
|
-
raise Error.new("Couldn't #{operation} item of type #{self.class.name}#{id.nil? ? "" : " (with id: #{id})"}: #{e} #{e.backtrace.join("\n")}")
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def set_timestamps
|
204
|
-
self.updated_at = Time.now.utc if self.respond_to?(:updated_at=)
|
205
|
-
self.created_at = Time.now.utc if self.respond_to?(:created_at=) && self.new_record?
|
206
|
-
end
|
207
|
-
|
208
|
-
def self.get_class_from_name(klass_name)
|
209
|
-
klass_name.to_s.gsub('__','/').classify.constantize
|
210
|
-
end
|
211
|
-
|
212
|
-
def self.formalize_class_name(name)
|
213
|
-
name.to_s.gsub('__','/').gsub('__','::').classify
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
class Item < SimplyStored::Simple
|
2
|
-
simpledb_string :foo_attribute, :item_daddy_id
|
3
|
-
simpledb_array :bar_attribute_array
|
4
|
-
simpledb_timestamp :updated_at, :created_at
|
5
|
-
simpledb_integer :integer_field
|
6
|
-
|
7
|
-
require_inclusion_of :foo_attribute, ['a', 'b', 'c']
|
8
|
-
require_inclusion_of :bar_attribute_array, ['goog', 'boob']
|
9
|
-
|
10
|
-
belongs_to :item_daddy
|
11
|
-
end
|