vex 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. data/Manifest +112 -0
  2. data/Rakefile +53 -0
  3. data/VERSION +1 -0
  4. data/config/README +2 -0
  5. data/config/dependencies.rb +10 -0
  6. data/config/gem.yml +7 -0
  7. data/init.rb +36 -0
  8. data/lib/nokogiri/nokogiri_ext.rb +96 -0
  9. data/lib/vex.rb +5 -0
  10. data/lib/vex/action_controller.rb +4 -0
  11. data/lib/vex/action_controller/verify_action.rb +97 -0
  12. data/lib/vex/action_controller/whitelisted_actions.rb +45 -0
  13. data/lib/vex/active_record.rb +3 -0
  14. data/lib/vex/active_record/__init__.rb +0 -0
  15. data/lib/vex/active_record/advisory_lock.rb +11 -0
  16. data/lib/vex/active_record/advisory_lock/mysql_adapter.rb +16 -0
  17. data/lib/vex/active_record/advisory_lock/sqlite_adapter.rb +78 -0
  18. data/lib/vex/active_record/belongs_to_many.rb +143 -0
  19. data/lib/vex/active_record/find_by_extension.rb +70 -0
  20. data/lib/vex/active_record/gem.rb +8 -0
  21. data/lib/vex/active_record/lite_table.rb +139 -0
  22. data/lib/vex/active_record/lite_view.rb +140 -0
  23. data/lib/vex/active_record/mass_load.rb +65 -0
  24. data/lib/vex/active_record/mysql_backup.rb +21 -0
  25. data/lib/vex/active_record/plugins/default_value_for/LICENSE.TXT +19 -0
  26. data/lib/vex/active_record/plugins/default_value_for/README.rdoc +421 -0
  27. data/lib/vex/active_record/plugins/default_value_for/Rakefile +6 -0
  28. data/lib/vex/active_record/plugins/default_value_for/init.rb +91 -0
  29. data/lib/vex/active_record/plugins/default_value_for/test.rb +279 -0
  30. data/lib/vex/active_record/plugins/default_value_for/test.sqlite3 +0 -0
  31. data/lib/vex/active_record/random_id.rb +56 -0
  32. data/lib/vex/active_record/resolver.rb +49 -0
  33. data/lib/vex/active_record/serialize_hash.rb +125 -0
  34. data/lib/vex/active_record/to_html.rb +53 -0
  35. data/lib/vex/active_record/validate.rb +76 -0
  36. data/lib/vex/active_record/validation_error_ext.rb +68 -0
  37. data/lib/vex/base.rb +2 -0
  38. data/lib/vex/base/app.rb +75 -0
  39. data/lib/vex/base/array/at_random.rb +17 -0
  40. data/lib/vex/base/array/cross.rb +26 -0
  41. data/lib/vex/base/array/each_batch.rb +32 -0
  42. data/lib/vex/base/array/parallel_map.rb +98 -0
  43. data/lib/vex/base/deprecation.rb +41 -0
  44. data/lib/vex/base/enumerable/deep.rb +95 -0
  45. data/lib/vex/base/enumerable/enumerable_ext.rb +59 -0
  46. data/lib/vex/base/enumerable/progress.rb +71 -0
  47. data/lib/vex/base/filesystem/fast_copy.rb +61 -0
  48. data/lib/vex/base/filesystem/grep.rb +34 -0
  49. data/lib/vex/base/filesystem/lock.rb +43 -0
  50. data/lib/vex/base/filesystem/lock.rb.test.lck +0 -0
  51. data/lib/vex/base/filesystem/lock.rb.test.pid +1 -0
  52. data/lib/vex/base/filesystem/make_dirs.rb +94 -0
  53. data/lib/vex/base/filesystem/parse_filename.rb +36 -0
  54. data/lib/vex/base/filesystem/tmp_file.rb +87 -0
  55. data/lib/vex/base/filesystem/write.rb +43 -0
  56. data/lib/vex/base/hash/compact.rb +38 -0
  57. data/lib/vex/base/hash/cross.rb +117 -0
  58. data/lib/vex/base/hash/easy_access.rb +141 -0
  59. data/lib/vex/base/hash/ensure_keys.rb +18 -0
  60. data/lib/vex/base/hash/extract.rb +71 -0
  61. data/lib/vex/base/hash/extras.rb +62 -0
  62. data/lib/vex/base/hash/inspect.rb +17 -0
  63. data/lib/vex/base/hash/simple_access_methods.rb +74 -0
  64. data/lib/vex/base/invalid_argument/invalid_argument.rb +97 -0
  65. data/lib/vex/base/local_conf.rb +35 -0
  66. data/lib/vex/base/net/http_ext.rb +227 -0
  67. data/lib/vex/base/net/socket_ext.rb +43 -0
  68. data/lib/vex/base/object/insp.rb +123 -0
  69. data/lib/vex/base/object/multiple_attributes.rb +58 -0
  70. data/lib/vex/base/object/singleton_methods.rb +23 -0
  71. data/lib/vex/base/object/with_benchmark.rb +110 -0
  72. data/lib/vex/base/range_array.rb +40 -0
  73. data/lib/vex/base/range_ext.rb +28 -0
  74. data/lib/vex/base/safe_token.rb +156 -0
  75. data/lib/vex/base/string/string_ext.rb +136 -0
  76. data/lib/vex/base/thread/deferred.rb +52 -0
  77. data/lib/vex/base/thread/sleep.rb +11 -0
  78. data/lib/vex/base/time/date_ext.rb +12 -0
  79. data/lib/vex/boot.rb +40 -0
  80. data/lib/vex/boot/array.rb +22 -0
  81. data/lib/vex/boot/blank.rb +41 -0
  82. data/lib/vex/boot/string.rb +60 -0
  83. data/migration/create_request_log.rb +28 -0
  84. data/r.rb +35 -0
  85. data/script/console +19 -0
  86. data/script/rebuild +7 -0
  87. data/tasks/echoe.rake +52 -0
  88. data/tasks/validate_db.rake +14 -0
  89. data/test/ar.rb +30 -0
  90. data/test/auto.rb +31 -0
  91. data/test/base-tests/local_conf.rb +25 -0
  92. data/test/base.rb +2 -0
  93. data/test/boot.rb +3 -0
  94. data/test/config/local.defaults.yml +4 -0
  95. data/test/config/local.yml +8 -0
  96. data/test/test.sqlite3 +0 -0
  97. data/test/test.sqlite3.Class#create.lck +0 -0
  98. data/test/test.sqlite3.Class#create.lck.lck +0 -0
  99. data/test/test.sqlite3.Class#create.lck.pid +1 -0
  100. data/test/test.sqlite3.Class#create.pid +1 -0
  101. data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck +0 -0
  102. data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.lck +0 -0
  103. data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.pid +1 -0
  104. data/test/test.sqlite3.LiteView.make.holders__view_dummy.pid +1 -0
  105. data/test/test.sqlite3.vex.lck +0 -0
  106. data/test/test_helper.rb +49 -0
  107. data/test/tmp/copy.dat +1 -0
  108. data/test/tmp/lock.sqlite3 +0 -0
  109. data/test/tmp/lock.sqlite3.etest.lck +0 -0
  110. data/test/tmp/lock.sqlite3.etest.pid +1 -0
  111. data/test/tmp/somedata.dat +61 -0
  112. data/vex.gemspec +49 -0
  113. data/vex.tmproj +186 -0
  114. metadata +305 -0
