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.
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