ahoward-helene 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/Rakefile +274 -0
  2. data/helene.gemspec +26 -0
  3. data/lib/helene.rb +113 -0
  4. data/lib/helene/attempt.rb +46 -0
  5. data/lib/helene/aws.rb +50 -0
  6. data/lib/helene/config.rb +147 -0
  7. data/lib/helene/content_type.rb +15 -0
  8. data/lib/helene/content_type.yml +661 -0
  9. data/lib/helene/error.rb +12 -0
  10. data/lib/helene/logging.rb +55 -0
  11. data/lib/helene/objectpool.rb +220 -0
  12. data/lib/helene/rails.rb +21 -0
  13. data/lib/helene/rightscale/acf/right_acf_interface.rb +379 -0
  14. data/lib/helene/rightscale/awsbase/benchmark_fix.rb +39 -0
  15. data/lib/helene/rightscale/awsbase/right_awsbase.rb +803 -0
  16. data/lib/helene/rightscale/awsbase/support.rb +111 -0
  17. data/lib/helene/rightscale/ec2/right_ec2.rb +1737 -0
  18. data/lib/helene/rightscale/net_fix.rb +160 -0
  19. data/lib/helene/rightscale/right_aws.rb +71 -0
  20. data/lib/helene/rightscale/right_http_connection.rb +507 -0
  21. data/lib/helene/rightscale/s3/right_s3.rb +1094 -0
  22. data/lib/helene/rightscale/s3/right_s3_interface.rb +1180 -0
  23. data/lib/helene/rightscale/sdb/active_sdb.rb +930 -0
  24. data/lib/helene/rightscale/sdb/right_sdb_interface.rb +696 -0
  25. data/lib/helene/rightscale/sqs/right_sqs.rb +388 -0
  26. data/lib/helene/rightscale/sqs/right_sqs_gen2.rb +286 -0
  27. data/lib/helene/rightscale/sqs/right_sqs_gen2_interface.rb +444 -0
  28. data/lib/helene/rightscale/sqs/right_sqs_interface.rb +596 -0
  29. data/lib/helene/s3.rb +34 -0
  30. data/lib/helene/s3/bucket.rb +379 -0
  31. data/lib/helene/s3/grantee.rb +134 -0
  32. data/lib/helene/s3/key.rb +162 -0
  33. data/lib/helene/s3/owner.rb +16 -0
  34. data/lib/helene/sdb.rb +9 -0
  35. data/lib/helene/sdb/base.rb +1204 -0
  36. data/lib/helene/sdb/base/associations.rb +481 -0
  37. data/lib/helene/sdb/base/attributes.rb +90 -0
  38. data/lib/helene/sdb/base/connection.rb +20 -0
  39. data/lib/helene/sdb/base/error.rb +20 -0
  40. data/lib/helene/sdb/base/hooks.rb +82 -0
  41. data/lib/helene/sdb/base/literal.rb +52 -0
  42. data/lib/helene/sdb/base/logging.rb +23 -0
  43. data/lib/helene/sdb/base/transactions.rb +53 -0
  44. data/lib/helene/sdb/base/type.rb +137 -0
  45. data/lib/helene/sdb/base/types.rb +123 -0
  46. data/lib/helene/sdb/base/validations.rb +256 -0
  47. data/lib/helene/sdb/cast.rb +114 -0
  48. data/lib/helene/sdb/connection.rb +36 -0
  49. data/lib/helene/sdb/error.rb +5 -0
  50. data/lib/helene/sdb/interface.rb +412 -0
  51. data/lib/helene/sdb/sentinel.rb +15 -0
  52. data/lib/helene/sleepcycle.rb +29 -0
  53. data/lib/helene/superhash.rb +297 -0
  54. data/lib/helene/util.rb +132 -0
  55. data/test/auth.rb +31 -0
  56. data/test/helper.rb +98 -0
  57. data/test/integration/begin.rb +0 -0
  58. data/test/integration/ensure.rb +8 -0
  59. data/test/integration/s3/bucket.rb +106 -0
  60. data/test/integration/sdb/associations.rb +45 -0
  61. data/test/integration/sdb/creating.rb +13 -0
  62. data/test/integration/sdb/emptiness.rb +56 -0
  63. data/test/integration/sdb/hooks.rb +19 -0
  64. data/test/integration/sdb/limits.rb +27 -0
  65. data/test/integration/sdb/saving.rb +21 -0
  66. data/test/integration/sdb/selecting.rb +39 -0
  67. data/test/integration/sdb/types.rb +31 -0
  68. data/test/integration/sdb/validations.rb +60 -0
  69. data/test/integration/setup.rb +27 -0
  70. data/test/integration/teardown.rb +21 -0
  71. data/test/loader.rb +39 -0
  72. 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