[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Strategies for writing Ruby applications to be easily distributed with RubyGems

Zev Blut

12/19/2006 6:35:00 AM

Hello,

This is mostly a repost of ruby-talk[229723] with some clarifications
and an appeal for ideas.

I have recently attempted to write a RubyGem for the Saikuro project.
Unfortunately, I have learned that there is a mismatch between how I
wrote Saikuro and how RubyGems expects executables to work.

I would like to know is are there any better or commonly followed ways
of writing executables that work with RubyGems and other installation
programs such as setup.rb ?

Below are the differences between how I wrote Saikuro and what
RubyGems does.

1)
Saikuro uses the "if __FILE__ =3D=3D $0" check before doing the
"application work". When RubyGems creates a new gemified saikuro
wrapper to call the real saikuro bin "$0" is the gemified saikuro and
not the real one. Thus, by default nothing happens.

For fun I cheated and commented out the "if __FILE__" check and
replaced it with "if true". Saikuro will work with this change, but I
then ran "saikuro -?" to get a usage message and found the next
problem:


2)
I was reading through the Programming Ruby book and found a part that
showed how to use rdoc to create usage messages. I figured this might
be better than my normal technique so I used it in Saikuro. This has
caused a number of problems actually.

* With the above cheat I get the gem message:
--
/usr/bin/saikuro: invalid option -- ?
This file was generated by RubyGems.

The application 'Saikuro' is installed as part of a gem, and this file
is here to facilitate running it.
--

Which is not the usage message I wanted.


My original goal was to keep Saikuro simple so that as a single file
nothing complicated was needed. But now I suppose that should change.

I am planning to move all logic above and "if __FILE__ =3D=3D $0" block
into a separate library file. Then add a require to this newly made
file and remove the "if __FILE__" check logic to make the insides of
the block automatically run.

Next I will stop using rdoc usage and simply put the usage message in
a method that outputs a String.

Does this sound like a good strategy?

Thanks,
Zev

4 Answers

Eric Hodel

12/19/2006 7:32:00 AM

0

On Dec 18, 2006, at 22:34, Zev Blut wrote:
> This is mostly a repost of ruby-talk[229723] with some clarifications
> and an appeal for ideas.
>
> I have recently attempted to write a RubyGem for the Saikuro project.
> Unfortunately, I have learned that there is a mismatch between how I
> wrote Saikuro and how RubyGems expects executables to work.
>
> I would like to know is are there any better or commonly followed ways
> of writing executables that work with RubyGems and other installation
> programs such as setup.rb ?

My executables typically consist of three lines:

#!/usr/local/bin/ruby -w
require 'some_file'
SomeFile.run

Where SomeFile::run is something like:

class SomeFile
def self.run(args = ARGV)
options = process_args args
new(option[:foo]).run
end
end

> 2)
> I was reading through the Programming Ruby book and found a part that
> showed how to use rdoc to create usage messages. I figured this might
> be better than my normal technique so I used it in Saikuro. This has
> caused a number of problems actually.

What does this technique look like? I'm not familiar with it.

> My original goal was to keep Saikuro simple so that as a single file
> nothing complicated was needed. But now I suppose that should change.
>
> I am planning to move all logic above and "if __FILE__ == $0" block
> into a separate library file. Then add a require to this newly made
> file and remove the "if __FILE__" check logic to make the insides of
> the block automatically run.

I keep these together, but put the logic that would normally go in
"if __FILE__ == $0" into its own method or methods. That keeps the
executable as simple as possible.

--
Eric Hodel - drbrain@segment7.net - http://blog.se...

I LIT YOUR GEM ON FIRE!


Zev Blut

12/19/2006 7:49:00 AM

0

On Tue, 19 Dec 2006 16:31:48 +0900, Eric Hodel <drbrain@segment7.net> =

wrote:

> On Dec 18, 2006, at 22:34, Zev Blut wrote:

>> I would like to know is are there any better or commonly followed way=
s
>> of writing executables that work with RubyGems and other installation=

>> programs such as setup.rb ?
>
> My executables typically consist of three lines:
>
> #!/usr/local/bin/ruby -w
> require 'some_file'
> SomeFile.run
>
> Where SomeFile::run is something like:
>
> class SomeFile
> def self.run(args =3D ARGV)
> options =3D process_args args
> new(option[:foo]).run
> end
> end

Yes that is a good way to solve this problem.

>> 2)
>> I was reading through the Programming Ruby book and found a part that=

>> showed how to use rdoc to create usage messages. I figured this migh=
t
>> be better than my normal technique so I used it in Saikuro. This has=

>> caused a number of problems actually.
>
> What does this technique look like? I'm not familiar with it.

http://ruby-doc.org/stdlib/libdoc/rdoc/rdoc/classes/RDoc.ht...

It is something like this:

-------------
#!/usr/bin/env ruby
# =3D=3D Usage
# Some stuff on how to use a program.
# More stuff

