Gems cleverness?

Is there an easy way to find out all the gems you're running in a
particular codebase? (It's a Rails app but I'd imagine the technique
has general usefulness?)

···

--
Giles Bowkett
http://www.gilesgoatboy.org


http://gilesgoatboy.blogspot.com

Giles Bowkett wrote:

Is there an easy way to find out all the gems you're running in a
particular codebase? (It's a Rails app but I'd imagine the technique
has general usefulness?)

Cheap hack:
$:.map{|s|s=~Regexp.new(Regexp.escape(Config::CONFIG['libdir']+'/ruby/gems/1.8/gems/')+'(.*)/lib$');$1}.compact
(or http://preview.tinyurl.com/ya4en4 in Firefox)

I'm sure if you dig through the RubyGems code, you'll find a better way of specifying that directory.

Devin

Gem::SourceIndex.from_installed_gems.search(//).map { |spec| spec.full_name } # *

You get back an Array of Gem::Specification objects.

(I should fix that search in there.)

* I'm running from SVN, but this should still work.

···

On Dec 11, 2006, at 19:31, Giles Bowkett wrote:

Is there an easy way to find out all the gems you're running in a
particular codebase? (It's a Rails app but I'd imagine the technique
has general usefulness?)

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

I LIT YOUR GEM ON FIRE!

Is there an easy way to find out all the gems you're running
in a particular codebase? (It's a Rails app but I'd imagine
the technique has general usefulness?)

Gem::Specification.list.select{|gem| gem.loaded?}.collect{|gem|
gem.full_name}

gegroet,
Erik V. - http://www.erikveen.dds.nl/

Giles Bowkett wrote:
> Is there an easy way to find out all the gems you're running in a
> particular codebase? (It's a Rails app but I'd imagine the technique
> has general usefulness?)

Cheap hack:
$:.map{|s|s=~Regexp.new(Regexp.escape(Config::CONFIG['libdir']+'/ruby/gems/1.8/gems/')+'(.*)/lib$');$1}.compact
(or http://preview.tinyurl.com/ya4en4 in Firefox)

I'm sure if you dig through the RubyGems code, you'll find a better way
of specifying that directory.

I hate to admit it, because digging through the RubyGems code is
probably much more worthwhile in the long term, but cheap hacks are
totally what I need right now.

Is it the Perl-y $: thing that gives it its magic special sauce? Also,
couldn't the Regexp part work just as well without the Config stuff,
because of the minimal likelihood of a non-gem having that string in
its path?

Anyway, it works perfectly:

gilesb@a2s8 [~/railsapp]# script/console
Loading development environment.

$:.map{|s|s=~Regexp.new(Regexp.escape(Config::CONFIG['libdir']+'/ruby/gems/1.8/gems/')+'(.*)/lib$');$1}.compact

=> ["net-sftp-1.1.0", "net-ssh-1.0.10", "needle-1.3.0",
"ferret-0.10.13", "rails-1.1.6", "actionwebservice-1.1.6",
"actionmailer-1.2.5", "BlueCloth-1.0.0", "RedCloth-3.0.4",
"actionpack-1.12.5", "activesupport-1.3.1",
"activerecord-1.14.4/lib/../../activesupport", "activerecord-1.14.4",
"rake-0.7.1"]

Thanks!

Actually, wait a minute -- the app also uses ImageMagick, but that
didn't show up here.

···

On 12/11/06, Devin Mullins <twifkak@comcast.net> wrote:

--
Giles Bowkett
http://www.gilesgoatboy.org

http://gilesgoatboy.blogspot.com

I think I should submit this question to Ruby Quiz. your approach is
very complete, but overkill -- it gives me everything on my system,
rather than everything my app is actually using. Devin's solution gave
me everything my app was using at the moment I ran the command, but
missed things which were used in the app but not yet loaded.

···

On 12/13/06, Eric Hodel <drbrain@segment7.net> wrote:

On Dec 11, 2006, at 19:31, Giles Bowkett wrote:

> Is there an easy way to find out all the gems you're running in a
> particular codebase? (It's a Rails app but I'd imagine the technique
> has general usefulness?)

Gem::SourceIndex.from_installed_gems.search(//).map { |spec|
spec.full_name } # *

You get back an Array of Gem::Specification objects.

(I should fix that search in there.)

* I'm running from SVN, but this should still work.

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

I LIT YOUR GEM ON FIRE!

--
Giles Bowkett
http://www.gilesgoatboy.org

http://gilesgoatboy.blogspot.com

Giles Bowkett wrote:

Is it the Perl-y $: thing that gives it its magic special sauce?

Yup. $: == $LOAD_PATH == the list of directories Ruby looks in when you do a require. FWIW, $" == $LOADED_FEATURES == the list of files (ruby and .so) that have been require'd.

> Also,

couldn't the Regexp part work just as well without the Config stuff,
because of the minimal likelihood of a non-gem having that string in
its path?

I was just trying to be a little robust. It just expands to /usr/local/lib or c:/prog/ruby/lib or whatever. *Very* unlikely that that path would contain a regex metacharacter that needs escaping, too, but what the hell. Yeah, you certainly could do:
$:.map{|s|s=~%r{ruby/gems/1.8/gems/([^/]+)/lib$};$1}.compact.uniq

Actually, wait a minute -- the app also uses ImageMagick, but that
didn't show up here.

You might not have triggered the loading of the code that actually depends on it. ActiveSupport overrides const_missing so you need not require everything. (At least, for... I blogsumed that the feature is being deprecated, or at least limited to your own rb files.)

Devin

> Is there an easy way to find out all the gems you're running in a
> particular codebase? (It's a Rails app but I'd imagine the technique
> has general usefulness?)

Gem::SourceIndex.from_installed_gems.search(//).map { |spec|
spec.full_name } # *

You get back an Array of Gem::Specification objects.

(I should fix that search in there.)

* I'm running from SVN, but this should still work.

I think I should submit this question to Ruby Quiz. your approach is
very complete, but overkill -- it gives me everything on my system,
rather than everything my app is actually using.

Oh, sorry.

require 'rubygems'
require 'inline'

class << Gem; attr_reader :loaded_specs; end

p Gem.loaded_specs.keys

I'll make this cleaner.

Devin's solution gave me everything my app was using at the moment I ran the command, but missed things which were used in the app but not yet loaded.

I don't see how you could possibly expect to know what files would be loaded by your program in the future.

···

On Dec 13, 2006, at 18:32, Giles Bowkett wrote:

On 12/13/06, Eric Hodel <drbrain@segment7.net> wrote:

On Dec 11, 2006, at 19:31, Giles Bowkett wrote:

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

A: Yes
Q: Is top-posting bad?
  — Derek Milhous Zumsteg

Ok, This will be going in once rubygems is up. Same interface.

···

On Dec 14, 2006, at 11:20, Eric Hodel wrote:

On Dec 13, 2006, at 18:32, Giles Bowkett wrote:

On 12/13/06, Eric Hodel <drbrain@segment7.net> wrote:

On Dec 11, 2006, at 19:31, Giles Bowkett wrote:

> Is there an easy way to find out all the gems you're running in a
> particular codebase? (It's a Rails app but I'd imagine the technique
> has general usefulness?)

Gem::SourceIndex.from_installed_gems.search(//).map { |spec|
spec.full_name } # *

You get back an Array of Gem::Specification objects.

(I should fix that search in there.)

* I'm running from SVN, but this should still work.

I think I should submit this question to Ruby Quiz. your approach is
very complete, but overkill -- it gives me everything on my system,
rather than everything my app is actually using.

Oh, sorry.

require 'rubygems'
require 'inline'

class << Gem; attr_reader :loaded_specs; end

p Gem.loaded_specs.keys

I'll make this cleaner.

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

I LIT YOUR GEM ON FIRE!

> Devin's solution gave me everything my app was using at the moment
> I ran the command, but missed things which were used in the app but
> not yet loaded.

I don't see how you could possibly expect to know what files would be
loaded by your program in the future.

Well, that's the challenge, isn't it? It's only when you start to hack
time-travel knowledge discovery problems that you discover how truly
astounding Ruby's dynamicity is.

Seriously a human can do it just by looking at the source. There were
image magick things in there, they weren't caught by checking all gems
currently in use. Maybe because the code lives in a plugins dir and
wasn't invoked yet? I don't know.

···

--
Giles Bowkett
http://www.gilesgoatboy.org

http://gilesgoatboy.blogspot.com

> Devin's solution gave me everything my app was using at the moment
> I ran the command, but missed things which were used in the app but
> not yet loaded.

I don't see how you could possibly expect to know what files would be
loaded by your program in the future.

Well, that's the challenge, isn't it? It's only when you start to hack
time-travel knowledge discovery problems that you discover how truly
astounding Ruby's dynamicity is.

Seriously a human can do it just by looking at the source.

Not accurately. Load path manipulation or require order may cause files to be loaded or not loaded contrary to your expectations. Files may have been orphaned by the author, or your code may not need certain files, so they won't be required.

There were image magick things in there, they weren't caught by checking all gems
currently in use. Maybe because the code lives in a plugins dir and wasn't invoked yet? I don't know.

Which is why human inspection doesn't work.

···

On Dec 15, 2006, at 12:56, Giles Bowkett wrote:

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

I LIT YOUR GEM ON FIRE!

and, of course, it can be even more pathalogical

   require 'find'
   Find.find($:[rand($:.size)]{|e| break(require(e)) if rand > 0.42}

nevermind code generation and subsequent inclusion!

:wink:

-a

···

On Sat, 16 Dec 2006, Eric Hodel wrote:

On Dec 15, 2006, at 12:56, Giles Bowkett wrote:

> Devin's solution gave me everything my app was using at the moment
> I ran the command, but missed things which were used in the app but
> not yet loaded.

I don't see how you could possibly expect to know what files would be
loaded by your program in the future.

Well, that's the challenge, isn't it? It's only when you start to hack
time-travel knowledge discovery problems that you discover how truly
astounding Ruby's dynamicity is.

Seriously a human can do it just by looking at the source.

Not accurately. Load path manipulation or require order may cause files to
be loaded or not loaded contrary to your expectations. Files may have been
orphaned by the author, or your code may not need certain files, so they
won't be required.

--
if you find yourself slandering anybody, first imagine that your mouth is
filled with excrement. it will break you of the habit quickly enough. - the
dalai lama

Granted, but that's not a good reason to not to do what you can. Based on a static analysis of the code, you can figure out what most of the module dependencies are, or even all of the module dependencies in most cases. Being able to identify the modules a script loads automatically is a necessary step for tools like PerlApp, perl2exe, PAR/pp, py2app, py2exe, etc. which produce executables from Perl and Python scripts by bundling the script, the interpreter and the dependent modules in a self-extracting, executable archive. I don't remember what the OP here wanted this for, but what they're asking for is not impractical or silly, and the problems people are citing with it are not unique to ruby.

If you're not familiar with the Perl and Python products I mentioned, here are some references:

     PAR http://par.perl.org/wiki/Main_Page
     Module::ScanDeps http://search.cpan.org/dist/Module-ScanDeps/
     py2app http://svn.pythonmac.org/py2app/py2app/trunk/doc/index.html
     PerlApp ActiveState Community - Boosting coder and team productivity with ready-to-use open source languages and tools.
     py2exe http://www.py2exe.org/

I noticed (while Googling) that there is a similar Ruby project already. Presumably it already does this sort of dependency analysis in one form or another.

     rubyscript2exe http://www.erikveen.dds.nl/rubyscript2exe/index.html

Cheers,

Tom

···

On Dec 15, 2006, at 3:15 PM, Eric Hodel wrote:

On Dec 15, 2006, at 12:56, Giles Bowkett wrote:

I don't see how you could possibly expect to know what files would be
loaded by your program in the future.

Well, that's the challenge, isn't it? It's only when you start to hack
time-travel knowledge discovery problems that you discover how truly
astounding Ruby's dynamicity is.

Seriously a human can do it just by looking at the source.

Not accurately. Load path manipulation or require order may cause files to be loaded or not loaded contrary to your expectations. Files may have been orphaned by the author, or your code may not need certain files, so they won't be required.

not to mention:
   def require; false end

Devin
(or some screwball impl involving reverse, rot13...)

···

ara.t.howard@noaa.gov wrote:

and, of course, it can be even more pathalogical

  require 'find'
  Find.find($:[rand($:.size)]{|e| break(require(e)) if rand > 0.42}

nevermind code generation and subsequent inclusion!