vex 0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|