require 'rdoc/usage'

RDoc.usage
-------------

Thanks for the advice!
Zev

Eric Hodel

12/19/2006 8:37:00 AM

0

On Dec 18, 2006, at 23:49, Zev Blut wrote:
> On Tue, 19 Dec 2006 16:31:48 +0900, Eric Hodel
> <drbrain@segment7.net> wrote:
>> On Dec 18, 2006, at 22:34, Zev Blut wrote:
>
>>> I would like to know is are there any better or commonly followed
>>> ways
>>> of writing executables that work with RubyGems and other
>>> installation
>>> programs such as setup.rb ?
>>
>> My executables typically consist of three lines:
>>
>> #!/usr/local/bin/ruby -w
>> require 'some_file'
>> SomeFile.run
>>
>> Where SomeFile::run is something like:
>>
>> class SomeFile
>> def self.run(args = ARGV)
>> options = process_args args
>> new(option[:foo]).run
>> end
>> end
>
> Yes that is a good way to solve this problem.
>
>>> 2)
>>> I was reading through the Programming Ruby book and found a part
>>> that
>>> showed how to use rdoc to create usage messages. I figured this
>>> might
>>> be better than my normal technique so I used it in Saikuro. This
>>> has
>>> caused a number of problems actually.
>>
>> What does this technique look like? I'm not familiar with it.
>
> http://ruby-doc.org/stdlib/libdoc/rdoc/rdoc/classes/RDoc.ht...
>
> It is something like this:
>
> -------------
> #!/usr/bin/env ruby
> # == Usage
> # Some stuff on how to use a program.
> # More stuff
>
> require 'rdoc/usage'
>
> RDoc.usage

Since RDoc.usage uses #caller to figure out which file to read you
should be able to combine RDoc.usage with my method above, and the
usage will live in the library file.

--
Eric Hodel - drbrain@segment7.net - http://blog.se...

I LIT YOUR GEM ON FIRE!


Zev Blut

12/20/2006 8:01:00 AM

0

On Tue, 19 Dec 2006 17:36:43 +0900, Eric Hodel <drbrain@segment7.net> =

wrote:

> On Dec 18, 2006, at 23:49, Zev Blut wrote:
>> On Tue, 19 Dec 2006 16:31:48 +0900, Eric Hodel <drbrain@segment7.net>=
=

>> wrote:
>>> On Dec 18, 2006, at 22:34, Zev Blut wrote:

>>>> 2)
>>>> I was reading through the Programming Ruby book and found a part th=
at
>>>> showed how to use rdoc to create usage messages. I figured this mi=
ght
>>>> be better than my normal technique so I used it in Saikuro. This h=
as
>>>> caused a number of problems actually.
>>>
>>> What does this technique look like? I'm not familiar with it.
>>
>> http://ruby-doc.org/stdlib/libdoc/rdoc/rdoc/classes/RDoc.htm...

>>
>> It is something like this:
>>
>> -------------
>> #!/usr/bin/env ruby
>> # =3D=3D Usage
>> # Some stuff on how to use a program.
>> # More stuff
>>
>> require 'rdoc/usage'
>>
>> RDoc.usage
>
> Since RDoc.usage uses #caller to figure out which file to read you =

> should be able to combine RDoc.usage with my method above, and the usa=
ge =

> will live in the library file.

I have done a quick refactoring to create something similar to your
suggestions. The bin part works now, but the RDoc.usage still gives a
RubyGems message.

Just in case here is my ruby version
# ruby -v
ruby 1.8.5 (2006-08-25) [i686-linux]

I stuck some debugging puts in the RDoc.usage_no_exit method and this
is what I got:

# saikuro -?
/usr/bin/saikuro: invalid option -- ?
Caller main program file is /usr/bin/saikuro
Caller stack is
/usr/lib/ruby/1.8/rdoc/usage.rb:93:in `usage'
/usr/lib/ruby/gems/1.8/gems/Saikuro-1.0.0/bin/saikuro:175:in `run'
/usr/lib/ruby/gems/1.8/gems/Saikuro-1.0.0/bin/saikuro:200
/usr/bin/saikuro:18:in `load'
/usr/bin/saikuro:18
This file was generated by RubyGems.

The application 'Saikuro' is installed as part of a gem, and this file
is here to facilitate running it.


-----

Here is the specific piece of code in rdoc/usage usage_no_exit

main_program_file =3D caller[-1].sub(/:\d+$/, '')

It appears that it assumes that the last caller on the stack is the
one who has the usage comments. But, in this current RubyGems bin
case the line above should be something like this:

main_program_file =3D caller[1].sub(/:\d+(:.*)?$/, '')

If you read the synopsis of RDoc/usage it states that it will always
take the usage from the main program file. This appears to be in
conflict with RubyGems. I suppose one could hack the method to look
at the caller stack and if it sees a RubyGems /bin/ in the caller
stack uses the first instance as the main_program_file ?

Thanks,
Zev