What happens to the object I assign to $stdout in Ruby? [closed] - ruby

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
EDIT: Don't bother reading this question, I just can't delete it. It's based on broken code and there's (almost) nothing to learn here.
I am redirecting console output in my Ruby program and although it works perfectly there is one thing I'm curious about:
Here's my code
capture = StringIO.new
$stdout = capture
puts "Hello World"
It looks like even though I'm assigning my capture object to $stdout, $stdout contains a new and different object after the assignment, but at least the type is correct.
In other words:
$stdout.to_s # => #<IO:0x2584b30>
capture = StringIO.new
$stdout = capture
$stdout.to_s # => #<StringIO:0x4fda948>
capture.to_s # => #<StringIO:0x4e3b220>
Subsequently $stdout.string contains "Hello World", but capture.string is empty.
Is there something happening behind the scenes or am I missing something here?
EDIT: This might be specific to certain versions only. I'm using Ruby 2.0.0-p247 on Windows 8.1

It works as expected.
>> capture = StringIO.new
=> #<StringIO:0x00000001ea8c00>
>> $stdout = capture
>> $stdout.to_s
>> capture.to_s
Above two line does not print anything because $stdout is now disconnected from terminal.
So I used $stderr.puts in following lines (can also use STDOUT.puts as Stefan commented):
>> $stderr.puts $stdout.to_s
#<StringIO:0x00000001ea8c00>
>> $stderr.puts capture.to_s
#<StringIO:0x00000001ea8c00>
$stdout.to_s, capture.to_s give me same result.
I used ruby 1.9.3. (Same for 2.0.0)

Are you sure there is no other manipulation of $stdout or capturehappening in between?
For me, output looks different. Both capture and $stdout are the same object and subsequently answer to string with the same response (ruby 1.9.2):
require 'stringio'
$stdout.to_s # => #<IO:0x2584b30>
capture = StringIO.new
$stdout = capture
puts $stdout.to_s # => #<StringIO:0x89a38c0>
puts capture.to_s # => #<StringIO:0x89a38c0>
puts "redirected"
$stderr.puts $stdout.string # => '#<StringIO:0x89a38c0>\n#<StringIO:0x89a38c0>\nredirected'
$stderr.puts capture.string # => '#<StringIO:0x89a38c0>\n#<StringIO:0x89a38c0>\nredirected'

Although this question was the result of overlooking a change to the value of $stdout, Ruby does have the ability to override assignment to global vars in this way, at least in the C api, using hooked variables.
$stdout actually does make use of this to check whether the new value is appropriate (it checks whether the new value responds to write) and raises an exception if it doesn’t.
If you really wanted (you don’t) you could create an extension that defines a global variable that automatically stores a different object than the value assigned, perhaps by called dup on it and using that instead:
#include "ruby.h"
VALUE foo;
static void foo_setter(VALUE val, ID id, VALUE *var){
VALUE dup_val = rb_funcall(val, rb_intern("dup"), 0);
*var = dup_val;
}
void Init_hooked() {
rb_define_hooked_variable("$foo", &foo, 0, foo_setter);
}
You could then use it like:
2.0.0-p247 :001 > require './ext/hooked'
=> true
2.0.0-p247 :002 > s = Object.new
=> #<Object:0x00000100b20560>
2.0.0-p247 :003 > $foo = s
=> #<Object:0x00000100b20560>
2.0.0-p247 :004 > s.to_s
=> "#<Object:0x00000100b20560>"
2.0.0-p247 :005 > $foo.to_s
=> "#<Object:0x00000100b3bea0>"
2.0.0-p247 :006 > s == $foo
=> false
Of course this is very similar to simply creating a setter method in a class that dups the vale and stores that, which you can do in plain Ruby:
def foo=(new_foo)
#foo = new_foo.dup
end
Since using global variables is generally bad design, it seems reasonable that this isn’t possible in Ruby for globals.

Related

Garbage Base64 decoded string [duplicate]

