object_oculus 1.2.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.
- 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: []
|