I am trying Pry for main code REPL editor.
I discovered this is very close to what I was looking for, but I don't know well about how to use it. I want to know how to add/modify/remove each method (or any other members) to/from a class.
When I tried this,
➜ ~ pry
[1] pry(main)> class AAA
[1] pry(main)* def bbb
[1] pry(main)* "ccc"
[1] pry(main)* end
[1] pry(main)* end
=> nil
[2] pry(main)> cd AAA
[3] pry(AAA):1> ls
AAA#methods: bbb
locals: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_
[4] pry(AAA):1> def xxx
[4] pry(AAA):1* "yyy"
[4] pry(AAA):1* end
=> nil
[5] pry(AAA):1> def xxx
[5] pry(AAA):1* "zzz"
[5] pry(AAA):1* end
=> nil
[6] pry(AAA):1> cd ..
[7] pry(main)> Pry.WrappedModule(AAA).source
=> "class AAA\n def bbb\n \"ccc\"\n end\nend\ndef xxx\n \"yyy\"\nend\ndef xxx\n \"zzz\"\nend\n"
[8] pry(main)> AAA.new.xxx
=> "zzz"
[9] pry(main)>
It worked well as I expected. But The source code contains duplicated definition of xxx method. If I want to erase older one (or both), how can I do that? Also, if I want to remove existing method (or any other member) without exchanging to a new one, how can I do that?
P.S. I am doing this mainly to edit, store and restore class source code between memory and disk. (a kind of image based persistent)
I found the answer. Use undef command.
[11] pry(main)> cd AAA
[13] pry(AAA):1> ls
AAA#methods: bbb xxx
locals: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_
[14] pry(AAA):1> undef xxx
=> nil
[15] pry(AAA):1> ls
AAA#methods: bbb
locals: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_
[16] pry(AAA):1> cd ..
[17] pry(main)> Pry.WrappedModule(AAA).source
=> "class AAA\n def bbb\n \"ccc\"\n end\nend\n"
[18] pry(main)>
Related
This piece of ruby code returns [1,1] but I expect to get just [1]. If I put the same text and jsonpath expression through http://jsonpath.com then I get [1]. Is this a bug in the 'jsonpath' gem?
require 'jsonpath'
string = <<-HERE_DOC
[
{"processId":1,"process":"XX"},
{"processId":2,"process":"YY"}
]
HERE_DOC
jsonpath = "$..[?(#.process=='XX')].processId"
path = JsonPath.new(jsonpath)
result = path.on(string)
puts "result: #{result}"
It seems that the problem is the extra point, in your jsonpath expression without this works similar in the two behaviours, you only need to go down one step:
[1] pry(main)> require 'jsonpath'
=> true
[2] pry(main)> jsonpath = "$.[?(#.process=='XX')].processId"
=> "$.[?(#.process=='XX')].processId"
[3] pry(main)> path = JsonPath.new(jsonpath)
=> #<JsonPath:0x00007f8c5bf42f10
#opts={},
#path=["$", "[?(#.process=='XX')]", "['processId']"]>
[4] pry(main)> string = <<-HERE_DOC
[4] pry(main)* [
[4] pry(main)* {"processId":1,"process":"XX"},
[4] pry(main)* {"processId":2,"process":"YY"}
[4] pry(main)* ]
[4] pry(main)* HERE_DOC
=> "[\n {\"processId\":1,\"process\":\"XX\"},\n {\"processId\":2,\"process\":\"YY\"}\n]\n"
[5] pry(main)> result = path.on(string)
=> [1]
I'm having two similar hashes. The first one looks like:
{'1'=>
{'ab'=>{'a'=>1, 'b'=>4},
{'bc'=>{'b'=>2, 'c'=>1},
...
}
The second one is pretty similar:
{'1'=>
{'ab'=>{'v'=>1},
{'bc'=>{'v'=>2},
...
}
I'd like to merge these like:
{'1'=>
{'ab'=>{'a'=>1, 'b'=>4, 'v'=>1},
{'bc'=>{'b'=>2, 'c'=>1, 'v'=>2},
...
}
What is the best way to do that?
For these simple case:
h1.merge(h2) do |_, v1, v2|
v1.merge(v2) { |_, v1, v2| v1.merge(v2) }
end
#⇒ {"1"=>{"ab"=>{"a"=>1, "b"=>4, "v"=>1},
# "bc"=>{"b"=>2, "c"=>1, "v"=>2}}}
Also note that what you have posted as an input are not valid ruby objects.
Try Hash#deep_merge from ActiveSupport. https://apidock.com/rails/Hash/deep_merge
If you don't want to depend on active_support gem or not willing to monkey-patch core classes, you can just copy the algorithm from the AS and adapt to your needs.
# File activesupport/lib/active_support/core_ext/hash/deep_merge.rb, line 21
def deep_merge!(other_hash, &block)
other_hash.each_pair do |current_key, other_value|
this_value = self[current_key]
self[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
this_value.deep_merge(other_value, &block)
else
if block_given? && key?(current_key)
block.call(current_key, this_value, other_value)
else
other_value
end
end
end
self
end
UPDATE:
I'm not sure why the answer was downvoted. Here is deep_merge in action:
[10] pry(main)> a = {'1'=>
[10] pry(main)* {'ab'=>{'a'=>1, 'b'=>4},
[10] pry(main)* 'bc'=>{'b'=>2, 'c'=>1}}
[10] pry(main)* };
[11] pry(main)>
[12] pry(main)> b = {'1'=>
[12] pry(main)* {'ab'=>{'v'=>1},
[12] pry(main)* 'bc'=>{'v'=>2}}
[12] pry(main)* };
[13] pry(main)>
[14] pry(main)> a.deep_merge(b)
=> {"1"=>{"ab"=>{"a"=>1, "b"=>4, "v"=>1}, "bc"=>{"b"=>2, "c"=>1, "v"=>2}}}
[15] pry(main)>
Exactly what OP needs.
I have e.g. r = "\t" and a = "thisisabigbad\wolf"
How can I prevent ruby from auto escaping my string and also count the \ at the same time?
a.count r #=> this should return 2 instead of 0
I wish to do a.count and receive 2
You can use single quotes:
[17] pry(main)> r = '\t'
=> "\\t"
[18] pry(main)> r.size
=> 2
[20] pry(main)> a = 'thisisabigbad\wolf'
=> "thisisabigbad\\wolf"
[21] pry(main)> a.size
=> 18
While working through http://docs.basho.com/riak/latest/dev/taste-of-riak/querying-ruby
I noticed what I can't store Time object in riak for some reason.
[3] pry(main)> client = Riak::Client.new(:protocol => "pbc", :pb_port => 8087, :host => "192.168.145.34")
=> #<Riak::Client [#<Node 192.168.145.34:8098:8087>]>
[4] pry(main)>
[5] pry(main)>
[6] pry(main)> tt = client.bucket('test')
=> #<Riak::Bucket {test}>
[7] pry(main)> v = tt.new("ttt")
=> #<Riak::RObject {test,ttt} [#<Riak::RContent [application/json]:nil>]>
[8] pry(main)> v.data = 1
=> 1
[9] pry(main)> v.store
=> #<Riak::RObject {test,ttt} [#<Riak::RContent [application/json]:1>]>
[10] pry(main)> v.data = Time.now
=> 2014-06-22 11:34:01 +0400
[11] pry(main)> v.store
SystemStackError: stack level too deep
from /home/maus/.gem/ruby/1.9.1/gems/pry-0.10.0/lib/pry/pry_instance.rb:353
After that I discovered what it's the case for user defined classes too:
[16] pry(main)> class Tst
[16] pry(main)* def initialize(x)
[16] pry(main)* #x = x
[16] pry(main)* end
[16] pry(main)* end
=> nil
[17] pry(main)> t111 = Tst.new(111)
=> #<Tst:0x9b13f4c #x=111>
[18] pry(main)> v.data = t111
=> #<Tst:0x9b13f4c #x=111>
[19] pry(main)> v.store
SystemStackError: stack level too deep
from /home/maus/.gem/ruby/1.9.1/gems/pry-0.10.0/lib/pry/pry_instance.rb:353
[20] pry(main)>
[21] pry(main)> v.data = [1,2,3]
=> [1, 2, 3]
[22] pry(main)> v.store
=> #<Riak::RObject {test,test_key} [#<Riak::RContent [application/json]:[1, 2, 3]>]>
Looks like something is terribly wrong with my install. But how to investigate it? I'm using riak-1.3.2 and ruby 1.9.3p194 with the following versions of gems:
i18n-0.6.9
builder-3.2.2
beefcake-0.3.7
multi_json-1.10.1
innertube-1.0.2
riak-client-1.4.4.1
The only place in the store method code path were I see the value being use is in BeefcakeProtobuffsBackend.ObjectMethods::dump_object which instantiates an RpbContent with :value => maybe_encode(robject.raw_data), so this would appear to be an issue with serializing the custom data.
RContent.raw_data calls Serializers::serialize
def serialize(content_type, content)
serializer_for(content_type).dump(content)
end
Serialize only understands a very few content types:
Serializers['text/plain'] = TextPlain
Serializers['application/json'] = ApplicationJSON
Serializers['application/x-ruby-marshal'] = ::Marshal
The default for content_type is application/json, whose dump method is:
def dump(object)
object.to_json(Riak.json_options)
end
Check that v.raw_data returns the value you expect, and if not, try setting v.content_type='text/plain'
For your custom class, make sure it has a to_json or to_s method that returns a string, and select the appropriate content_type.
I know that pry allows you to "cd" into other scopes.
pry(main)> cd Object
pry(Object)> ls
constants:
ARGF Encoding GC NIL
ArgumentError EncodingError Gem NilClass
ARGV Enumerable Hash Noexec
Array Enumerator IndexError NoMemoryError
...
But is there any way to move the interactive session into a block thats passed to a method?
pry(main)> cd some_instance.some_method do |some_argument|
pry(block)> ls
some_argument some_other_vars_available_within_block
pry(block)> end
result_of_block
pry(main)>
If possible, this would be exceedingly helpful. I've tried getting binding.pry to work myself in this fashion, without some luck, but I wanted to make sure I'm going down the right path before I continue.
Not sure i understand you fully, but you can try this, for example:
(master ✘)✹✭ ᐅ pry
[1] pry(main)> def hello(&block)
| Object.new.instance_exec(&block)
| end
=> nil
[2] pry(main)> block_binding = nil
=> nil
[3] pry(main)> hello { |some_argument = "testing"| u = 20; block_binding = binding }
=> #<Binding:0x007fdd33b1f680>
[4] pry(main)> cd block_binding
[5] pry(#<Object>):1> ls
locals: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_ _super block_binding some_argument u
[6] pry(#<Object>):1> some_argument
=> "testing"
[7] pry(#<Object>):1> u
=> 20
[8] pry(#<Object>):1> self
=> #<Object:0x007fdd33b1f888>
[9] pry(#<Object>):1>
Actually it turns out that nesting pry works beautifully. Kudos to the pry team.
Once I got my little binding.pry issue out of the way (my fault entirely).
Nesting pry: (note the 2 exit statements needed)
Hershwild:~ jstillwell$ pry
[1] pry(main)> binding.pry
[1] pry(main)> exit
=> nil
[2] pry(main)> exit
Hershwild:~ jstillwell$
Bringing forth pry from within a block:
Hershwild:~ jstillwell$ pry
[1] pry(main)> def test
[1] pry(main)* yield true
[1] pry(main)* end
=> nil
[2] pry(main)> test do |inside|
[2] pry(main)* binding.pry
[2] pry(main)* end
# after that end statement, pry resumes inside the block
[1] pry(main)> inside
=> true
[2] pry(main)> exit
=> nil
[3] pry(main)> exit
Hershwild:~ jstillwell$