ahoward-helene 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|