simply_stored 0.3.9 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|