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 B. 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

On 12/11/06, Devin M. [email protected] wrote:

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.

Giles B. 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

On Dec 11, 2006, at 19:31, Giles B. 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 H. - [email protected] - http://blog.segment7.net

I LIT YOUR GEM ON FIRE!

I think I should submit this question to Ruby Q… 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 Dec 13, 2006, at 18:32, Giles B. wrote:

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 Q… 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.


Eric H. - [email protected] - http://blog.segment7.net

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

On Dec 14, 2006, at 11:20, Eric H. wrote:

spec.full_name } # *

Oh, sorry.

require ‘rubygems’
require ‘inline’

class << Gem; attr_reader :loaded_specs; end

p Gem.loaded_specs.keys

I’ll make this cleaner.

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


Eric H. - [email protected] - 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.

On Dec 15, 2006, at 12:56, Giles B. wrote:

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.


Eric H. - [email protected] - http://blog.segment7.net

I LIT YOUR GEM ON FIRE!

On Sat, 16 Dec 2006, Eric H. wrote:

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.

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 Dec 15, 2006, at 3:15 PM, Eric H. wrote:

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.

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		http://aspn.activestate.com/ASPN/docs/PDK/6.0/

PerlApp_overview.html
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

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/

[email protected] 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!
not to mention:
def require; false end

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