Ruby cmd line script executes code non-consecutively - ruby

I've built a ruby script that is supposed to run in the terminal.
$ ruby script.rb
I have some code specific to newer versions of ruby so I added a ruby version check towards the top of the page:
abort("You're using ruby #{RUBY_VERSION}. Please use version 2.1 or newer") if (RUBY_VERSION.to_f < 2.1)
I double checked the code line in irb and seems to work when changing the ruby version via RVM.
However, when I run the ruby script file under, say ruby 1.8.7, the script blows up with the following error:
$ ruby script.rb
script.rb:6: odd number list for Hash
option1: 'some options',
^
script.rb:6: syntax error, unexpected ':', expecting '}'
option1: 'some options',
^
script.rb:6: syntax error, unexpected ',', expecting $end
This would be expected behavior if I didn't have the version check on the top of the file.
Why doesn't the version check execute before the next lines of code? Is there a way to force execution of the ruby check before continuing with the rest of the code?
My full file is:
#!/usr/bin/env ruby
abort("You're using ruby #{RUBY_VERSION}. Please use version 2.1 or newer") if (RUBY_VERSION.to_f < 2.1)
options = {
option1: 'some options',
option2: 'some more options',
option3: 'other options'
}

That error is on the ruby parser. In ruby 1.8.7 hashes with symbols must be written with hashrockets { :option => 'some options'} because the shorthand { option: '' } was only introduced in ruby 1.9
To explain it better, ruby has to parse the whole file before executing anything on it. So your version check wont be executed because your file has invalid ruby 1.8 syntax.

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

Why is force_encoding("BINARY") used here?

When we install Rails, we get this rails "executable":
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
#
# The application 'railties' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0"
if ARGV.first
str = ARGV.first
str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then
version = $1
ARGV.shift
end
end
gem 'railties', version
load Gem.bin_path('railties', 'rails', version)
I'm wondering what the point of doing force_encoding("BINARY") is on that String. What possible values could it be that force_encoding is necessary? I would think that people would only specify versions using numbers and letters here.
This isn't a rails specific thing - it's a wrapper rubygems will generate for any ruby executable in a gem. The call to force_encoding was added in 6bf71914
The reason for the change is that the first argument might not be a version at all - we want to test if it is a version, but it could be anything and we don't want the regex check to blow up. For example some executables accept a list of file names as arguments, and those file names could be invalid in the default external encoding used by ruby.
There is a bit more discussion on the issue which prompted this change.

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` %>

Console not ready ruby sublime text file

I'm new to programming. Just about to start learning Ruby. I already took a console class, but I am stuck here.
I'm using a mac 10.6.8. I have done a quick 1+2 in the sublime text editor. I saved it. I went over to my console typed irb and then typed ruby example.rb. I have read elsewhere here that typing require './example' would help....it didn't. I am getting the following
NameError: undefined local variable or method `example' for main:Object
from (irb):2
from /usr/local/rvm/rubies/ruby-1.9.3-p392/bin/irb:16:in `<main>'
I don't understand what I am doing wrong. Thank you for your help. I really appreciate it.
-L
I would do as below:
kirti#kirti-Aspire-5733Z:~$ irb
2.0.0p0 :001 > require 'fileutils'
=> true
2.0.0p0 :002 > FileUtils.pwd
=> "/home/kirti"
2.0.0p0 :003 > FileUtils.cd "/home/kirti/ruby"
=> nil
2.0.0p0 :004 > load "./SO.rb"
3
=> true
2.0.0p0 :005 > require "./SO.rb"
3
=> true
My SO.rb file contains the below line :
puts 1+2
May be you wanna give a try.
Step 1: Navigate to your project/file folder by using command "cd folder_name/folder_location"
Step 2: load './example.rb'
For better solution you may wanna define some function inside example.rb
Like:
def sum
1 + 2
end
And to get the output enter sum in irb after loading the example.rb file.
irb is the interactive ruby shell. Within the shell, everything you type is interpreted as Ruby code, not bash commands. So, for example:
bash> puts 1 + 2
# command not found: puts
# this happens because you're not in a Ruby shell
bash> irb
# now you're in a Ruby shell
irb> puts 1 + 2
# 3
If you wrote some code in example.rb, you have two options:
From the bash shell, run ruby example.rb (from the same directory where your example.rb file is saved.
From the irb console, you can require 'example', which will load the contents of example.rb into your interpreter. In this case, it will immediately execute the Ruby code. If you wrapped the contents of example.rb in a class, it would load the class, but not execute code within it until you instantiated/called it.
Hopefully that helps!
My guess is that you are typing (into irb):
require example.rb
When you need to type:
require './example.rb'
The first tells ruby: "require what is in a variable called example". Because you did not define a variable called example, it results in the no variable or method error.
The second tells ruby: "require a string './example.rb'". Since the require method essentially knows how to find the file name passed as a string and evaluate the file, you'll get the right output
By the way, for this example, example.rb needs to be in the same directory. If example.rb is in another directory, you'll need to use the full path (I won't expand on it here) to source it.
You'll also notice that the output will look something like this:
3
=> true
This is because the file was evaluated (executing the code: puts 1+2) and the require method returns true to indicate it evaluated the file.
If you require the file again, you'll get false because the file is already loaded.

Unexpected token error with Ruby

Attempting to execute the basic.rb example for HTTParty. Running into an interesting error. Executing this under 1.8.7 on my Mac (10.7.2). When I run the example (see code below), I get this error:
$ ./HTTPartyTest.rb
./HTTPartyTest.rb: line 1: syntax error near unexpected token `('
./HTTPartyTest.rb: line 1: `dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))'
If I take line 1 and execute it via irb I get this result.
>> dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
=> "/Users/me/Workspaces/lib"
Not sure why this occurring. Any help is appreciated.
You probably need to add the correct hash-bang header or this will be executed using your shell instead:
#!/usr/bin/env ruby
# ... (Rest of program)
The alternative is to explicitly specify you want to run it with Ruby:
ruby ./HTTPartyTest.rb

Resources