简体   繁体   中英

Creating a new gem which extends another gem: /kernel_require.rb>:85:in `require': cannot load such file -- csv-probe (LoadError)

I'm trying to create my first ruby gem. I've created the gem skeleton by using bundler bundle gem csv-probe . Since the gem is intended as an extension of the csv gem I used a hyphen in its name instead of the underscore as suggested in: https://guides.rubygems.org/name-your-gem/ .

I built the gem and tried to use it, however, when I try to load the gem via require 'csv-probe' I get following error:

<internal:/usr/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- csv-probe (LoadError)
    from <internal:/usr/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
    from ./test.rb:6:in `<main>'

I think it has something to do with the nested structure of the lib directory which bundler created.

lib
└── csv
    ├── probe
    │   ├── checks.rb
    │   └── version.rb
    └── probe.rb

Maybe I extended the csv classes the wrong way?
Content of the lib/csv/probe.rb file

# frozen_string_literal: true

require "csv"
require "terminal-table"
require_relative "probe/version"
require_relative "probe/checks"

# Probe provides methods for linting a:
# * CSV::Table
# * CSV::Row
#
# The linting methods:
# * lint_rows takes following arguments
#   * csv_rows: CSV::Table
#   * checks: Array of Probe Checks and
#   * options
# * lint_row takes following arguments
#   * csv_row: CSV::Row
#   * checks: Array of Probe Checks and
#   * optsions
module Probe
  def self.lint_rows(csv_rows, checks, opts = {})
    lineno_start = opts[:headers] ? 2 : 1
    csv_rows.each.with_index(lineno_start) do |row, lineno|
      opts[:lineno] = lineno
      lint_row(row, checks, opts)
    end
  end

  def self.lint_row(csv_row, checks, opts = {})
    unless csv_row.is_a? CSV::Row
      raise Error "lint_row(csv_row,...), csv_row is not of type CSV::Row, but of type '#{csv_row.class}'"
    end

    checks.each do |check|
      check.evaluate(csv_row, opts)
    rescue LintingError => e
      raise e unless opts[:exception] == false

      puts e.message # if exception oppressed, write error out on stdout
    end
  end
end

# Extend CSV::Table with .lint(...) method
class CSV::Table # rubocop:disable Style/ClassAndModuleChildren -> TODO: don't know how to fix this
  def lint(checks, opts = {})
    opts[:headers] = true unless opts.key?(:headers) # CSV::Table has always headers, hence set :headers = true
    Probe.lint_rows(self, checks, opts)
  end
end

# Extend CSV::Row with .lint(...) method
class CSV::Row # rubocop:disable Style/ClassAndModuleChildren
  def lint(checks, opts = {})
    Probe.lint_row(self, checks, opts)
  end
end

I noticed when loading the gem by using require 'csv/probe' it works, however, the generated README.md skeleton mentioned the gem is loaded via require 'csv-probe' so I guess I did something wrong.

The source code for the gem can be found here:
https://gitlab.com/homebase-dev/csv-probe

As the error message says, Ruby cannot find a file named csv-probe.rb .

Computers are very good at finding things. So, in 99% of all cases when a computer tells you it cannot find a thing, the reason is that the thing you told it to find does not exist.

So, step #1 would be to check: does the file named csv-probe.rb actually exist?

In 99% of the rest of the cases, the thing you told the computer to find does actually exist somewhere , but it doesn't exist where you told the computer to look, in other words, you told the computer to look for the right thing in the wrong place.

So, in case the file does exist somewhere , step #2 would be to check: is the path where the file lives in Ruby's $LOAD_PATH ?

Note that RubyGems actually monkey-patches Kernel#require and will automatically try and add a Gem's lib directory to the $LOAD_PATH . So, if the file exists inside some Gem's lib directory, but is not currently in the $LOAD_PATH , then the next step would be to investigate why that Gem's directory is not automatically added to the $LOAD_PATH .

There is a convention that a Gem's main entry point should have the same name as the Gem, but that is only a convention. One of the most famous Gems that does not follow the convention is the activesupport Gem whose main entry point is active_support.rb .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM