object_oculus 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +32 -0
- data/README.rdoc +102 -0
- data/lib/object_oculus/classic.rb +29 -0
- data/lib/object_oculus/dummy_out.rb +10 -0
- data/lib/object_oculus/frozen_section.rb +29 -0
- data/lib/object_oculus/method_finder.rb +146 -0
- data/lib/object_oculus/methods.rb +80 -0
- data/lib/object_oculus/version.rb +4 -0
- data/lib/object_oculus.rb +37 -0
- data/object_oculus.gemspec +22 -0
- data/spec/classic_spec.rb +10 -0
- data/spec/frozen_section_spec.rb +23 -0
- data/spec/method_finder_spec.rb +13 -0
- data/spec/methods_spec.rb +60 -0
- data/spec/spec_helper.rb +7 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 13c75e4eff1e0a849c8a2162097995baa400503a112fb2c41c167a1ab91d194a
|
4
|
+
data.tar.gz: da3566f45634c1718bf235c95c58ce9762e4f1c0770206a460e09c11efa79fc2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2489cd1b412bd62a5880de14a4452d816bef3a2e4693b482a8e1ffaae6db969854d52a027396c7d641028b9bd2174f7ea73136877a7f34d3a2b29dd0c6d6cdde
|
7
|
+
data.tar.gz: 3ed6a105543d05053b0ca088824e4b83ceffbd1785694260992dd17cb45b9e84cbedc1d4409cbc7daf2873beb2895d3e2bd15a9e42954b2a64fe6f555630e2cb
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
object_oculus (1.2.3)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.5.1)
|
10
|
+
rspec (3.13.0)
|
11
|
+
rspec-core (~> 3.13.0)
|
12
|
+
rspec-expectations (~> 3.13.0)
|
13
|
+
rspec-mocks (~> 3.13.0)
|
14
|
+
rspec-core (3.13.0)
|
15
|
+
rspec-support (~> 3.13.0)
|
16
|
+
rspec-expectations (3.13.0)
|
17
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
18
|
+
rspec-support (~> 3.13.0)
|
19
|
+
rspec-mocks (3.13.0)
|
20
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
21
|
+
rspec-support (~> 3.13.0)
|
22
|
+
rspec-support (3.13.1)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
object_oculus!
|
29
|
+
rspec (~> 3.0)
|
30
|
+
|
31
|
+
BUNDLED WITH
|
32
|
+
2.5.6
|
data/README.rdoc
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
= object\_oculus
|
2
|
+
|
3
|
+
This is a fork of Dr. Nic's excellent little what_methods utility, updated a bit to expand
|
4
|
+
functionality and bring syntax a bit more in line with the Ruby status quo. It's actually been
|
5
|
+
batted around the internet for a while, with rough etchings dating to 2002. So this is my shot at
|
6
|
+
it.
|
7
|
+
|
8
|
+
<b>Dr. Nic says</b> (or is heard from echoes traversing the sands of time)<b>:</b>
|
9
|
+
|
10
|
+
This is from Dr. Nic. See http://drnicwilliams.com/2006/10/12/my-irbrc-for-consoleirb/
|
11
|
+
|
12
|
+
Ever asked: "if I have an object, what method can I call on it to get that result?"
|
13
|
+
|
14
|
+
See if this suits your console cravings:
|
15
|
+
|
16
|
+
> 3.45.what_equals 3
|
17
|
+
3.45.to_i == 3
|
18
|
+
3.45.to_int == 3
|
19
|
+
3.45.floor == 3
|
20
|
+
3.45.round == 3
|
21
|
+
3.45.truncate == 3
|
22
|
+
=> {:to_i=>3, :to_int=>3, :floor=>3, :round=>3, :truncate=>3}
|
23
|
+
|
24
|
+
> 3.45.what_equals 4
|
25
|
+
3.45.ceil == 4
|
26
|
+
=> {:ceil=>4}
|
27
|
+
|
28
|
+
> 3.55.what_equals 4
|
29
|
+
3.55.ceil == 4
|
30
|
+
3.55.round == 4
|
31
|
+
=> {:ceil=>4, :round=>4}
|
32
|
+
|
33
|
+
> 3.45.what_equals /\n/
|
34
|
+
3.45.psych_to_yaml == "--- 3.45\n...\n"
|
35
|
+
3.45.to_yaml == "--- 3.45\n...\n"
|
36
|
+
3.45.pretty_inspect == "3.45\n"
|
37
|
+
=> {:psych_to_yaml=>"--- 3.45\n...\n", :to_yaml=>"--- 3.45\n...\n", :pretty_inspect=>"3.45\n"}
|
38
|
+
|
39
|
+
> 3.what_equals 4, 1
|
40
|
+
3 + 1 == 4
|
41
|
+
=> {:+=>4}
|
42
|
+
|
43
|
+
> 3.given(1).what_equals 4
|
44
|
+
3 + 1 == 4
|
45
|
+
|
46
|
+
Just what you need in the console.
|
47
|
+
|
48
|
+
Notice the last example: you can pass parameters after the desired result. whats_up will tell you
|
49
|
+
what method will return the desired result if you pass those parameters to it.
|
50
|
+
|
51
|
+
<b>Bryan says:</b>
|
52
|
+
|
53
|
+
This modest little update retains the original +what?+ method, but that was from the halcyon days of
|
54
|
+
2006, before the Ruby community had a rough consensus that +?+ methods should be returning a true or
|
55
|
+
false value (or at least something useable as such). I've aliased that method as +what_equals+.
|
56
|
+
|
57
|
+
You can add arguments by either supplying additional arguments after the expected result or by using
|
58
|
+
the +given+ method. So the following two queries are equivalent:
|
59
|
+
|
60
|
+
5.given(1).what_equals 6
|
61
|
+
5.what_equals 6, 1
|
62
|
+
|
63
|
+
Note also the addition of helpers like +whats_exactly+, which will only find exact matches, and
|
64
|
+
+what_matches+, which will match a regular expression:
|
65
|
+
|
66
|
+
> 5.whats_exactly 5.0
|
67
|
+
5.to_f == 5.0
|
68
|
+
=> {:to_f=>5.0}
|
69
|
+
|
70
|
+
> "hello".what_matches /^\d$/
|
71
|
+
"hello".length == 5
|
72
|
+
"hello".size == 5
|
73
|
+
"hello".bytesize == 5
|
74
|
+
"hello".to_i == 0
|
75
|
+
"hello".hex == 0
|
76
|
+
"hello".oct == 0
|
77
|
+
=> {:length=>5, :size=>5, :bytesize=>5, :to_i=>0, :hex=>0, :oct=>0}
|
78
|
+
|
79
|
+
And if you just want to know everything, I've added +what_works_with+ that lists the results of all
|
80
|
+
current methods and +whats_not_blank_with+ that ignores any false, falsy or empty values:
|
81
|
+
|
82
|
+
> "hello".what_works_with 2
|
83
|
+
"hello" <=> 2 == nil
|
84
|
+
"hello" == 2 == false
|
85
|
+
"hello" === 2 == false
|
86
|
+
"hello".eql?(2) == false
|
87
|
+
"hello" * 2 == "hellohello"
|
88
|
+
"hello" % 2 == "hello"
|
89
|
+
"hello"[2] == "l"
|
90
|
+
"hello" =~ 2 == nil
|
91
|
+
"hello".upto(2) == #<Enumerator: "hello":upto(2)>
|
92
|
+
# ...
|
93
|
+
|
94
|
+
> "hello".given(2).whats_not_blank
|
95
|
+
"hello" * 2 == "hellohello"
|
96
|
+
"hello" % 2 == "hello"
|
97
|
+
"hello"[2] == "l"
|
98
|
+
"hello".upto(2) == #<Enumerator: "hello":upto(2)>
|
99
|
+
# ...
|
100
|
+
|
101
|
+
In line with the original +what_methods+ gem, you can <tt>require "object_oculus/classic"</tt> to enable
|
102
|
+
aliases like +what?+, +matches?+, +exactly?+, +works?+ and +not_blank?+.
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "object_oculus"
|
2
|
+
|
3
|
+
module ObjectOculus
|
4
|
+
# This module contains the original +what?+ method, as well as some aliases for newer methods. In
|
5
|
+
# line with the current expectation that a Ruby method ending in +?+ returns a true or false value
|
6
|
+
# (or at least something truthy or falsy), I've decided not to make +what?+ and it's brethren the
|
7
|
+
# default. You can include them by:
|
8
|
+
#
|
9
|
+
# require "object_oculus/classic"
|
10
|
+
#
|
11
|
+
# or, if object_oculus is already loaded:
|
12
|
+
#
|
13
|
+
# ObjectOculus::Classic # which triggers object_oculus/classic to autoload
|
14
|
+
module Classic
|
15
|
+
alias :what? :what_equals
|
16
|
+
alias :exactly? :whats_exactly
|
17
|
+
alias :matches? :what_matches
|
18
|
+
alias :works? :what_works_with
|
19
|
+
alias :not_blank? :whats_not_blank_with
|
20
|
+
end
|
21
|
+
|
22
|
+
class MethodFinder
|
23
|
+
@@blacklist += Classic.instance_methods
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Object # :nodoc:
|
28
|
+
include ObjectOculus::Classic
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ObjectOculus
|
2
|
+
# A classic designed to allow variables to be stored along with a frozen object.
|
3
|
+
#
|
4
|
+
# Frozen objects can't have new instance variables added directly, so this prevents object_oculus
|
5
|
+
# methods from being locked out of inspecting anything frozen. This proxy class should be
|
6
|
+
# initialized automatically if object_oculus detects that the object it's to inspect is frozen.
|
7
|
+
class FrozenSection
|
8
|
+
# The frozen object
|
9
|
+
attr_reader :object
|
10
|
+
|
11
|
+
# Creates a new FrozenSection object from the provided +object+ and a list of instance variables
|
12
|
+
# to store
|
13
|
+
def initialize(object, vars = {})
|
14
|
+
@object = object
|
15
|
+
vars.each do |key, value|
|
16
|
+
instance_variable_set "@#{key}", value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# An override of Methods#show_methods that passes the object stored in <tt>@object</tt> instead of
|
23
|
+
# +self+
|
24
|
+
def show_methods(expected_result, opts = {}, *args, &block) # :doc:
|
25
|
+
@args = args unless args.empty?
|
26
|
+
MethodFinder.show(@object, expected_result, opts, *@args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module ObjectOculus
|
2
|
+
# A singleton class used to iterate over the methods of an object trying to match any returned
|
3
|
+
# values with an expected result. ny matches will then be pretty printed to the console.
|
4
|
+
class MethodFinder
|
5
|
+
# A list of symbols indicated which methods to always ignore
|
6
|
+
@@blacklist = %w(daemonize debug debugger display ed emacs exec exit! fork mate nano sleep
|
7
|
+
stub stub! stub_chain syscall system unstub unstub! vi vim).map(&:to_sym)
|
8
|
+
@@blacklist += Methods.instance_methods
|
9
|
+
|
10
|
+
# A list of symbols for infix operators for which Ruby has special syntax
|
11
|
+
@@infixes = %w(+ - * / % ** == != =~ !~ !=~ > < >= <= <=> === & | ^ << >>).map(&:to_sym)
|
12
|
+
|
13
|
+
# A list of symbols for prefix operators for which Ruby has special syntax
|
14
|
+
@@prefixes = %w(+@ -@ ~ !).map(&:to_sym)
|
15
|
+
|
16
|
+
class << self
|
17
|
+
# Builds a lambda for checking against the provided +expected_result+ given a hash of options.
|
18
|
+
# Given the value of a method, the result of this lambda will determine whether that method
|
19
|
+
# and value are included in the output of a object_oculus method.
|
20
|
+
#
|
21
|
+
# ==== Options
|
22
|
+
#
|
23
|
+
# * <tt>:exclude_blank</tt> - Exclude blank values
|
24
|
+
# * <tt>:force_exact</tt> - Force values to be exactly equal
|
25
|
+
# * <tt>:force_regex</tt> - Coerce the +expected_result+ into a regular expression for pattern
|
26
|
+
# matching
|
27
|
+
# * <tt>:show_all</tt> - Show the results of all methods
|
28
|
+
def build_check_lambda(expected_result, opts = {})
|
29
|
+
if opts[:force_regex]
|
30
|
+
expected_result = Regexp.new(expected_result.to_s) unless expected_result.is_a?(Regexp)
|
31
|
+
->(value) { expected_result === value.to_s }
|
32
|
+
elsif expected_result.is_a?(Regexp) && !opts[:force_exact]
|
33
|
+
->(value) { expected_result === value.to_s }
|
34
|
+
elsif opts[:force_exact]
|
35
|
+
->(value) { expected_result.eql?(value) }
|
36
|
+
elsif opts[:show_all]
|
37
|
+
if opts[:exclude_blank]
|
38
|
+
->(value) { !value.nil? && !(value.respond_to?(:empty?) && value.empty?) }
|
39
|
+
else
|
40
|
+
->(value) { true }
|
41
|
+
end
|
42
|
+
else
|
43
|
+
->(value) { expected_result == value }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Find all methods on +an_object+ which, when called with +args+ return +expected_result+
|
48
|
+
def find(an_object, expected_result, opts = {}, *args, &block)
|
49
|
+
check_result = build_check_lambda(expected_result, opts)
|
50
|
+
|
51
|
+
# Prevent any writing to the terminal
|
52
|
+
stdout, stderr = $stdout, $stderr
|
53
|
+
unless $stdout.is_a?(DummyOut)
|
54
|
+
$stdout = $stderr = DummyOut.new
|
55
|
+
restore_std = true
|
56
|
+
end
|
57
|
+
|
58
|
+
# Use only methods with valid arity that aren't blacklisted
|
59
|
+
methods = an_object.methods
|
60
|
+
methods.select! { |n| an_object.method(n).arity <= args.size && !@@blacklist.include?(n) }
|
61
|
+
|
62
|
+
# Collect all methods equaling the expected result
|
63
|
+
results = methods.inject({}) do |res, name|
|
64
|
+
stdout.print ""
|
65
|
+
begin
|
66
|
+
value = an_object.clone.method(name).call(*args, &block)
|
67
|
+
res[name] = value if check_result.call(value)
|
68
|
+
rescue
|
69
|
+
end
|
70
|
+
res
|
71
|
+
end
|
72
|
+
|
73
|
+
# Restore printing to the terminal
|
74
|
+
$stdout, $stderr = stdout, stderr if restore_std
|
75
|
+
results
|
76
|
+
end
|
77
|
+
|
78
|
+
# Pretty prints the results of #find
|
79
|
+
def show(an_object, expected_result, opts = {}, *args, &block)
|
80
|
+
opts = {
|
81
|
+
exclude_blank: false,
|
82
|
+
force_exact: false,
|
83
|
+
force_regex: false,
|
84
|
+
show_all: false
|
85
|
+
}.merge(opts)
|
86
|
+
|
87
|
+
found = find(an_object, expected_result, opts, *args, &block)
|
88
|
+
prettified = prettify_found(an_object, found, *args)
|
89
|
+
max_length = prettified.map { |k, v| k.length }.max
|
90
|
+
|
91
|
+
prettified.each { |k, v| puts "#{k.ljust max_length} == #{v}" }
|
92
|
+
|
93
|
+
found
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
# Pretty prints a method depending on whether it's an operator, has arguments, is array/hash
|
99
|
+
# syntax, etc.
|
100
|
+
def prettify_found(an_object, found, *args)
|
101
|
+
args = args.map { |a| a.inspect }.join(", ")
|
102
|
+
pretty_object = truncate_inspect(an_object, to: 40)
|
103
|
+
|
104
|
+
found.map do |key, value|
|
105
|
+
pretty_key = if @@infixes.include?(key)
|
106
|
+
"#{pretty_object} #{key} #{args}"
|
107
|
+
elsif @@prefixes.include?(key)
|
108
|
+
"#{key.to_s.sub /\@$/, ""}#{pretty_object}"
|
109
|
+
elsif key == :[]
|
110
|
+
"#{pretty_object}[#{args}]"
|
111
|
+
elsif args != ""
|
112
|
+
"#{pretty_object}.#{key}(#{args})"
|
113
|
+
else
|
114
|
+
"#{pretty_object}.#{key}"
|
115
|
+
end
|
116
|
+
|
117
|
+
pretty_value =
|
118
|
+
begin
|
119
|
+
truncate_inspect(value, to: 120)
|
120
|
+
rescue => ex
|
121
|
+
ex.class
|
122
|
+
end
|
123
|
+
|
124
|
+
[pretty_key, pretty_value]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Inspects an object and returns a string representation, truncating it to length in the
|
129
|
+
# provided <tt>to:</tt> argument if necessary
|
130
|
+
def truncate_inspect(object, opts = {})
|
131
|
+
max_length = opts[:to] || 80
|
132
|
+
full = object.inspect
|
133
|
+
|
134
|
+
if full.length > max_length
|
135
|
+
available_length = max_length - 5 # to account for the " ... "
|
136
|
+
left_cutoff = available_length * 2 / 3
|
137
|
+
right_cutoff = available_length - left_cutoff - 1
|
138
|
+
|
139
|
+
"#{full[0..left_cutoff]} ... #{full[-right_cutoff..-1]}"
|
140
|
+
else
|
141
|
+
full
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module ObjectOculus
|
2
|
+
# The methods added to all objects by object_oculus
|
3
|
+
module Methods
|
4
|
+
# Provides a list of arguments that will be used when trying to find matching methods.
|
5
|
+
#
|
6
|
+
# 5.given(1).what_equals 6
|
7
|
+
# # => 5 + 1 == 6
|
8
|
+
def given(*args)
|
9
|
+
if frozen?
|
10
|
+
FrozenSection.new self, args: args
|
11
|
+
else
|
12
|
+
@args = args
|
13
|
+
self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Outputs a list of methods and their values that equal an +expected_result+, allowing for some
|
18
|
+
# coercion (e.g. <tt>5 == 5.0</tt>)
|
19
|
+
def what_equals(expected_result, *args, &block)
|
20
|
+
show_methods expected_result, {}, *args, &block
|
21
|
+
end
|
22
|
+
|
23
|
+
# Outputs a list of methods and their values that exactly equal an +expected_result+
|
24
|
+
def whats_exactly(expected_result, *args, &block)
|
25
|
+
show_methods expected_result, { force_exact: true }, *args, &block
|
26
|
+
end
|
27
|
+
|
28
|
+
# Outputs a list of methods and their values that match an +expected_result+, which is coerced
|
29
|
+
# into a regular expression if it's not already one
|
30
|
+
def what_matches(expected_result, *args, &block)
|
31
|
+
show_methods expected_result, { force_regex: true }, *args, &block
|
32
|
+
end
|
33
|
+
|
34
|
+
# Outputs a list of all methods and their values
|
35
|
+
def what_works_with(*args, &block)
|
36
|
+
show_methods nil, { show_all: true }, *args, &block
|
37
|
+
end
|
38
|
+
alias :what_works :what_works_with
|
39
|
+
|
40
|
+
# Outputs a list of all methods and their values, provided they are not blank (nil, false,
|
41
|
+
# undefined, empty)
|
42
|
+
def whats_not_blank_with(*args, &block)
|
43
|
+
show_methods nil, { show_all: true, exclude_blank: true }, *args, &block
|
44
|
+
end
|
45
|
+
alias :whats_not_blank :whats_not_blank_with
|
46
|
+
|
47
|
+
# The list of all methods unique to an object
|
48
|
+
def unique_methods
|
49
|
+
methods - self.class.methods
|
50
|
+
end
|
51
|
+
|
52
|
+
# Lists all methods available to the object by ancestor
|
53
|
+
def methods_by_ancestor
|
54
|
+
([self] + self.class.ancestors).inject({}) do |result, object|
|
55
|
+
result[object] = object.unique_methods
|
56
|
+
result
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Make sure cloning doesn't cause anything to fail via type errors
|
61
|
+
alias_method :__clone__, :clone
|
62
|
+
|
63
|
+
# Adds in a type error check to the default Object#clone method to prevent any interruptions while
|
64
|
+
# checking methods. If a TypeError is encountered, +self+ is returned
|
65
|
+
def clone
|
66
|
+
__clone__
|
67
|
+
rescue TypeError
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Called by all of the +what_+ methods, this tells MethodFinder to output the result for any methods
|
74
|
+
# matching an +expected_result+ for the #given arguments
|
75
|
+
def show_methods(expected_result, opts = {}, *args, &block) # :doc:
|
76
|
+
@args = args unless args.empty?
|
77
|
+
MethodFinder.show(self, expected_result, opts, *@args, &block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# object_oculus enables you to determine what methods can be called on an object that return a given
|
2
|
+
# value
|
3
|
+
#
|
4
|
+
# === Some credits from Dr. Nic
|
5
|
+
#
|
6
|
+
# Code this version is based on: {Andrew
|
7
|
+
# Birkett's}[http://www.nobugs.org/developer/ruby/method_finder.html]
|
8
|
+
#
|
9
|
+
# Improvements from Why's blog entry:
|
10
|
+
# * +what?+ - Why
|
11
|
+
# * <tt>@@blacklist</tt> - llasram
|
12
|
+
# * +clone+ alias - Daniel Schierbeck
|
13
|
+
# * <tt>$stdout</tt> redirect - Why
|
14
|
+
#
|
15
|
+
# {Improvements from Nikolas Coukouma}[http://atrustheotaku.livejournal.com/339449.html]
|
16
|
+
# * Varargs and block support
|
17
|
+
# * Improved catching
|
18
|
+
# * Redirecting <tt>$stdout</tt> and <tt>$stderr</tt> (independently of Why)
|
19
|
+
#
|
20
|
+
# {A version posted in 2002 by Steven
|
21
|
+
# Grady}[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/32844]
|
22
|
+
#
|
23
|
+
# David Tran's versions:
|
24
|
+
# * Simple[http://www.doublegifts.com/pub/ruby/methodfinder.rb.html]
|
25
|
+
# * {Checks permutations of arguments}[http://www.doublegifts.com/pub/ruby/methodfinder2.rb.html]
|
26
|
+
module ObjectOculus
|
27
|
+
autoload :Classic, "object_oculus/classic"
|
28
|
+
autoload :DummyOut, "object_oculus/dummy_out"
|
29
|
+
autoload :FrozenSection, "object_oculus/frozen_section"
|
30
|
+
autoload :MethodFinder, "object_oculus/method_finder"
|
31
|
+
autoload :Methods, "object_oculus/methods"
|
32
|
+
autoload :VERSION, "object_oculus/version"
|
33
|
+
end
|
34
|
+
|
35
|
+
class Object # :nodoc:
|
36
|
+
include ObjectOculus::Methods
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "object_oculus/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "object_oculus"
|
6
|
+
s.authors = ["Jason Cheong-Kee-You", "Bryan McKelvey", "Dr Nic Williams"]
|
7
|
+
s.email = "j.chunky@gmail.com"
|
8
|
+
s.homepage = "https://github.com/jchunky/object_oculus"
|
9
|
+
s.licenses = ['MIT']
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.version = ObjectOculus::VERSION
|
12
|
+
s.summary = "Rapidly explore an object's API in 'irb'"
|
13
|
+
s.description = <<~DESCRIPTION
|
14
|
+
ObjectOculus is a ruby tool for viewing all of an object's methods and seeing what those
|
15
|
+
methods return. ObjectOculus can be used in 'irb' to rapidly explore an object's API.
|
16
|
+
DESCRIPTION
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec", "~> 3.0"
|
22
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
RSpec.describe "ObjectOculus::Classic" do
|
2
|
+
it "should not have any classic methods without Classic loaded" do
|
3
|
+
expect("hello").not_to respond_to(:what?)
|
4
|
+
end
|
5
|
+
|
6
|
+
it "should have classic methods with Classic loaded" do
|
7
|
+
require "object_oculus/classic"
|
8
|
+
expect("hello").to respond_to(:what?)
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
RSpec.describe FrozenSection do
|
2
|
+
describe "initialization" do
|
3
|
+
before(:each) do
|
4
|
+
@number = 2
|
5
|
+
@string = "hello"
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should not occur given an unfrozen object" do
|
9
|
+
expect(@string.given(1)).to be_a(String)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should occur given an integer" do
|
13
|
+
expect(@number.given(1)).to be_a(FrozenSection)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should occur given a frozen object" do
|
17
|
+
@number.freeze
|
18
|
+
@string.freeze
|
19
|
+
expect(@number.given(1)).to be_a(FrozenSection)
|
20
|
+
expect(@string.given(1)).to be_a(FrozenSection)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
RSpec.describe MethodFinder do
|
2
|
+
describe "blacklist" do
|
3
|
+
it "should contain classic methods" do
|
4
|
+
expect(MethodFinder.class_variable_get(:@@blacklist)).to include(:what?)
|
5
|
+
expect(MethodFinder.class_variable_get(:@@blacklist)).to include(:works?)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should contain newer methods" do
|
9
|
+
expect(MethodFinder.class_variable_get(:@@blacklist)).to include(:what_equals)
|
10
|
+
expect(MethodFinder.class_variable_get(:@@blacklist)).to include(:what_works)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
RSpec.describe Methods do
|
2
|
+
before(:all) do
|
3
|
+
@stderr, @stdout = $stderr, $stdout
|
4
|
+
$stderr = $stdout = DummyOut.new
|
5
|
+
end
|
6
|
+
|
7
|
+
after(:all) do
|
8
|
+
$stderr, $stdout = @stderr, @stdout
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "what_equals" do
|
12
|
+
it "should find the correct method without arguments" do
|
13
|
+
expect("hello ".what_equals("hello")).to have_key(:rstrip)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should find the correct method with arguments" do
|
17
|
+
expect("hello".what_equals("e", 1)).to have_key(:[])
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should find the correct method with arguments using given" do
|
21
|
+
expect("hello".given(1).what_equals("e")).to have_key(:[])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "what_matches" do
|
26
|
+
it "should find the correct method given a regular expression" do
|
27
|
+
expect(5.what_matches(/5/)).to have_key(:to_s)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should find the correct method by converting an arbitrary object to a regular expression" do
|
31
|
+
expect(5.what_matches(5)).to have_key(:to_s)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "whats_exactly" do
|
36
|
+
it "should fail to match inexact matches that would succeed with == type coercion" do
|
37
|
+
expect(5.whats_exactly(5.0)).not_to have_key(:to_i)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should succeed for exact matches" do
|
41
|
+
expect(5.whats_exactly(5.0)).to have_key(:to_f)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "whats_not_blank" do
|
46
|
+
it "should include only non-blank values" do
|
47
|
+
expect(5.whats_not_blank.select { |n| !n || n.empty? }).to be_empty
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "what_works" do
|
52
|
+
it "should produce all results found with whats_not_blank" do
|
53
|
+
works = 5.what_works
|
54
|
+
|
55
|
+
5.whats_not_blank.keys.each do |key|
|
56
|
+
expect(works).to have_key(key)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: object_oculus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jason Cheong-Kee-You
|
8
|
+
- Bryan McKelvey
|
9
|
+
- Dr Nic Williams
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2024-03-02 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - "~>"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - "~>"
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '3.0'
|
29
|
+
description: |
|
30
|
+
ObjectOculus is a ruby tool for viewing all of an object's methods and seeing what those
|
31
|
+
methods return. ObjectOculus can be used in 'irb' to rapidly explore an object's API.
|
32
|
+
email: j.chunky@gmail.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- ".gitignore"
|
38
|
+
- ".rspec"
|
39
|
+
- Gemfile
|
40
|
+
- Gemfile.lock
|
41
|
+
- README.rdoc
|
42
|
+
- lib/object_oculus.rb
|
43
|
+
- lib/object_oculus/classic.rb
|
44
|
+
- lib/object_oculus/dummy_out.rb
|
45
|
+
- lib/object_oculus/frozen_section.rb
|
46
|
+
- lib/object_oculus/method_finder.rb
|
47
|
+
- lib/object_oculus/methods.rb
|
48
|
+
- lib/object_oculus/version.rb
|
49
|
+
- object_oculus.gemspec
|
50
|
+
- spec/classic_spec.rb
|
51
|
+
- spec/frozen_section_spec.rb
|
52
|
+
- spec/method_finder_spec.rb
|
53
|
+
- spec/methods_spec.rb
|
54
|
+
- spec/spec_helper.rb
|
55
|
+
homepage: https://github.com/jchunky/object_oculus
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubygems_version: 3.5.6
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Rapidly explore an object's API in 'irb'
|
78
|
+
test_files: []
|