ahoward-helene 0.0.3
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/Rakefile +274 -0
- data/helene.gemspec +26 -0
- data/lib/helene.rb +113 -0
- data/lib/helene/attempt.rb +46 -0
- data/lib/helene/aws.rb +50 -0
- data/lib/helene/config.rb +147 -0
- data/lib/helene/content_type.rb +15 -0
- data/lib/helene/content_type.yml +661 -0
- data/lib/helene/error.rb +12 -0
- data/lib/helene/logging.rb +55 -0
- data/lib/helene/objectpool.rb +220 -0
- data/lib/helene/rails.rb +21 -0
- data/lib/helene/rightscale/acf/right_acf_interface.rb +379 -0
- data/lib/helene/rightscale/awsbase/benchmark_fix.rb +39 -0
- data/lib/helene/rightscale/awsbase/right_awsbase.rb +803 -0
- data/lib/helene/rightscale/awsbase/support.rb +111 -0
- data/lib/helene/rightscale/ec2/right_ec2.rb +1737 -0
- data/lib/helene/rightscale/net_fix.rb +160 -0
- data/lib/helene/rightscale/right_aws.rb +71 -0
- data/lib/helene/rightscale/right_http_connection.rb +507 -0
- data/lib/helene/rightscale/s3/right_s3.rb +1094 -0
- data/lib/helene/rightscale/s3/right_s3_interface.rb +1180 -0
- data/lib/helene/rightscale/sdb/active_sdb.rb +930 -0
- data/lib/helene/rightscale/sdb/right_sdb_interface.rb +696 -0
- data/lib/helene/rightscale/sqs/right_sqs.rb +388 -0
- data/lib/helene/rightscale/sqs/right_sqs_gen2.rb +286 -0
- data/lib/helene/rightscale/sqs/right_sqs_gen2_interface.rb +444 -0
- data/lib/helene/rightscale/sqs/right_sqs_interface.rb +596 -0
- data/lib/helene/s3.rb +34 -0
- data/lib/helene/s3/bucket.rb +379 -0
- data/lib/helene/s3/grantee.rb +134 -0
- data/lib/helene/s3/key.rb +162 -0
- data/lib/helene/s3/owner.rb +16 -0
- data/lib/helene/sdb.rb +9 -0
- data/lib/helene/sdb/base.rb +1204 -0
- data/lib/helene/sdb/base/associations.rb +481 -0
- data/lib/helene/sdb/base/attributes.rb +90 -0
- data/lib/helene/sdb/base/connection.rb +20 -0
- data/lib/helene/sdb/base/error.rb +20 -0
- data/lib/helene/sdb/base/hooks.rb +82 -0
- data/lib/helene/sdb/base/literal.rb +52 -0
- data/lib/helene/sdb/base/logging.rb +23 -0
- data/lib/helene/sdb/base/transactions.rb +53 -0
- data/lib/helene/sdb/base/type.rb +137 -0
- data/lib/helene/sdb/base/types.rb +123 -0
- data/lib/helene/sdb/base/validations.rb +256 -0
- data/lib/helene/sdb/cast.rb +114 -0
- data/lib/helene/sdb/connection.rb +36 -0
- data/lib/helene/sdb/error.rb +5 -0
- data/lib/helene/sdb/interface.rb +412 -0
- data/lib/helene/sdb/sentinel.rb +15 -0
- data/lib/helene/sleepcycle.rb +29 -0
- data/lib/helene/superhash.rb +297 -0
- data/lib/helene/util.rb +132 -0
- data/test/auth.rb +31 -0
- data/test/helper.rb +98 -0
- data/test/integration/begin.rb +0 -0
- data/test/integration/ensure.rb +8 -0
- data/test/integration/s3/bucket.rb +106 -0
- data/test/integration/sdb/associations.rb +45 -0
- data/test/integration/sdb/creating.rb +13 -0
- data/test/integration/sdb/emptiness.rb +56 -0
- data/test/integration/sdb/hooks.rb +19 -0
- data/test/integration/sdb/limits.rb +27 -0
- data/test/integration/sdb/saving.rb +21 -0
- data/test/integration/sdb/selecting.rb +39 -0
- data/test/integration/sdb/types.rb +31 -0
- data/test/integration/sdb/validations.rb +60 -0
- data/test/integration/setup.rb +27 -0
- data/test/integration/teardown.rb +21 -0
- data/test/loader.rb +39 -0
- metadata +139 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
module Helene
|
2
|
+
module Sdb
|
3
|
+
class Base
|
4
|
+
class Type
|
5
|
+
type(:string){
|
6
|
+
ruby_to_sdb do |value|
|
7
|
+
value.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
sdb_to_ruby do |value|
|
11
|
+
Array(value).first.to_s
|
12
|
+
end
|
13
|
+
}
|
14
|
+
|
15
|
+
type(:symbol){
|
16
|
+
ruby_to_sdb do |value|
|
17
|
+
value.to_s.to_sym.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
sdb_to_ruby do |value|
|
21
|
+
Array(value).first.to_s.to_sym
|
22
|
+
end
|
23
|
+
}
|
24
|
+
|
25
|
+
type(:timestamp){
|
26
|
+
ruby_to_sdb do |value|
|
27
|
+
Time.parse(value.to_s).utc.iso8601(2)
|
28
|
+
end
|
29
|
+
|
30
|
+
sdb_to_ruby do |value|
|
31
|
+
Time.parse(Array(value).first.to_s).localtime
|
32
|
+
end
|
33
|
+
}
|
34
|
+
|
35
|
+
type(:boolean){
|
36
|
+
ruby_to_sdb do |value|
|
37
|
+
(!!value).to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
sdb_to_ruby do |value|
|
41
|
+
Array(value).first.to_s =~ %r/^\s*t/i ? true : false
|
42
|
+
end
|
43
|
+
}
|
44
|
+
|
45
|
+
type(:number){
|
46
|
+
ruby_to_sdb do |value|
|
47
|
+
number = Integer(value.to_s)
|
48
|
+
raise ArgumentError, "(#{ name } = #{ number.inspect }) < 0" if number < 0
|
49
|
+
INT_FMT % number
|
50
|
+
end
|
51
|
+
|
52
|
+
sdb_to_ruby do |value|
|
53
|
+
Integer(Array(value).first.to_s.sub(%r/^[0-]+/,''))
|
54
|
+
end
|
55
|
+
}
|
56
|
+
|
57
|
+
type(:integer){
|
58
|
+
ruby_to_sdb do |value|
|
59
|
+
number = Integer(value.to_s)
|
60
|
+
offset = number + Type::INT_OFF
|
61
|
+
if(offset < 0 || offset.class != Fixnum)
|
62
|
+
raise(
|
63
|
+
ArgumentError,
|
64
|
+
"(#{ name } = #{ number.inspect } (offset=#{ offset })) too small"
|
65
|
+
)
|
66
|
+
end
|
67
|
+
INT_FMT % offset
|
68
|
+
end
|
69
|
+
|
70
|
+
sdb_to_ruby do |array|
|
71
|
+
offset = Integer([array].flatten.first.to_s.sub(%r/^[0-]+/,''))
|
72
|
+
number = offset - Type::INT_OFF
|
73
|
+
end
|
74
|
+
}
|
75
|
+
|
76
|
+
type(:sti){
|
77
|
+
ruby_to_sdb do |value|
|
78
|
+
value.to_s
|
79
|
+
end
|
80
|
+
|
81
|
+
sdb_to_ruby do |value|
|
82
|
+
Array(value).first.to_s
|
83
|
+
end
|
84
|
+
}
|
85
|
+
|
86
|
+
type(:url){
|
87
|
+
ruby_to_sdb do |value|
|
88
|
+
value.to_s.sub(%r{\A(?!\w+:)(?=\S)}, "http://")
|
89
|
+
end
|
90
|
+
|
91
|
+
sdb_to_ruby do |value|
|
92
|
+
Array(value).first.to_s
|
93
|
+
end
|
94
|
+
}
|
95
|
+
|
96
|
+
type(:text){
|
97
|
+
ruby_to_sdb do |value|
|
98
|
+
chunks = value.to_s.scan(%r/.{1,1019}/) # 1024 - '1024:'.size
|
99
|
+
i = -1
|
100
|
+
fmt = '%04d:'
|
101
|
+
chunks.map!{|chunk| [(fmt % (i += 1)), chunk].join}
|
102
|
+
raise ArgumentError, 'that is just too big yo!' if chunks.size >= 256
|
103
|
+
chunks
|
104
|
+
end
|
105
|
+
|
106
|
+
sdb_to_ruby do |value|
|
107
|
+
chunks =
|
108
|
+
Array(value).flatten.map do |chunk|
|
109
|
+
index, text = chunk.split(%r/:/, 2)
|
110
|
+
[Float(index).to_i, text]
|
111
|
+
end
|
112
|
+
chunks.replace chunks.sort_by{|index, text| index}
|
113
|
+
chunks.map!{|index, text| text}.join
|
114
|
+
end
|
115
|
+
|
116
|
+
to_condition do |value|
|
117
|
+
value.to_s
|
118
|
+
end
|
119
|
+
}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
module Helene
|
2
|
+
module Sdb
|
3
|
+
class Base
|
4
|
+
module Validations
|
5
|
+
class Error < StandardError
|
6
|
+
attr :object
|
7
|
+
|
8
|
+
def initialize(object, *args, &block)
|
9
|
+
@object = object
|
10
|
+
args.unshift object.errors.message if args.empty?
|
11
|
+
super(*args, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def errors
|
15
|
+
object.errors
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.included(c)
|
20
|
+
super
|
21
|
+
c.extend ClassMethods
|
22
|
+
end
|
23
|
+
|
24
|
+
def errors
|
25
|
+
if(not defined?(@errors) or @errors.nil?)
|
26
|
+
@errors ||= Errors.new(self)
|
27
|
+
end
|
28
|
+
@errors
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate
|
32
|
+
errors.clear
|
33
|
+
self.class.validate(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate!
|
37
|
+
errors.clear
|
38
|
+
self.class.validate!(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def valid?
|
42
|
+
validate
|
43
|
+
errors.empty?
|
44
|
+
end
|
45
|
+
|
46
|
+
def errors?
|
47
|
+
not valid?
|
48
|
+
end
|
49
|
+
|
50
|
+
class Errors < ::Hash
|
51
|
+
attr_accessor :object
|
52
|
+
|
53
|
+
class << Errors
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize object = nil
|
57
|
+
@object = object
|
58
|
+
block = lambda{|h,k| h[k] = []}
|
59
|
+
super(&block)
|
60
|
+
end
|
61
|
+
|
62
|
+
def Errors._load(string)
|
63
|
+
new.update(Marshal.load(string))
|
64
|
+
end
|
65
|
+
|
66
|
+
def _dump(*a)
|
67
|
+
Marshal.dump({}.update(to_hash))
|
68
|
+
end
|
69
|
+
|
70
|
+
def count
|
71
|
+
size
|
72
|
+
end
|
73
|
+
|
74
|
+
def on(att)
|
75
|
+
self[att]
|
76
|
+
end
|
77
|
+
|
78
|
+
def add(att, msg)
|
79
|
+
self[att] << msg
|
80
|
+
end
|
81
|
+
|
82
|
+
def full_messages
|
83
|
+
inject([]) do |m, kv| att, errors = *kv
|
84
|
+
errors.each {|e| m << "#{att} #{e}"}
|
85
|
+
m
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def message
|
90
|
+
full_messages.join(' | ')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Validation
|
95
|
+
def initialize(on = :save, &validation)
|
96
|
+
@on = (on || :save).to_sym
|
97
|
+
@validation = validation || lambda { |o, att, v| }
|
98
|
+
end
|
99
|
+
|
100
|
+
attr_reader :on
|
101
|
+
|
102
|
+
def call(o, att, v)
|
103
|
+
save_type = o.new_record? ? :create : :update
|
104
|
+
@validation[o, att, v] if [:save, save_type].include?(on)
|
105
|
+
end
|
106
|
+
alias_method :[], :call
|
107
|
+
end
|
108
|
+
|
109
|
+
module ClassMethods
|
110
|
+
def validations
|
111
|
+
@validations ||= Hash.new {|h, k| h[k] = []}
|
112
|
+
end
|
113
|
+
|
114
|
+
def has_validations?
|
115
|
+
!validations.empty?
|
116
|
+
end
|
117
|
+
|
118
|
+
def validate(o)
|
119
|
+
if superclass.respond_to?(:validate) && !@skip_superclass_validations
|
120
|
+
superclass.validate(o)
|
121
|
+
end
|
122
|
+
validations.each do |att, procs|
|
123
|
+
v = o.send(att)
|
124
|
+
procs.each {|p| p[o, att, v]}
|
125
|
+
end
|
126
|
+
o
|
127
|
+
end
|
128
|
+
|
129
|
+
def validate!(o)
|
130
|
+
validate(o)
|
131
|
+
raise Error.new(o, o.errors.message) unless o.errors.empty?
|
132
|
+
o
|
133
|
+
end
|
134
|
+
|
135
|
+
def skip_superclass_validations
|
136
|
+
@skip_superclass_validations = true
|
137
|
+
end
|
138
|
+
|
139
|
+
def validates_each(*atts, &block)
|
140
|
+
options = atts.extract_options!.to_options!
|
141
|
+
atts.each {|a| validations[a] << Validation.new(options[:on], &block)}
|
142
|
+
end
|
143
|
+
|
144
|
+
def validates(a, options = Hash.new, &block)
|
145
|
+
curried = Validation.new(options[:on]) {|record, attr, value| block.call(record, value)}
|
146
|
+
validations[a] << curried
|
147
|
+
end
|
148
|
+
|
149
|
+
def validates_acceptance_of(*atts)
|
150
|
+
opts = {
|
151
|
+
:message => 'is not accepted',
|
152
|
+
:allow_nil => true,
|
153
|
+
:accept => '1'
|
154
|
+
}.merge!(atts.extract_options!)
|
155
|
+
|
156
|
+
args = atts + [{:on => opts[:on]}]
|
157
|
+
validates_each(*args) do |o, a, v|
|
158
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
159
|
+
o.errors[a] << opts[:message] unless v == opts[:accept]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def validates_confirmation_of(*atts)
|
164
|
+
opts = {
|
165
|
+
:message => 'is not confirmed',
|
166
|
+
}.merge!(atts.extract_options!)
|
167
|
+
|
168
|
+
atts.each { |a| attr_accessor :"#{a}_confirmation" }
|
169
|
+
|
170
|
+
args = atts + [{:on => opts[:on]}]
|
171
|
+
validates_each(*args) do |o, a, v|
|
172
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
173
|
+
c = o.send(:"#{a}_confirmation")
|
174
|
+
o.errors[a] << opts[:message] unless v == c
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def validates_format_of(*atts)
|
179
|
+
opts = {
|
180
|
+
:message => 'is invalid',
|
181
|
+
}.merge!(atts.extract_options!)
|
182
|
+
|
183
|
+
unless opts[:with].is_a?(Regexp)
|
184
|
+
raise ArgumentError, "A regular expression must be supplied as the :with option of the options hash"
|
185
|
+
end
|
186
|
+
|
187
|
+
args = atts + [{:on => opts[:on]}]
|
188
|
+
validates_each(*args) do |o, a, v|
|
189
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
190
|
+
o.errors[a] << opts[:message] unless v.to_s =~ opts[:with]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def validates_length_of(*atts)
|
195
|
+
opts = {
|
196
|
+
:too_long => 'is too long',
|
197
|
+
:too_short => 'is too short',
|
198
|
+
:wrong_length => 'is the wrong length'
|
199
|
+
}.merge!(atts.extract_options!)
|
200
|
+
|
201
|
+
args = atts + [{:on => opts[:on]}]
|
202
|
+
validates_each(*args) do |o, a, v|
|
203
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
204
|
+
if m = opts[:maximum]
|
205
|
+
o.errors[a] << (opts[:message] || opts[:too_long]) unless v && v.size <= m
|
206
|
+
end
|
207
|
+
if m = opts[:minimum]
|
208
|
+
o.errors[a] << (opts[:message] || opts[:too_short]) unless v && v.size >= m
|
209
|
+
end
|
210
|
+
if i = opts[:is]
|
211
|
+
o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && v.size == i
|
212
|
+
end
|
213
|
+
if w = opts[:within]
|
214
|
+
o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && w.include?(v.size)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
NUMBER_RE = /^\d*\.{0,1}\d+$/ unless defined?(NUMBER_RE)
|
220
|
+
INTEGER_RE = /\A[+-]?\d+\Z/ unless defined?(INTEGER_RE)
|
221
|
+
|
222
|
+
def validates_numericality_of(*atts)
|
223
|
+
opts = {
|
224
|
+
:message => 'is not a number',
|
225
|
+
}.merge!(atts.extract_options!)
|
226
|
+
|
227
|
+
re = opts[:only_integer] ? INTEGER_RE : NUMBER_RE
|
228
|
+
number = lambda do |value|
|
229
|
+
Float(value) rescue Integer(value) rescue false
|
230
|
+
end
|
231
|
+
|
232
|
+
args = atts + [{:on => opts[:on]}]
|
233
|
+
validates_each(*args) do |o, a, v|
|
234
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
235
|
+
#o.errors[a] << opts[:message] unless v.to_s =~ re
|
236
|
+
o.errors[a] << opts[:message] unless number[v]
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def validates_presence_of(*atts)
|
241
|
+
opts = {
|
242
|
+
:message => 'is not present',
|
243
|
+
}.merge!(atts.extract_options!)
|
244
|
+
|
245
|
+
args = atts + [{:on => opts[:on]}]
|
246
|
+
validates_each(*args) do |o, a, v|
|
247
|
+
o.errors[a] << opts[:message] unless v && !v.blank?
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
include Validations
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Helene
|
2
|
+
module Sdb
|
3
|
+
module Cast
|
4
|
+
def self.export m
|
5
|
+
module_function m
|
6
|
+
public m
|
7
|
+
end
|
8
|
+
|
9
|
+
List = []
|
10
|
+
|
11
|
+
def self.cast m, &b
|
12
|
+
define_method m, &b
|
13
|
+
export m
|
14
|
+
List << m.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
cast :boolean do |obj|
|
18
|
+
obj = [obj].flatten.first.to_s
|
19
|
+
case obj
|
20
|
+
when %r/^(true|t|1)$/
|
21
|
+
true
|
22
|
+
when %r/^(false|f|0)$/
|
23
|
+
false
|
24
|
+
else
|
25
|
+
!!obj
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
cast :integer do |obj|
|
30
|
+
obj = [obj].flatten.first.to_s
|
31
|
+
Integer(obj)
|
32
|
+
end
|
33
|
+
|
34
|
+
cast :float do |obj|
|
35
|
+
obj = [obj].flatten.first.to_s
|
36
|
+
Float(obj)
|
37
|
+
end
|
38
|
+
|
39
|
+
cast :number do |obj|
|
40
|
+
obj = [obj].flatten.first.to_s
|
41
|
+
Float(obj) rescue Integer(obj)
|
42
|
+
end
|
43
|
+
|
44
|
+
cast :string do |obj|
|
45
|
+
obj = [obj].flatten.first.to_s
|
46
|
+
String(obj)
|
47
|
+
end
|
48
|
+
|
49
|
+
cast :symbol do |obj|
|
50
|
+
obj = [obj].flatten.first.to_s
|
51
|
+
String(obj).to_sym
|
52
|
+
end
|
53
|
+
|
54
|
+
cast :uri do |obj|
|
55
|
+
require 'uri'
|
56
|
+
obj = [obj].flatten.first.to_s
|
57
|
+
::URI.parse(obj)
|
58
|
+
end
|
59
|
+
|
60
|
+
cast :time do |obj|
|
61
|
+
require 'time'
|
62
|
+
obj = [obj].flatten.first.to_s
|
63
|
+
::Time.parse(obj)
|
64
|
+
end
|
65
|
+
|
66
|
+
cast :date do |obj|
|
67
|
+
obj = [obj].flatten.first.to_s
|
68
|
+
require 'date'
|
69
|
+
::Date.parse(obj)
|
70
|
+
end
|
71
|
+
|
72
|
+
cast :list do |*objs|
|
73
|
+
[*objs].flatten.join(',').split(/,/)
|
74
|
+
end
|
75
|
+
|
76
|
+
# add list_of_xxx methods
|
77
|
+
List.dup.each do |type|
|
78
|
+
next if type.to_s =~ %r/list/
|
79
|
+
m = "list_of_#{ type }"
|
80
|
+
define_method m do |*objs|
|
81
|
+
list(*objs).map{|obj| send type, obj}
|
82
|
+
end
|
83
|
+
export m
|
84
|
+
List << m
|
85
|
+
end
|
86
|
+
|
87
|
+
# add list_of_xxx_from_file
|
88
|
+
List.dup.each do |type|
|
89
|
+
next if type.to_s =~ %r/list/
|
90
|
+
m = "list_of_#{ type }"
|
91
|
+
define_method m do |*objs|
|
92
|
+
list(*objs).map{|obj| send type, obj}
|
93
|
+
end
|
94
|
+
export m
|
95
|
+
List << m
|
96
|
+
end
|
97
|
+
|
98
|
+
def Cast.for(sym)
|
99
|
+
prefix = sym.to_s.downcase.to_sym
|
100
|
+
candidates = List.select{|m| m =~ %r/^#{ prefix }/i}
|
101
|
+
m = candidates.shift
|
102
|
+
raise ArgumentError, "unsupported cast: #{ sym.inspect } (#{ List.join ',' })" unless
|
103
|
+
m
|
104
|
+
raise ArgumentError, "ambiguous cast: #{ sym.inspect } (#{ List.join ',' })" unless
|
105
|
+
candidates.empty? or m.to_s == sym.to_s
|
106
|
+
this = self
|
107
|
+
lambda{|obj| method(m).call obj}
|
108
|
+
end
|
109
|
+
def self.[] sym
|
110
|
+
Cast.for(sym)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|