How do I get a list of files that have been `requi

2019-02-04 06:31发布

This is purely an experiment, but I'm wondering if it's possible to get a list of the require'd gems at runtime via some kind of metaprogramming. For example, say I have:

require 'rubygems'
require 'sinatra'
require 'nokogiri'

# don't know what to do here

How can I print out the following at runtime?

this app needs rubygems, sinatra, nokogiri

2条回答
Evening l夕情丶
2楼-- · 2019-02-04 06:49

Here's a way to get all the calls to require. Create this file: show_requires.rb

alias :orig_require :require
def require s
  print "Requires #{s}\n" if orig_require(s)
end

Then start your app with

ruby -r show_requires.rb myapp.rb

This produces something like:

C:\code\test>ruby -r show_requires.rb test.rb
Requires stringio
Requires yaml/error
Requires syck
Requires yaml/ypath
Requires yaml/basenode
Requires yaml/syck
Requires yaml/tag
Requires yaml/stream
Requires yaml/constants
Requires date/format
Requires date
Requires yaml/rubytypes
Requires yaml/types
Requires yaml
Requires etc
Requires dl
Requires rbreadline
Requires readline

If you want only the top-level requires, add a global to track the nesting level:

$_rq_lvl = 0
alias :orig_require :require
def require s
  $_rq_lvl+=1
  print "Requires #{s}\n" if orig_require(s) and $_rq_lvl == 1
  $_rq_lvl -=1
end

Then you get:

C:\code\test>ruby -r require_test.rb test.rb
Requires yaml
Requires readline
查看更多
霸刀☆藐视天下
3楼-- · 2019-02-04 07:10

You can't do this exactly, because requiring one file may require others, and Ruby can't tell the difference between the file that you required and the file that someone else required.

You can check out $LOADED_FEATURES for a list of every single thing that's been required. But you should use Bundler if you want to specify dependencies explicitly.

Here's a thoroughly imperfect way to guess at the gem names and enumerate everything:

ruby-1.9.2-p180 :001 > $LOADED_FEATURES.
   select { |feature| feature.include? 'gems' }.
   map { |feature| File.dirname(feature) }.
   map { |feature| feature.split('/').last }.
   uniq.sort
 => ["1.9.1", "action_dispatch", "action_pack", "action_view", "actions", "active_model", "active_record", "active_support", "addressable", "agent", "array", "aws", "builder", "bundler", "cache_stores", "cancan", "cdn", "class", "client", "common", "compute", "connection", "control", "controllers", "core", "core_ext", "core_extensions", "css", "data_mapper", "decorators", "dependencies", "dependency_detection", "deprecation", "devise", "digest", "dns", "encodings", "encryptor", "engine", "errors", "excon", "ext", "failure", "faraday", "fields", "fog", "formatador", "geographer", "haml", "hash", "helpers", "heroku_san", "hmac", "hooks", "hoptoad_notifier", "html", "http", "i18n", "idna", "importers", "inflector", "initializers", "instrumentation", "integrations", "interpolate", "interval_skip_list", "jquery-rails", "json", "kaminari", "kernel", "lib", "mail", "metric_parser", "mime", "mixins", "model_adapters", "models", "module", "mongo_mapper", "mongoid", "multibyte", "new_relic", "node", "nokogiri", "numeric", "oauth", "object", "omniauth", "orm_adapter", "package", "parser", "parsers", "plugin", "pp", "providers", "queued", "rack", "rails", "railtie", "redis", "request", "request_proxy", "resp    ruby-1.9.2-p180 :008 >onse", "resque", "retriever_methods", "routing", "ruby_extensions", "ruby_flipper", "rubygems", "runtime", "samplers", "sass", "sax", "script", "scss", "selector", "sequel", "ses", "shell", "signature", "simple_geo", "state_machine", "stats_engine", "storage", "strategies", "string", "tar_reader", "template", "terremark", "thor", "tokens", "tree", "treetop", "twitter", "us", "util", "vendor", "version_specific", "visitors", "warden", "xml", "xml_mini", "xpath", "xslt"] 
查看更多
登录 后发表回答