How to require Ruby 1.9 from a required file?

Is there any way to require Ruby 1.9 from a required file such that I
can trigger an error message before the main file is parsed?

Suppose I’m making a DSL that depends on the very nice Ruby 1.9 hash
syntax. Here’s an example:

app.rb

$LOAD_PATH << File.dirname(__FILE__)
require 'my_library'

make_pie apple:2, butter:1, flour:4
puts "bye"

in my_library I want to report an error if we’re not running with 1.9,
so I did this:

if RUBY_VERSION < "1.9.0"
  abort <<-end_message
    This requires Ruby 1.9
  end_message
end

def make_pie options
  return unless options.respond_to? :key
  puts "with " + options.keys.join(',') + " we can make a great pie"
end

It works great as long as I don’t have Ruby 1.9 syntax in the main file,
but when I do, Ruby 1.8.7 will show that error first.

$ rvm use 1.9.2-head
Using ruby 1.9.2 head
$ ruby app.rb
with apple,butter,flour we can make a great pie
bye
$ rvm use 1.8.7
Using ruby 1.8.7 p249
$ ruby app.rb
app.rb:4: syntax error, unexpected tINTEGER, expecting

tSTRING_CONTENT or tSTRING_DBEG or tSTRING_DVAR or tSTRING_END
make_pie apple:2, butter:1, flour:4
^

I posted the files at: GitHub - ultrasaurus/ruby_version_check: understanding how to require Ruby 1.9

Sure this can be solved with documentation OR changing the syntax of my
DSL to use 1.8.7, but I was hoping for a nicer solution for end users
(who are expected to be kids).

Thanks in advance,

Sarah

http://www.ultrasaurus.com

On Mon, Sep 6, 2010 at 9:40 PM, Sarah A. [email protected]
wrote:

end
Using ruby 1.9.2 head

I posted the files at: GitHub - ultrasaurus/ruby_version_check: understanding how to require Ruby 1.9

Sure this can be solved with documentation OR changing the syntax of my
DSL to use 1.8.7, but I was hoping for a nicer solution for end users
(who are expected to be kids).

Thanks in advance,

Sarah

You can’t catch a SyntaxError in same file in which it occurs (if you
think about it - your rescue statement has to come after the place
where the syntax error has already occurred). You ~can~ catch a
SyntaxError in eval’d or loaded code. So, instead of requiring your
library, why not use a script loader like this:

file: recipe-dsl

#!/usr/bin/env ruby
def make_pie(params)
p params
end

begin
load ARGV[0]
rescue SyntaxError => e
if RUBY_VERSION < ‘1.9.0’
puts “You need ruby 1.9.x to run this script”
else
raise
end
end

which you use to run the DSL scripts like so:

$ recipe-dsl ~/apple-pie.recipe

where apple-pie.recipe contains just your DSL statements:

file: apple-pie.recipe

make_pie apple: 2, butter: 1, flour: 4

If you try to run this under 1.8.x, you’ll get:

$ ./recipe-dsl apple-pie.recipe
You need ruby 1.9.x to run this script

If you really do have a syntax error in your recipe script, that will
be reported under 1.9.x.

HTH

Regards,
Sean

Sean O’halpin wrote:

You can’t catch a SyntaxError in same file in which it occurs (if you
think about it - your rescue statement has to come after the place
where the syntax error has already occurred). You ~can~ catch a
SyntaxError in eval’d or loaded code. So, instead of requiring your
library, why not use a script loader like this:

file: recipe-dsl

#!/usr/bin/env ruby
def make_pie(params)
p params
end

begin
load ARGV[0]
rescue SyntaxError => e
if RUBY_VERSION < ‘1.9.0’
puts “You need ruby 1.9.x to run this script”
else
raise
end
end

Or:

my_library.rb:
#!/usr/bin/env ruby
abort “You need ruby 1.9.x to run this script” if RUBY_VERSION <
“1.9.0”
load ‘my_library_1.9’

if you know your libraries Ruby 1.9-dependencies aren’t limited to
constructs that would be syntactic errors in Ruby 1.8, so you don’t want
the error message to depend on the presence of syntax errors.

This generalizes to:

my_library.rb:
#!/usr/bin/env ruby
case
when RUBY_VERSION >= “1.9.0” then load ‘my_library_1.9’
else load ‘my_library_1.8’
end

if you add an Ruby 1.8 implementation.

Sarah A. wrote:

Is there any way to require Ruby 1.9 from a required file such that I
can trigger an error message before the main file is parsed?

Suppose I’m making a DSL that depends on the very nice Ruby 1.9 hash
syntax. […]
[…]
Sure this can be solved with documentation OR changing the syntax of my
DSL to use 1.8.7, but I was hoping for a nicer solution for end users
(who are expected to be kids).

Unfortunately, no.

Ruby 1.8.8 is supposed to be syntactically compatible with Ruby 1.9,
specifically to solve the very problem you are having. So, in Ruby
1.8.8, just parsing Ruby 1.9 code should not result in an error,
only actually running it. But obviously, Ruby 1.8.8 isn’t out yet,
and if you could get the kids to upgrade to Ruby 1.8.8, you could
presumably get them to upgrade to Ruby 1.9.2 as well, so …

jwm