@@ -0,0 +1,35 @@
1
+ class LocalConf < Hash
2
+ include Hash::EasyAccess
3
+
4
+ def initialize(file)
5
+ r1 = load file.sub(/\.yml$/, ".defaults.yml")
6
+ r2 = load file, App.env
7
+
8
+ return if r1 || r2
9
+
10
+ raise Errno::ENOENT,
11
+ "Missing configuration file #{App.root}/config/#{file.sub(/\.yml$/, "")}{.defaults}.yml}"
12
+ end
13
+
14
+ private
15
+
16
+ def load(file, key = nil)
17
+ data = YAML::load_file("#{App.root}/config/#{file}")
18
+ data = data[key] if data && key
19
+ data.each { |k,v| update k.to_sym => v } if data
20
+ true
21
+ rescue Errno::ENOENT
22
+ false
23
+ end
24
+
25
+ def method_missing(sym, *args, &block)
26
+ return super unless args.empty? && !block_given? && sym.to_s =~ /(.*)\?/
27
+ !fetch($1.to_sym).blank?
28
+ rescue IndexError
29
+ false
30
+ end
31
+
32
+ def self.method_missing(sym, *args, &block)
33
+ App.local_conf.send sym, *args, &block
34
+ end
35
+ end if VEX_TEST == "base"
@@ -0,0 +1,227 @@
1
+ require "net/http"
2
+ require "net/https"
3
+
4
+ module Net::HTTPExt; end
5
+
6
+ Net.extend Net::HTTPExt
7
+
8
+ #
9
+ # This adds Net.get, Net.head, Net.post
10
+ module Net::HTTPExt
11
+ REDIRECTION_LIMIT = 10
12
+
13
+ DEFAULT_OPTIONS = {
14
+ :redirect => 10 # MAX # of redirection
15
+ }
16
+
17
+ # This is a combination of a string (for the response body) and
18
+ # of a "hash" for the response header
19
+ class Response < String
20
+ class Headers
21
+ attr :code, true
22
+
23
+ def initialize(response)
24
+ @headers = response.instance_variable_get "@header"
25
+ end
26
+
27
+ def method_missing(sym, *args, &block)
28
+ return super unless args.empty? && !block_given?
29
+ self[sym]
30
+ end
31
+
32
+ def [](key)
33
+ r = @headers[key.to_s.downcase.gsub("_", "-")]
34
+ raise "huh?" unless r.is_a?(Array)
35
+ r.length <= 1 ? r.first : r
36
+ end
37
+ end
38
+
39
+ attr :response
40
+ attr :headers
41
+
42
+ def code; Integer(response.code); end
43
+ def good?; code >= 200 && code < 300; end
44
+ def message; response.message; end
45
+
46
+ def initialize(response)
47
+ super(response.body) if response.body
48
+ @response, @headers = response, Headers.new(response)
49
+ end
50
+ end
51
+
52
+ # POST request
53
+ def post(url, body, opts = {})
54
+ http :post, url, body, opts
55
+ end
56
+
57
+ # HEAD request
58
+ def head(url, opts = {})
59
+ http :head, url, nil, opts
60
+ end
61
+
62
+ # GET request
63
+ def get(url, opts = {})
64
+ http :get, url, nil, opts
65
+ end
66
+
67
+ def exists?(url, opts = {})
68
+ r = Net.head(url, opts)
69
+ r.code >= 200 && r.code < 300
70
+ end
71
+
72
+ alias :exist? :exists?
73
+
74
+ HEADERS_KEY = :"net:http_ext:preprocessors:headers"
75
+
76
+ def headers
77
+ Thread.current[HEADERS_KEY] ||= {}
78
+ end
79
+
80
+ def headers=(h)
81
+ Thread.current[HEADERS_KEY] = h
82
+ end
83
+
84
+ def with_headers(scope, &block)
85
+ old = headers
86
+ self.headers = headers.dup.update scope
87
+ yield
88
+ ensure
89
+ self.headers = old
90
+ end
91
+
92
+ private
93
+
94
+ def adjust_request!(verb, path, h, body)
95
+ headers.each do |k,v|
96
+ k = k.to_s
97
+
98
+ if v.respond_to?(:call)
99
+ v.call(verb, path, h, body)
100
+ elsif v.nil?
101
+ h.delete k
102
+ h.delete k.to_sym
103
+ else
104
+ h[k] ||= v
105
+ end
106
+ end
107
+ end
108
+
109
+ def http(verb, url, body, opts, &block)
110
+ # -- timeout handling
111
+ if timeout = opts.delete(:timeout)
112
+ begin
113
+ return Timeout.timeout(timeout) { http(verb, url, body, opts, &block) }
114
+ rescue Timeout::Error
115
+ return nil
116
+ end
117
+ end
118
+
119
+ headers = DEFAULT_OPTIONS.dup.update(opts)
120
+ redirect = headers.delete :redirect
121
+
122
+ r = do_http verb, url, body, headers, redirect, &block
123
+ r.headers.code = r.code
124
+
125
+ verb != :head ? r : r.headers
126
+ end
127
+
128
+ # connects to a HTTP server, yields the URI and the HTTP connection
129
+ def do_http(verb, url, body, headers={}, redirect = nil, &block)
130
+ # -- connect to the server
131
+ uri = url.is_a?(URI) ? url : URI.parse(url)
132
+
133
+ connection = Net::HTTP.new(uri.host, uri.port)
134
+ connection.use_ssl = uri.scheme == "https"
135
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
136
+
137
+ invalid_argument!("Invalid URL", url) unless %w(https http).include?(uri.scheme)
138
+
139
+ # -- do whatever
140
+ connection.start do |c|
141
+ adjust_request! verb, uri.request_uri, headers, body
142
+
143
+ args = [ ]
144
+ args << "request_#{verb}"
145
+ args << uri.request_uri
146
+ args << body if verb == :post || verb == :put
147
+ args << headers
148
+
149
+ response = connection.send *args
150
+
151
+ if !response.is_a?(Net::HTTPRedirection) || !redirect
152
+ next Response.new(response)
153
+ end
154
+
155
+ raise "Reached maximum number of redirections" if redirect <= 0
156
+
157
+ do_http verb == :head ? :head : :get,
158
+ redirection_url(url, response['location']),
159
+ nil,
160
+ headers,
161
+ redirect - 1
162
+ end
163
+ ensure
164
+ connection.finish if connection && connection.started?
165
+ end
166
+
167
+ #
168
+ # fix non default responses. Magento does this, sometimes...
169
+ def redirection_url(uri, location)
170
+ return location if URI.parse(location).scheme rescue nil
171
+ raise "Cannot redirect to URI #{location}" unless uri.to_s =~ /^((.*?)\/\/(.*?)\/)/
172
+ $1 + location.gsub(/^\/+/, "")
173
+ end
174
+ end
175
+
176
+ module Net::HTTPExt::Etest
177
+ def test_w_google_w_redirection
178
+ return unless Socket.online?
179
+
180
+ google = Net.get("http://www.google.com")
181
+ assert google =~ /<title>Google/
182
+ assert google.headers["Content-Type"] =~ /text\/html/
183
+ assert google.headers.content_type =~ /text\/html/
184
+ end
185
+
186
+ def test_w_google_wo_redirection
187
+ return unless Socket.online?
188
+
189
+ google = Net.get("http://www.google.com", :redirect => false)
190
+ assert_equal(302 , google.code)
191
+ assert google.headers["Content-Type"] =~ /text\/html/
192
+ assert google.headers.content_type =~ /text\/html/
193
+ end
194
+
195
+ def test_w_google
196
+ return unless Socket.online?
197
+
198
+ assert Net.exists?("http://www.google.de")
199
+ assert Net.exist?("http://www.google.de")
200
+
201
+ google = Net.get("http://www.google.de")
202
+ assert google =~ /<title>Google/
203
+ assert google.headers["Content-Type"] =~ /text\/html/
204
+ assert google.headers.content_type =~ /text\/html/
205
+ end
206
+
207
+ def test_w_google_timeout
208
+ return unless Socket.online?
209
+
210
+ google = Net.get("http://www.google.de", :timeout => 0.01)
211
+ assert_equal(nil, google)
212
+ end
213
+
214
+ def test_w_google_adjusted_headers
215
+ return unless Socket.online?
216
+
217
+ Net.with_headers :x_abc => "Test ABC" do
218
+ assert_equal("Test ABC", Net.headers[:x_abc])
219
+ assert Net.exists?("http://www.google.de")
220
+ Net.with_headers :x_abc => nil do
221
+ assert_equal(nil, Net.headers[:x_abc])
222
+ end
223
+ assert_equal("Test ABC", Net.headers[:x_abc])
224
+ end
225
+ end
226
+ end if VEX_TEST == "base"
227
+
@@ -0,0 +1,43 @@
1
+ require 'socket'
2
+
3
+ #
4
+ # see http://coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/
5
+ #
6
+ class Socket
7
+ #
8
+ # Parameters:
9
+ #
10
+ # * when_talking_to: returns my IP when talking to that host.
11
+ # * when_talking_to: returns my IP when talking to that host.
12
+
13
+ # do_raise is mainly for test purposes
14
+ def self.local_ip(when_talking_to = nil)
15
+ when_talking_to ||= '64.233.187.99'
16
+ begin
17
+ orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
18
+
19
+ UDPSocket.open do |s|
20
+ s.connect when_talking_to, 1
21
+ s.addr.last
22
+ end
23
+ rescue
24
+ "127.0.0.1" # not connected to the funny wide web?
25
+ ensure
26
+ Socket.do_not_reverse_lookup = orig
27
+ end
28
+ end
29
+
30
+ def self.online?
31
+ local_ip != "127.0.0.1"
32
+ end
33
+ end
34
+
35
+ module Socket::Etest
36
+ def test_returns_127_locally
37
+ require 'ipaddr'
38
+ local_net = IPAddr.new("127.0.0.0/24")
39
+ %w(127.0.0.1 127.0.0.2 localhost).each do |ip|
40
+ assert(local_net.include?(IPAddr.new(Socket.local_ip(ip))))
41
+ end
42
+ end
43
+ end if VEX_TEST == "base"
@@ -0,0 +1,123 @@
1
+ #
2
+ # short inspect method on all objects.
3
+ #
4
+ # "abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop".insp
5
+ # -> "abcdefghijklmnopabcdefghijk..."
6
+ # Model.find(1).insp
7
+ # -> "<Model#1>"
8
+
9
+ class Object
10
+ def insp
11
+ body = "#{insp_body}"
12
+ body = ": #{body}" unless body.empty?
13
+ "#{insp_head}#{body}#{insp_close}"
14
+ end
15
+
16
+ private
17
+
18
+ def insp_head; "<#{self.class}@#{self.object_id}"; end
19
+ def insp_body; end
20
+ def insp_close; ">"; end
21
+ end
22
+
23
+ [ Numeric, TrueClass, FalseClass, NilClass, Symbol, Module ].each do |klass|
24
+ klass.send :alias_method, :insp, :inspect
25
+ end
26
+
27
+ class String
28
+ INSP_TRUNCATE_LEN = 30
29
+
30
+ def insp
31
+ return inspect unless length > INSP_TRUNCATE_LEN
32
+
33
+ l = INSP_TRUNCATE_LEN - 3
34
+ (self[0...l].to_s + "...").inspect
35
+ end
36
+ end
37
+
38
+ if defined?(ActiveRecord)
39
+ class ActiveRecord::Base
40
+ private
41
+
42
+ def insp_head; "<#{self.class}##{self.id}"; end
43
+ end
44
+ end
45
+
46
+ class Hash
47
+ def insp
48
+ self.class == Hash && instance_variables.empty? ? insp_body : super
49
+ end
50
+
51
+ private
52
+
53
+ INSP_TRUNCATE_LEN = 10
54
+
55
+ def insp_body
56
+ body = to_a.sort { |a,b|
57
+ a <=> b rescue a.to_s <=> b.to_s
58
+ }
59
+
60
+ if length > INSP_TRUNCATE_LEN
61
+ body = body[0...INSP_TRUNCATE_LEN]
62
+ more = ", ... (#{length - INSP_TRUNCATE_LEN} more)"
63
+ end
64
+
65
+ "{#{body.map { |k,v| "#{k.insp} => #{v.insp}"}.join(", ")}#{more}}"
66
+ end
67
+ end
68
+
69
+ class Array
70
+ def insp
71
+ self.class == Array && instance_variables.empty? ? insp_body : super
72
+ end
73
+
74
+ private
75
+
76
+ INSP_TRUNCATE_LEN = 20
77
+
78
+ def insp_body
79
+ if length > INSP_TRUNCATE_LEN
80
+ body = self[0...INSP_TRUNCATE_LEN]
81
+ more = ", ... (#{length - INSP_TRUNCATE_LEN} more)"
82
+ end
83
+
84
+ "[#{(body || self).map(&:insp).join(", ")}#{more}]"
85
+ end
86
+ end
87
+
88
+ module Insp; end
89
+
90
+ module Insp::Etest
91
+ def test_insp_array
92
+ assert_equal("[1, 2]", [1,2].insp)
93
+ assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ... (10 more)]", (1..30).to_a.insp)
94
+ end
95
+
96
+ def test_insp_hash
97
+ assert_equal("{}", {}.insp)
98
+
99
+ h = (1..30).to_a.inject({}) do |hash, id|
100
+ hash.update id => id*id
101
+ end
102
+ assert_equal "{1 => 1, 2 => 4, 3 => 9, 4 => 16, 5 => 25, 6 => 36, 7 => 49, 8 => 64, 9 => 81, 10 => 100, ... (20 more)}",
103
+ h.insp
104
+ end
105
+
106
+ def test_insp_string
107
+ s = "123"
108
+ assert_equal(s.insp, s.inspect)
109
+ s = (s * 100).insp
110
+ assert s.ends_with?("...\"")
111
+ assert s.length < 50
112
+ end
113
+
114
+ class X
115
+ def initialize
116
+ @x = "x"
117
+ end
118
+ end
119
+
120
+ def test_insp_obj
121
+ assert X.new.insp =~ /Insp::Etest::X/
122
+ end
123
+ end if VEX_TEST == "base"
@@ -0,0 +1,58 @@
1
+ class Module
2
+ module MultipleAttributes
3
+ def attributes(*args)
4
+ writable_flag = args.last
5
+ if writable_flag != true && writable_flag != false
6
+ writable_flag = false
7
+ else
8
+ args.pop
9
+ end
10
+
11
+ args.each do |arg|
12
+ attr arg, writable_flag
13
+ end
14
+ end
15
+ end
16
+
17
+ include MultipleAttributes
18
+ end
19
+
20
+ module Module::MultipleAttributes::Etest
21
+ class X
22
+ attributes :a
23
+ attributes :b, :c
24
+
25
+ attributes :d, :e, true
26
+
27
+ def initialize
28
+ @a = "a"
29
+ @b = "b"
30
+ @c = "c"
31
+ @d = "d"
32
+ @e = "e"
33
+ end
34
+ end
35
+
36
+ def test_ma
37
+ x = X.new
38
+ assert_equal %w(a b c d e), [ x.a, x.b, x.c, x.d, x.e ]
39
+
40
+ assert_raise(NoMethodError) {
41
+ x.a = 1
42
+ }
43
+
44
+ assert_raise(NoMethodError) {
45
+ x.b = 1
46
+ }
47
+
48
+ assert_raise(NoMethodError) {
49
+ x.c = 1
50
+ }
51
+
52
+ x.d = 1
53
+ x.e = 2
54
+
55
+ assert_equal 1, x.d
56
+ assert_equal 2, x.e
57
+ end
58
+ end if VEX_TEST == "base"