vex 0.2
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/Manifest +112 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/config/README +2 -0
- data/config/dependencies.rb +10 -0
- data/config/gem.yml +7 -0
- data/init.rb +36 -0
- data/lib/nokogiri/nokogiri_ext.rb +96 -0
- data/lib/vex.rb +5 -0
- data/lib/vex/action_controller.rb +4 -0
- data/lib/vex/action_controller/verify_action.rb +97 -0
- data/lib/vex/action_controller/whitelisted_actions.rb +45 -0
- data/lib/vex/active_record.rb +3 -0
- data/lib/vex/active_record/__init__.rb +0 -0
- data/lib/vex/active_record/advisory_lock.rb +11 -0
- data/lib/vex/active_record/advisory_lock/mysql_adapter.rb +16 -0
- data/lib/vex/active_record/advisory_lock/sqlite_adapter.rb +78 -0
- data/lib/vex/active_record/belongs_to_many.rb +143 -0
- data/lib/vex/active_record/find_by_extension.rb +70 -0
- data/lib/vex/active_record/gem.rb +8 -0
- data/lib/vex/active_record/lite_table.rb +139 -0
- data/lib/vex/active_record/lite_view.rb +140 -0
- data/lib/vex/active_record/mass_load.rb +65 -0
- data/lib/vex/active_record/mysql_backup.rb +21 -0
- data/lib/vex/active_record/plugins/default_value_for/LICENSE.TXT +19 -0
- data/lib/vex/active_record/plugins/default_value_for/README.rdoc +421 -0
- data/lib/vex/active_record/plugins/default_value_for/Rakefile +6 -0
- data/lib/vex/active_record/plugins/default_value_for/init.rb +91 -0
- data/lib/vex/active_record/plugins/default_value_for/test.rb +279 -0
- data/lib/vex/active_record/plugins/default_value_for/test.sqlite3 +0 -0
- data/lib/vex/active_record/random_id.rb +56 -0
- data/lib/vex/active_record/resolver.rb +49 -0
- data/lib/vex/active_record/serialize_hash.rb +125 -0
- data/lib/vex/active_record/to_html.rb +53 -0
- data/lib/vex/active_record/validate.rb +76 -0
- data/lib/vex/active_record/validation_error_ext.rb +68 -0
- data/lib/vex/base.rb +2 -0
- data/lib/vex/base/app.rb +75 -0
- data/lib/vex/base/array/at_random.rb +17 -0
- data/lib/vex/base/array/cross.rb +26 -0
- data/lib/vex/base/array/each_batch.rb +32 -0
- data/lib/vex/base/array/parallel_map.rb +98 -0
- data/lib/vex/base/deprecation.rb +41 -0
- data/lib/vex/base/enumerable/deep.rb +95 -0
- data/lib/vex/base/enumerable/enumerable_ext.rb +59 -0
- data/lib/vex/base/enumerable/progress.rb +71 -0
- data/lib/vex/base/filesystem/fast_copy.rb +61 -0
- data/lib/vex/base/filesystem/grep.rb +34 -0
- data/lib/vex/base/filesystem/lock.rb +43 -0
- data/lib/vex/base/filesystem/lock.rb.test.lck +0 -0
- data/lib/vex/base/filesystem/lock.rb.test.pid +1 -0
- data/lib/vex/base/filesystem/make_dirs.rb +94 -0
- data/lib/vex/base/filesystem/parse_filename.rb +36 -0
- data/lib/vex/base/filesystem/tmp_file.rb +87 -0
- data/lib/vex/base/filesystem/write.rb +43 -0
- data/lib/vex/base/hash/compact.rb +38 -0
- data/lib/vex/base/hash/cross.rb +117 -0
- data/lib/vex/base/hash/easy_access.rb +141 -0
- data/lib/vex/base/hash/ensure_keys.rb +18 -0
- data/lib/vex/base/hash/extract.rb +71 -0
- data/lib/vex/base/hash/extras.rb +62 -0
- data/lib/vex/base/hash/inspect.rb +17 -0
- data/lib/vex/base/hash/simple_access_methods.rb +74 -0
- data/lib/vex/base/invalid_argument/invalid_argument.rb +97 -0
- data/lib/vex/base/local_conf.rb +35 -0
- data/lib/vex/base/net/http_ext.rb +227 -0
- data/lib/vex/base/net/socket_ext.rb +43 -0
- data/lib/vex/base/object/insp.rb +123 -0
- data/lib/vex/base/object/multiple_attributes.rb +58 -0
- data/lib/vex/base/object/singleton_methods.rb +23 -0
- data/lib/vex/base/object/with_benchmark.rb +110 -0
- data/lib/vex/base/range_array.rb +40 -0
- data/lib/vex/base/range_ext.rb +28 -0
- data/lib/vex/base/safe_token.rb +156 -0
- data/lib/vex/base/string/string_ext.rb +136 -0
- data/lib/vex/base/thread/deferred.rb +52 -0
- data/lib/vex/base/thread/sleep.rb +11 -0
- data/lib/vex/base/time/date_ext.rb +12 -0
- data/lib/vex/boot.rb +40 -0
- data/lib/vex/boot/array.rb +22 -0
- data/lib/vex/boot/blank.rb +41 -0
- data/lib/vex/boot/string.rb +60 -0
- data/migration/create_request_log.rb +28 -0
- data/r.rb +35 -0
- data/script/console +19 -0
- data/script/rebuild +7 -0
- data/tasks/echoe.rake +52 -0
- data/tasks/validate_db.rake +14 -0
- data/test/ar.rb +30 -0
- data/test/auto.rb +31 -0
- data/test/base-tests/local_conf.rb +25 -0
- data/test/base.rb +2 -0
- data/test/boot.rb +3 -0
- data/test/config/local.defaults.yml +4 -0
- data/test/config/local.yml +8 -0
- data/test/test.sqlite3 +0 -0
- data/test/test.sqlite3.Class#create.lck +0 -0
- data/test/test.sqlite3.Class#create.lck.lck +0 -0
- data/test/test.sqlite3.Class#create.lck.pid +1 -0
- data/test/test.sqlite3.Class#create.pid +1 -0
- data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck +0 -0
- data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.lck +0 -0
- data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.pid +1 -0
- data/test/test.sqlite3.LiteView.make.holders__view_dummy.pid +1 -0
- data/test/test.sqlite3.vex.lck +0 -0
- data/test/test_helper.rb +49 -0
- data/test/tmp/copy.dat +1 -0
- data/test/tmp/lock.sqlite3 +0 -0
- data/test/tmp/lock.sqlite3.etest.lck +0 -0
- data/test/tmp/lock.sqlite3.etest.pid +1 -0
- data/test/tmp/somedata.dat +61 -0
- data/vex.gemspec +49 -0
- data/vex.tmproj +186 -0
- 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"
|