methodsolver 0.0.2 → 0.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 88d147d86dee794e8d6efa1c405fced0a0d94661
4
- data.tar.gz: 8fc6b465cbb619726fec383c511fc1251b6f08b1
3
+ metadata.gz: b6f2c0e313ebc463f001136e17e06df659e86933
4
+ data.tar.gz: 92bc53f31083ecdcbe0c8ae18e13e4820195c092
5
5
  SHA512:
6
- metadata.gz: f9f798884fa6b87d5c0564169151d6a330499c3f70b2a18b59b41cd06b861491bba74c7ef282e59c72c77c0e4ddc9d8751b282e495d434eb34a9ebbee8d32fbe
7
- data.tar.gz: b76b6cf03f299ef1813230cfced1008fe509988dcbfca685c4d855d37b7b8deeaba284f836fdec3976fdce48b3dffdf7a68a0bef69edaba470878dc63e166b76
6
+ metadata.gz: 6ca8fbed39d19eb7dc3256000674b408d01f9b7a45c1083b3e43c1a3d44bc0ecf5876e3a62a4c8fb6d5825033197f0ebc3b36dde241aac08faa160ef1e38904e
7
+ data.tar.gz: b8952babf725dec3a443d54c1da155c72fbcb261362fe10f11e58717c1143d86f8757fe8564371a9961f0c047cef0086bd073fb5b2d9f6c46e96397e43bdbf89
data/README.md CHANGED
@@ -10,6 +10,10 @@ solve { 'lettuce'.foo == 7 }
10
10
 
11
11
  Will find `#length` and `#size`
12
12
 
13
+ Use with caution and beware of side effects!
14
+
15
+ The solver attempts to executes the block with arbitrary methods found on the reciever. Append the symbol of dangerous methods to `Methodsolver::BLACKLIST` in order to blacklist them.
16
+
13
17
  ## Installation
14
18
 
15
19
  Clone this repo and run pry:
@@ -28,18 +32,6 @@ solve { 'lettuce'.foo == 7 }
28
32
 
29
33
  Please refer to `examples/solve.rb` (and the rspec tests) for more examples.
30
34
 
31
- ## Usage
32
-
33
- Use with caution!
34
-
35
- The solver attempts to executes the block with arbitrary methods found on the reciever. Beware of side effects. Append the symbol of dangerous methods to `Methodsolver::BLACKLIST` in order to blacklist them.
36
-
37
- ## Development
38
-
39
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
40
-
41
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
42
-
43
35
  ## Contributing
44
36
 
45
37
  Bug reports and pull requests are welcome on GitHub at https://github.com/akuhn/methodsolver.
@@ -1,3 +1,3 @@
1
1
  module Methodsolver
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/methodsolver.rb CHANGED
@@ -3,49 +3,76 @@ require 'method_source'
3
3
 
4
4
  module Methodsolver
5
5
 
6
- def self.call(&block)
6
+ def self.call(options = {}, &block)
7
7
  raise ArgumentError, 'no block given' unless block_given?
8
+
9
+ # Detect missing method, ie placeholder:
10
+
8
11
  begin
9
- Object.class_eval('def method_missing(name, *args); throw :method_missing, [self, name]; end')
10
- method_missing = catch :method_missing do block.call; nil end
12
+ Object.class_eval('def method_missing(name, *args); throw :undefined_method, [self, name]; end')
13
+ reciever, placeholder = catch :undefined_method do
14
+ block.call
15
+ raise ArgumentError, 'no missing method found'
16
+ end
11
17
  ensure
12
18
  Object.class_eval('remove_method :method_missing')
13
19
  end
14
- raise ArgumentError, 'no missing method found' unless method_missing
15
- object, message = method_missing
16
- found = methods_for(object).select do |each|
20
+
21
+ # Find methods that pass the block:
22
+
23
+ results = methods_for(reciever).select do |name|
24
+ method = reciever.method(name) rescue next
17
25
  begin
18
- object.class.class_eval("alias #{message.inspect} #{each.inspect}")
26
+ method.owner.class_eval("alias #{placeholder.inspect} #{name.inspect}")
19
27
  true === block.call
20
28
  rescue
21
29
  false
22
30
  ensure
23
- object.class.class_eval("remove_method #{message.inspect}")
31
+ method.owner.class_eval("remove_method #{placeholder.inspect}")
24
32
  end
25
33
  end
26
- return object, found
34
+
35
+ # Optionally return a hash with metadata:
36
+
37
+ if options[:metadata]
38
+ { reciever: reciever, placeholder: placeholder, results: results }
39
+ else
40
+ results
41
+ end
27
42
  end
28
43
 
29
- BLACKLIST = [:cycle]
44
+ private
45
+
46
+ BLACKLIST = [
47
+ :cycle,
48
+ ]
49
+ WHITELIST = [
50
+ :'!', :'!=', :'!~', :'<', :'<=', :'<=>', :'==', :'===', :'=~', :'>', :'>=',
51
+ :class, :eql?, :equal?, :hash, :instance_of?, :is_a?, :itself, :kind_of?,
52
+ :nil?, :respond_to?, :tap, :to_s,
53
+ ]
30
54
 
31
55
  def self.methods_for(object)
32
56
  object.class.ancestors
33
- .take_while { |a| Object != a }
34
- .flat_map { |a| a.instance_methods(all = false) }
35
- .concat(%w(
36
- ! != == !~ <=> === =~ class eql? equal?
37
- instance_of? is_a? kind_of? hash nil? to_s
38
- ))
39
- .map(&:to_sym)
57
+ .take_while { |cls| ![Class, Module, Object].member?(cls) }
58
+ .flat_map { |cls| cls.instance_methods(all = false) }
59
+ .concat(object.singleton_methods)
60
+ .reject { |name| name =~ /[=!]$/ }
61
+ .concat(WHITELIST)
62
+ .-(BLACKLIST)
40
63
  .uniq
41
- .- BLACKLIST
42
64
  end
43
65
 
44
66
  end
45
67
 
46
68
  def solve(&block)
47
- object, found = Methodsolver.call(&block)
48
- puts "Found #{found.count} methods for #{block.source.strip rescue 'source not available'}"
69
+ data = Methodsolver.call(metadata: true, &block)
70
+ object, found = data[:reciever], data[:results]
71
+ if block.respond_to? :method_source
72
+ puts "Found #{found.count} methods for #{block.method_source.strip}"
73
+ else
74
+ puts "Found #{found.count} methods for ##{data[:placeholder]}"
75
+ end
49
76
  found.map do |symbol|
50
77
  method = object.method(symbol)
51
78
  puts "- #{method.owner}\e[32m##{method.name}\e[0m"
data/methodsolver.gemspec CHANGED
@@ -16,6 +16,4 @@ Gem::Specification.new do |spec|
16
16
  spec.bindir = "exe"
17
17
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
18
  spec.require_paths = ["lib"]
19
-
20
- spec.add_dependency "method_source"
21
19
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: methodsolver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Kuhn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-07-20 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: method_source
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
11
+ date: 2015-07-21 00:00:00.000000000 Z
12
+ dependencies: []
27
13
  description:
28
14
  email:
29
15
  - akuhn@iam.unibe.ch