How to require Ruby 1.9 from a required file?

S

Sarah Allen

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: http://github.com/ultrasaurus/ruby_version_check

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
http://blazingcloud.net
 
S

Sean O'Halpin

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. =A0Here's an example:

app.rb

=A0 =A0$LOAD_PATH << File.dirname(__FILE__)
=A0 =A0require 'my_library'

=A0 =A0make_pie apple:2, butter:1, flour:4
=A0 =A0puts "bye"

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

=A0 =A0if RUBY_VERSION < "1.9.0"
=A0 =A0 =A0abort <<-end_message
=A0 =A0 =A0 =A0This requires Ruby 1.9
=A0 =A0 =A0end_message
=A0 =A0end

=A0 =A0def make_pie options
=A0 =A0 =A0return unless options.respond_to? :key
=A0 =A0 =A0puts "with " + options.keys.join(',') + " we can make a great = pie"
=A0 =A0end

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.

=A0 =A0$ rvm use 1.9.2-head
=A0 =A0Using ruby 1.9.2 head
=A0 =A0$ ruby app.rb
=A0 =A0with apple,butter,flour we can make a great pie
=A0 =A0bye
=A0 =A0$ rvm use 1.8.7
=A0 =A0Using ruby 1.8.7 p249
=A0 =A0$ ruby app.rb
=A0 =A0app.rb:4: syntax error, unexpected tINTEGER, expecting
tSTRING_CONTENT or tSTRING_DBEG or tSTRING_DVAR or tSTRING_END
=A0 =A0make_pie apple:2, butter:1, flour:4
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0^

I posted the files at: =A0http://github.com/ultrasaurus/ruby_version_chec= k

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 =3D> 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
 
O

Oliver Steele

Sean said:
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.
 
J

Jörg W Mittag

Sarah said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top