This question already has answers here:
p vs puts in Ruby
(8 answers)
Closed 3 years ago.
Could somebody explain me, why there are two various outputs?
CODE IN IRB(Interactive ruby shell):
irb(main):001:0> require 'base64'
=> true
irb(main):002:0> cookie = "YXNkZmctLTBEAiAvi95NGgcgk1W0pyUKXFEo6IuEvdxhmrfLqNVpskDv5AIgVn8wfIWf0y41cb%2Bx9I0ah%2F4BIIeRJ54nX2qGcxw567Y%3D"
=> "YXNkZmctLTBEAiAvi95NGgcgk1W0pyUKXFEo6IuEvdxhmrfLqNVpskDv5AIgVn8wfIWf0y41cb%2Bx9I0ah%2F4BIIeRJ54nX2qGcxw567Y%3D"
irb(main):003:0> decoded_cookie = Base64.urlsafe_decode64(URI.decode(cookie))
=> "asdfg--0D\x02 /\x8B\xDEM\x1A\a \x93U\xB4\xA7%\n\\Q(\xE8\x8B\x84\xBD\xDCa\x9A\xB7\xCB\xA8\xD5i\xB2#\xEF\xE4\x02 V\x7F0|\x85\x9F\xD3.5q\xBF\xB1\xF4\x8D\x1A\x87\xFE\x01 \x87\x91'\x9E'_j\x86s\x1C9\xEB\xB6"
Code from Linux terminal:
asd#asd:~# ruby script.rb
asdfg--0D /��M� �U��%
\Q(苄��a��˨�i�#�� V0|���.5q������ ��'�'_j�s9�
Script:
require 'base64'
require 'ecdsa'
cookie = "YXNkZmctLTBEAiAvi95NGgcgk1W0pyUKXFEo6IuEvdxhmrfLqNVpskDv5AIgVn8wfIWf0y41cb%2Bx9I0ah%2F4BIIeRJ54nX2qGcxw567Y%3D"
def decode_cookie(cookie)
decoded_cookie = Base64.urlsafe_decode64(URI.decode(cookie))
end
puts (decode_cookie(cookie))
How can i get the same output in terminal?
I need the output:
"asdfg--0D\x02 /\x8B\xDEM\x1A\a \x93U\xB4\xA7%\n\Q(\xE8\x8B\x84\xBD\xDCa\x9A\xB7\xCB\xA8\xD5i\xB2#\xEF\xE4\x02 V\x7F0|\x85\x9F\xD3.5q\xBF\xB1\xF4\x8D\x1A\x87\xFE\x01 \x87\x91'\x9E'_j\x86s\x1C9\xEB\xB6"
In Linux terminal.
A string like "\x8B" is a representation of character, not the literal \x8B. Ruby uses such representation if it's missing the font to display the character or if it messes with whitespacing (for example "\n" is a newline and not \ followed by a n).
The reason you get another output in irb is because you don't print the string using puts (like you do in your script). Simply calling decoded_cookie will return the string representation, not the actual content.
You can display the actual content by simply printing it to an output.
require 'base64'
cookie = "YXNkZmctLTBEAiAvi95NGgcgk1W0pyUKXFEo6IuEvdxhmrfLqNVpskDv5AIgVn8wfIWf0y41cb%2Bx9I0ah%2F4BIIeRJ54nX2qGcxw567Y%3D"
decoded_cookie = Base64.urlsafe_decode64(URI.decode(cookie))
puts decoded_cookie
# asdfg--0D /��M �U��%
# \Q(苄��a��˨�i�#�� V0|���.5q����� ��'�'_j�s9�
#=> nil
You can find more info about the "\xnn" representation here.
If you'd like the script to display the string representation use p instead of puts, or use puts decoded_cookie.inspect.

ruby object to_s gives unexpected output

What is the correct way to view the output of the puts statements below? My apologies for such a simple question.... Im a little rusty on ruby. github repo
require 'active_support'
require 'active_support/core_ext'
require 'indicators'
my_data = Indicators::Data.new(Securities::Stock.new(:symbol => 'AAPL', :start_date => '2012-08-25', :end_date => '2012-08-30').output)
puts my_data.to_s #expected to see Open,High,Low,Close for AAPL
temp=my_data.calc(:type => :sma, :params => 3)
puts temp.to_s #expected to see an RSI value for each data point from the data above
Maybe check out the awesome_print gem.
It provides the .ai method which can be called on anything.
An example:
my_obj = { a: "b" }
my_obj_as_string = my_obj.ai
puts my_obj_as_string
# ... this will print
# {
# :a => "b"
# }
# except the result is colored.
You can shorten all this into a single step with ap(my_obj).
There's also a way to return objects as HTML. It's the my_obj.ai(html: true) option.
Just use .inspect method instead of .to_s if you want to see internal properties of objects.

Ruby access propteries with dot-notation

I'm trying to build a class that will basically be used as a data structure for storing values/nested values. I want there to be two methods, get and set, that accept a dot-notated path to recursively set or get variables.
For example:
bag = ParamBag.new
bag.get('foo.bar') # => nil
bag.set('foo.bar', 'baz')
bag.get('foo.bar') # => 'baz'
The get method could also take a default return value if the value doesn't exist:
bag.get('foo.baz', false) # => false
I could also initialize a new ParamBag with a Hash.
How would I manage this in Ruby? I've done this in other languages, but in order to set a recursive path, I would take the value by reference, but I'm not sure how I'd do it in Ruby.
This was a fun exercise but still falls under the "you probably should not do this" category.
To accomplish what you want, OpenStruct can be used with some slight modifications.
class ParamBag < OpenStruct
def method_missing(name, *args, &block)
if super.nil?
modifiable[new_ostruct_member(name)] = ParamBag.new
end
end
end
This class will let you chain however many method calls together you would like and set any number of parameters.
Tested with Ruby 2.2.1
2.2.1 :023 > p = ParamBag.new
=> #<ParamBag>
2.2.1 :024 > p.foo
=> #<ParamBag>
2.2.1 :025 > p.foo.bar
=> #<ParamBag>
2.2.1 :026 > p.foo.bar = {}
=> {}
2.2.1 :027 > p.foo.bar
=> {}
2.2.1 :028 > p.foo.bar = 'abc'
=> "abc"
Basically, take your get and set methods away and call methods like you would normally.
I do not advise you actually do this, I would instead suggest you use OpenStruct by itself to acheive some flexibility without going too crazy. If you find yourself needing to chain a ton of methods and have them never fail, maybe take a step backwards and ask "is this really the right way to approach this problem?". If the answer to that question is a resounding yes, then ParamBag might just be perfect.

Reopening an IO Stream vs. just using the new Stream

In the Ruby-Docs it gives the example of:
f1 = File.new("testfile")
f2 = File.new("testfile")
f2.readlines[0] #=> "This is line one\n"
f2.reopen(f1) #=> #<File:testfile>
f2.readlines[0] #=> "This is line one\n"
My question is why reopen f2 when you could just f2.close and f1.readlines[0]? Are there any advantages to reopening with a new stream vs. just using the new stream?
I talked to some devs on IRB a while back and the response I got was that it was mostly used for changing the $std variables to modify where methods such as puts and print output to...
$stdout.reopen(File.open('log'))
puts 'hello world'
The reason for using this rather than...
$stdout = File.open('log')
...was kinda up in the air though. I had one dev that said that direct assignment didn't play well with some of ruby's C functions. I don't know much about C and can't say much about this, but he pointed me to some minitest source to see an example of it in use. However, apparently even the source has switched over to direct assignment vs. reopening since the dev last looked at it.
In conclusion... from the looks of it IO#reopen might be useless, but I would love to hear an argument against this.
Update
Ok, so I reread over the documentation and saw that there was a second set of opts for reopen:
reopen(path, mode_str) → ios
This actually seems somewhat useful as opposed to the reopen(other_IO) → ios option.
I suspect that the main difference is that with reopen, the new stream would apply not only to subsequent uses of the $std... variable, but also to variables that previously were assigned the value of the $std... variable. This can be good or bad, depending on your situation.
This irb session shows that with reopen, a variable that was assigned previous to the stream change will acquire the newly changed stream. Note that the fileno does not change for either variable, and both variables produce no output:
> $stderr.fileno
=> 2
> stderr_copy = $stderr
=> #<IO:<STDERR>>
> stderr_copy.fileno
=> 2
> $stderr.reopen(File.open('/dev/null', 'w'))
=> #<File:/dev/null>
> stderr_copy.fileno
=> 2
> $stderr.fileno
=> 2
> $stderr.puts 'foo'
=> nil
> stderr_copy.puts 'foo'
=> nil
In contrast, when instead of using reopen, the newly opened /dev/null File object is assigned to $stderr, stderr_copy will retain its original output stream. Only $stderr gets the new fileno, and stderr_copy still produces output:
> $stderr.fileno
=> 2
> stderr_copy = $stderr
=> #<IO:<STDERR>>
> stderr_copy.fileno
=> 2
> $stderr = File.open('/dev/null', 'w')
=> #<File:/dev/null>
> $stderr.fileno
=> 10
> stderr_copy.fileno
=> 2
> $stderr.puts 'foo'
=> nil
> stderr_copy.puts 'foo'
foo
=> nil
If you want to use reopen, but want to save a copy of the original output stream, you can use dup:
> stderr_dup = $stderr.dup
=> #<IO:<STDERR>>
> stderr_dup.fileno
=> 10
> $stderr.reopen(File.open('/dev/null', 'w'))
=> #<File:/dev/null>
> $stderr.fileno
=> 2
> stderr_dup.puts 'foo'
foo
=> nil
> $stderr.puts 'foo'
=> nil

How to extract the code from a Proc object?

Given a Proc object, is it possible to look at the code inside it?
For example:
p = Proc.new{test = 0}
What I need is for some way to get the string "test = 0" from a Proc object that has already been created.
You can use the ruby2ruby library:
>> # tested with 1.8.7
>> require "parse_tree"
=> true
>> require "ruby2ruby"
=> true
>> require "parse_tree_extensions"
=> true
>> p = Proc.new{test = 0}
>> p.to_ruby
=> "proc { test = 0 }"
You can also turn this string representation of the proc back to ruby and call it:
>> eval(p.to_ruby).call
0
More about ruby2ruby in this video: Hacking with ruby2ruby.
In case you're using Ruby 1.9, you can use the sourcify gem
$ irb
ruby-1.9.2-p0 > require 'sourcify'
=> true
ruby-1.9.2-p0 > p = Proc.new{test = 0}
=> #<Proc:0xa4b166c#(irb):2>
ruby-1.9.2-p0 > p.to_source
=> "proc { test = 0 }"
Use proc.source_location to get the location of the source file that defines the proc.
It also returns the line number of the definition.
You can use those values to locate the location of the proc source.
I think you could use ParseTree for this, it also seems that support for Ruby 1.9.2 is getting close.

Resources