Module: RubySmart::Support::GemInfo

Defined in:
lib/ruby_smart/support/gem_info.rb

Constant Summary collapse

GEM_PATH_REGEXP =

regexp to detect a gems path

/\/gems\//
GEM_NAME_REGEXP =

regexp to resolves a name from a gem path

/\/gems\/([A-za-z0-9_\-]+)\-[\d\w\-\_\.]+\//
FEATURE_NAME_REGEXP =

regexp to resolves a feature from a gem path

/\/gems\/([A-za-z0-9_\-]+)\-[\d\w\-\_\.]+\/lib\/(?:\1\/(\1)|([A-za-z0-9_\-]+))\.rb/

Class Method Summary collapse

Class Method Details

.feature?(name) ⇒ Boolean

returns true if the provided feature is loaded.

GemInfo.feature?('active_support')

true

Parameters:

  • name (String)
    • the feature name

Returns:

  • (Boolean)


142
143
144
# File 'lib/ruby_smart/support/gem_info.rb', line 142

def self.feature?(name)
  features.include?(name)
end

.featuresArray<String>

returns an array of all loaded features

GemInfo.features

['active_support','bundler']

Returns:



123
124
125
126
127
128
129
130
131
132
133
# File 'lib/ruby_smart/support/gem_info.rb', line 123

def self.features
  $LOADED_FEATURES.
    select { |feature| feature.match(GEM_PATH_REGEXP) }.
    map { |feature|
      m = feature.match(FEATURE_NAME_REGEXP)
      m ? (m[2] || m[3]) : nil
    }.
    uniq.
    compact.
    sort
end

.installedHash{<name> => Array[<version>]}

returns a hash of all installed gems with it's versions

Examples:


GemInfo.installed
# > {'bundler' => ['2.2.30', '1.2.3']}

Returns:



24
25
26
# File 'lib/ruby_smart/support/gem_info.rb', line 24

def self.installed
  Hash[::Gem::Specification.reduce({}) { |m, g| m[g.name] ||= []; m[g.name] << g.version.to_s; m }.sort]
end

.installed?(name, version = nil) ⇒ Boolean

returns true if the provided gem name is installed. the optional version requirement matches against any available version

GemInfo.installed?('bundler') # > true

GemInfo.installed?('bundler', '~> 3.0') # > false

Parameters:

  • name (String)
    • the gem name
  • version (nil, String) (defaults to: nil)
    • optional version requirement

Returns:

  • (Boolean)


40
41
42
# File 'lib/ruby_smart/support/gem_info.rb', line 40

def self.installed?(name, version = nil)
  installed.key?(name) && (version.nil? || installed[name].any? { |gem_version| match?(gem_version, version) })
end

.licensesHash{<name> => <license>}

returns a hash of all loaded gems with it's licenses

Examples:


GemInfo.licenses
# > {'bundler' => 'MIT', 'hashery' => 'BSD-2-Clause'}

Returns:

  • (Hash{<name> => <license>})

    licenses



64
65
66
# File 'lib/ruby_smart/support/gem_info.rb', line 64

def self.licenses
  Hash[::Gem.loaded_specs.values.map { |g| [g.name, g.license || '?'] }.sort]
end

.loadedHash{<name> => <version>}

returns a hash of all loaded gems with its current version

Examples:


GemInfo.loaded
# > {'bundler' => '2.2.30'}

Returns:

  • (Hash{<name> => <version>})

    gem name-version hash



52
53
54
# File 'lib/ruby_smart/support/gem_info.rb', line 52

def self.loaded
  Hash[::Gem.loaded_specs.values.map { |g| [g.name, g.version.to_s] }.sort]
end

.loaded?(name, version = nil) ⇒ Boolean

returns true if the provided gem name is loaded (defined within any Gemfile), but must not be required yet. the optional version requirement matches against the loaded version

GemInfo.loaded?('bundler') # > true

GemInfo.loaded?('bundler', '~> 3.0') # > false

