-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change implementation from prepend
to UnboundMethod
#1
Conversation
Pull Request Test Coverage Report for Build 15
💛 - Coveralls |
@_memery_module.module_eval do | ||
define_method(method_name) do |*args, &block| | ||
return super(*args, &block) if block | ||
define_method(method_name) do |*args, &block| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be conviment way to obtain source of original method in pry
or irb
Memery allows it with $ method_name -s
in pry or method(:method_name).super_method.source
in irb which is good
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be conviment way to obtain source of original method in pry or irb
Then there should be specs for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that viewing the source code of memoized method from pry
/irb
is very important, but OK, it can be an argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, $ method_name -s
doesn't work in Pry, but I hope that some day it will get fixed.
A.instance_method(:x).super_method.source
technique does work, though, so we might want to just add that spec. I don't see much harm in having some extra ancestors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
irb(main):002:0> def foo
irb(main):003:1> p :bar
irb(main):004:1> end
=> :foo
irb(main):005:0> method(:foo).source
NoMethodError: undefined method `source' for #<Method: main.foo>
from (irb):5
from /home/alex/.rbenv/versions/2.4.4/bin/irb:11:in `<main>'
What are you talking about?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A.instance_method(:x).super_method.source
works everywhere in case you required method_source
gem.
But that's just an example, the idea is, with current implementation it is possible to get the actual method's source code using Ruby, and with this implementation it becomes impossible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. This MR is just offer, proof of concept, showcase of alternative way. If you think that getting source from Ruby (pry
) is more important than a lot of Memery
in ancestors
in case of inheritance (and maybe some other unpleasant consequences, about which I don't remember or don't know) — you can just close this MR. And in the future, if some obvious shortcomings of the prepend
approach will be revealed — you and others will know about another not bad (in my opinion) approach, and apply it, or create a fork with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, $ method_name -s doesn't work in Pry, but I hope that some day it will get fixed.
Just a ref to issue: pry/pry#1756
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this implementation you can show the source of original method by moving (stepping) into method from memery
and calling $ original_method
from method body.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, but you can't do method(:x).super_method.source
as stated in Readme.
`prepend` pollutes `Module#ancestors`: ```ruby module Foo end class Bar prepend Foo end class Baz < Bar prepend Foo end Baz.ancestors # => [Foo, Baz, Foo, Bar, Object, Kernel, BasicObject] ```
0d62f66
to
30cbebb
Compare
Cool, closing for now then. The ability to get the source code of the original method was kept in mind when I was building this gem, and it does not rely on |
It would be good to refer to issue in |
We have a code in commercial project with Spec added. Maybe you can review your decision. |
I often use the |
OK. I've fixed our case with |
The bad case with # .test.rb
# frozen_string_literal: true
require 'pry-byebug'
require_relative 'lib/memery'
module A
include Memery
memoize def foo
'source'
end
end
module B
include Memery
include A
memoize def foo
"Get this #{super}!"
end
end
class C
include B
end
c = C.new
binding.pry
puts c.foo > ruby .test.rb
From: /home/alex/Projects/ruby/memery/.test.rb @ line 31 :
26:
27: c = C.new
28:
29: binding.pry
30:
=> 31: puts c.foo
pry: main > c.foo
=> "Get this source!"
pry: main > show-source c.foo
From: /home/alex/Projects/ruby/memery/lib/memery.rb @ line 55:
Owner: #<Module:0x000055d0fa6ab460>
Visibility: public
Number of lines: 17
define_method(method_name) do |*args, &block|
if block || (condition && !instance_exec(&condition))
return super(*args, &block)
end
key = "#{method_name}_#{mod_id}"
store = (@_memery_memoized_values ||= {})[key] ||= {}
if store.key?(args) && (ttl.nil? || Memery.monotonic_clock <= store[args][:time] + ttl)
return store[args][:result]
end
result = super(*args)
@_memery_memoized_values[key][args] = { result: result, time: Memery.monotonic_clock }
result
end
pry: main > show-source -s c.foo
From: /home/alex/Projects/ruby/memery/lib/memery.rb @ line 55:
Owner: #<Module:0x000055d0fa6ab460>
Visibility: public
Number of lines: 17
define_method(method_name) do |*args, &block|
if block || (condition && !instance_exec(&condition))
return super(*args, &block)
end
key = "#{method_name}_#{mod_id}"
store = (@_memery_memoized_values ||= {})[key] ||= {}
if store.key?(args) && (ttl.nil? || Memery.monotonic_clock <= store[args][:time] + ttl)
return store[args][:result]
end
result = super(*args)
@_memery_memoized_values[key][args] = { result: result, time: Memery.monotonic_clock }
result
end
pry: main > show-source -ss c.foo
From: /home/alex/Projects/ruby/memery/lib/memery.rb @ line 55:
Owner: #<Module:0x000055d0fa6abd98>
Visibility: public
Number of lines: 17
define_method(method_name) do |*args, &block|
if block || (condition && !instance_exec(&condition))
return super(*args, &block)
end
key = "#{method_name}_#{mod_id}"
store = (@_memery_memoized_values ||= {})[key] ||= {}
if store.key?(args) && (ttl.nil? || Memery.monotonic_clock <= store[args][:time] + ttl)
return store[args][:result]
end
result = super(*args)
@_memery_memoized_values[key][args] = { result: result, time: Memery.monotonic_clock }
result
end
pry: main > show-source -sss c.foo
From: /home/alex/Projects/ruby/memery/lib/memery.rb @ line 55:
Owner: #<Module:0x000055d0fa6abd98>
Visibility: public
Number of lines: 17
define_method(method_name) do |*args, &block|
if block || (condition && !instance_exec(&condition))
return super(*args, &block)
end
key = "#{method_name}_#{mod_id}"
store = (@_memery_memoized_values ||= {})[key] ||= {}
if store.key?(args) && (ttl.nil? || Memery.monotonic_clock <= store[args][:time] + ttl)
return store[args][:result]
end
result = super(*args)
@_memery_memoized_values[key][args] = { result: result, time: Memery.monotonic_clock }
result
end
pry: main > show-source -ssss c.foo
Error: Couldn't locate a definition for c.foo |
I've updated the branch if you'll be interested. (but PR is not updated somewhy) Also, with the example ( pry: main > c.method(:foo).owner.memoized_methods[:foo].source
=> " memoize def foo\n \"Get this \#{super}!\"\n end\n"
pry: main > c.method(:foo).super_method.owner.memoized_methods[:foo].source
=> " memoize def foo\n 'source'\n end\n" |
And another issue:
I can create a literally issue, but this PR is resolving them all. |
prepend
pollutesModule#ancestors
:Also, two modules with included Memery can broke the source of super-method.
And
define_method
withUnboundMethod
is possible now.