Ruby hash.key error - ruby

I feel like I'm overlooking something here. When I try to use the Hash.key(keytolookfor) method, I get an error.
Is this method deprecated?
pete#Vader:~/tmp$ ruby -v
ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-linux]
pete#Vader:~/tmp$ ./hashtest.rb
./hashtest.rb:8: undefined method `key' for {"firstkey"=>"firstvalue", "secondkey"=>"secondvalue"}:Hash (NoMethodError)
pete#Vader:~/tmp$
The script is as follows.
#!/usr/bin/ruby
testHash = Hash.new
testHash["firstkey"] = "firstvalue"
testHash["secondkey"] = "secondvalue"
if testHash.has_value?("secondvalue")
keyvalue = testHash.key("secondvalue")
puts "match found with key #{keyvalue}"
else
puts "no match found"
end

My wild guess is that your system ruby /usr/bin/ruby is 1.8.7 which doesn't have Hash#key method. ruby -v most probably shows rvm version which is located in ~/.rvm/..., but first line in your script calls /usr/bin/ruby.

Use the heap record for script as follows:
#/usr/bin/env ruby
This picks up the default ruby version specified by the system, rvm, or rbenv. Since Ruby 1.8.7 has no Hash#key, make sure that you're running at least Ruby 1.9.1:
$ /usr/bin/ruby -v
1.9.1p0
Alternatively, use Hash#[] instead:
keyvalue = testHash["secondvalue"]

Related

Force .rb file running under specific ruby versions

I write a ruby script in a .rb file. It uses latest Ruby features (version 2.7). Is there any way to force this .rb file can only be executed in a specific Ruby version range? For example, the first line of a .rb file could be:
#! ruby 2.7+
# This .rb file can only be run with Ruby version 2.7 or above
Use the gem semantic to handle parsing the current Ruby version:
require 'semantic'
# Require >= 2.7 < 3
exit unless Semantic::Version.new(RUBY_VERSION).satisfies?('~> 2.7')
# Require >= 2.7, including 3 and above
exit unless Semantic::Version.new(RUBY_VERSION).satisfies?('>= 2.7')
This requires you to use bundler and a Gemfile with your app.
Other comparators are listed in the source code for the gem:
if ['<', '>', '<=', '>='].include?(comparator)
satisfies_comparator? comparator, pad_version_string(other_version_string)
elsif comparator == '~>'
pessimistic_match? other_version_string
else
tilde_matches? other_version_string
end
This will allow you to fine-tune your version requirements.
Naively,
unless RUBY_VERSION[0, 3] == "2.7"
puts "You need 2.7")
exit
end

Programatically get current version of ruby standard library

I looking for a way in my ruby program to determine the version of Ruby that is running my program as well as the version of the Standard Libary?
The version of Ruby is stored in the RUBY_VERSION global constant.
puts RUBY_VERSION
You can compare versions by using classes provided by Rubygems:
min_ruby_version = Gem::Requirement.new(">=2.2.0")
current_ruby_version = Gem::Version.new(RUBY_VERSION)
# check if ruby conforms to version req using =~ operator
if min_ruby_version =~ current_ruby_version
do_this
else
do_that
end

why does `ruby -v` return true in rails, rather than return the version?

This seems like a silly question, but it's got me stumped. If I do this in the rails console:
system('ruby -v')
ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-darwin14]
=> true
So it shows the version, but returns true. So I do this in an .erb file:
<%= system('ruby -v') %>
and it just prints "true" on the web page. I've searched google, though the words involved just make it harder since they are used in so many places I've found it hard to craft a query that will return what I want. Thus proving google is not an AI. :-)
system executes the command and returns true if there was no error. So in this case the version is printed to the standard output and your program receives true which is included in your Erb output (check your log files, you might find the output of ruby -v in them.
What you probably want is ` (that’s a backtick). This is a method, but is called by using the backticks like quotes:
2.2.1 :001 > `ruby -v`
=> "ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-darwin13]\n"
Note how this returns the output of the call to ruby -v rather than printing it.
system prints out the result of the command and returns whether it was a success or not. Try the `` syntax:
<%= `ruby -v` %>

Array#to_s in Ruby 2.1 broke my code

This code broke on Ruby 2.1
class Test
def to_s()
"hi"
end
end
puts [Test.new(), Test.new()].to_s
Ruby 1.9.3:
$ ruby --version
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
$ /opt/chef/embedded/bin/ruby test.rb
[hi, hi]
Ruby 2.1:
$ ruby --version
ruby 2.1.4p265 (2014-10-27 revision 48166) [x86_64-linux]
$ ruby test.rb
[#<Test:0x000000022ac400>, #<Test:0x000000022ac3d8>]
Is this documented somewhere? How can the old behavior be preserved?
Your code:
puts [Test.new(), Test.new()].to_s
is a questionable use of Array.to_s. Instead I'd use:
puts [Test.new(), Test.new()].map(&:to_s)
While I can see that the first use makes sense, the second use makes more sense and should work in any version of Ruby.
On ruby 2.1.5:
class Test
def to_s
"hi"
end
alias inspect to_s # add this line
end
puts [Test.new, Test.new].to_s
#=> [hi, hi]
This seems like a bug to me. If it is intended behavior, that is really annoying.
You don't need to_s. puts does the work for you
puts [Test.new(), Test.new()]
# hi
# hi
If you want the brackets, that's what inspect is for (in which case it makes sense that you would need to define Test#inspect).

Need to call different Ruby method depending on what version is installed

I have a Ruby script that iterates over each line of a text file.
In Ruby 1.8.* using content.each do |line| works fine, but in Ruby 1.9.* that does not work, and I need to use content.each_line do |line|.
Since this script will be used by several different people, I need to be able to use the right method depending on their version of Ruby.
Is there a way to do this?
The global constant RUBY_VERSION contains the version of the currently running Ruby. So this script will do what you want:
if RUBY_VERSION < "1.9.2"
# code for 1.8.7
else
# code for 1.9.2+
end
If the inner code of the each_line is equal with 1.8.* and 1.9.*, the following approach is more DRY:
each_selector = RUBY_VERSION < "1.9.2" ? :each : :each_line
content.send(each_selector) do | line|
# ...
end

Resources