Parameters:

  • name (String)
    • the gem name
  • version (nil, String) (defaults to: nil)
    • optional version requirement

Returns:

  • (Boolean)


80
81
82
# File 'lib/ruby_smart/support/gem_info.rb', line 80

def self.loaded?(name, version = nil)
  loaded.key?(name) && (version.nil? || match?( loaded[name], version))
end

.match?(*args) ⇒ Boolean

compares two versions against each other

match?('4.3.0', '4.3.0')

true

match?('4.3.0', '>= 3.0')

true

match?('3.3.0', '~> 3.1')

true

match?('3.3.0', '~>', '3.1')

true

match?('0.1.0', '~> 1.1.0')

false

Returns:

  • (Boolean)


202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/ruby_smart/support/gem_info.rb', line 202

def self.match?(*args)
  version_current = args.shift
  version_requirement = args.join(' ')

  return true if version_requirement.nil? || version_requirement.strip == ''

  gem_version_current     = Gem::Version.new(version_current)
  gem_version_requirement = Gem::Requirement.new(version_requirement)

  # check if required version is PRE & current is NOT
  if gem_version_requirement.prerelease? && !gem_version_current.prerelease?
    gem_version_requirement = Gem::Requirement.new("#{gem_version_requirement.requirements[0][0]} #{gem_version_requirement.requirements[0][1].release.version}")
  elsif gem_version_requirement.prerelease? != gem_version_current.prerelease?
    # check if required version PRE doesn't equal current version PRE
    gem_version_current = gem_version_current.release
  end
  # else is not required here: either its PRE && PRE || !PRE && !PRE

  gem_version_requirement.satisfied_by?(gem_version_current)
end

.requiredArray<name>

returns an array of all required gems

GemInfo.required

['bundler']

Returns:

  • (Array<name>)

    ] gem names



90
91
92
93
94
95
96
97
98
99
# File 'lib/ruby_smart/support/gem_info.rb', line 90

def self.required
  $LOADED_FEATURES.
    select { |feature| feature.match(GEM_PATH_REGEXP) }.
    map { |feature|
      m = feature.match(GEM_NAME_REGEXP)
      m ? m[1] : File.dirname(feature).split('/').last
    }.
    uniq.
    sort
end

.required?(name, version = nil) ⇒ Boolean

returns true if the provided gem name is required. the optional version matches against the required version

GemInfo.required?('bundler')

true

GemInfo.required?('bundler', '~> 3.0')

false

Parameters:

  • name (String)
    • the gem name
  • version (nil, String) (defaults to: nil)
    • optional version requirement

Returns:

  • (Boolean)

    activated?



113
114
115
# File 'lib/ruby_smart/support/gem_info.rb', line 113

def self.required?(name, version = nil)
  required.include?(name) && (version.nil? || match?(self.version(name), version))
end

.safe_require(path, gem = nil, version = nil) ⇒ Boolean

safe requires a feature by provided name & optional gem

GemInfo.safe_require('rake')

true

GemInfo.safe_require('active_support')

true

GemInfo.safe_require('action_view/helpers/date_helper','actionview', '> 0.1.0')

true

Parameters:

  • path (String)
    • the resource path
  • gem (nil, String) (defaults to: nil)
    • optional gem name
  • version (nil, String) (defaults to: nil)
    • optional gem version compare string

Returns:

  • (Boolean)


171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/ruby_smart/support/gem_info.rb', line 171

def self.safe_require(path, gem = nil, version = nil)
  # check for missing gem (nicely check if the feature name differs to the gem name)
  return false if !gem.nil? && path != gem && !required?(gem, version)

  # try to require the feature
  begin
    require path
  rescue LoadError, NameError
    return false
  end

  # just the final true result
  true
end

.version(name) ⇒ String?

returns the currently loaded gem version

GemInfo.version 'bundler'

'2.2.30'

Returns:

  • (String, nil)

    current gem version - return nil if the gem wasn't found



152
153
154
# File 'lib/ruby_smart/support/gem_info.rb', line 152

def self.version(name)
  loaded[name]
end