hudsonmendes
hudsonmendes

Reputation: 559

undefined method `configure' for MyGem:Module

Context of the Problem

The initializer: leanpirates_aarrr.rb

LeanPirates::Aarrr.configure do |config|
  config.api_server     = "http://localhost:3000"
  config.startup_key    = Rails.configuration.leanpirates_aarrr.startup_key
  config.startup_secret = Rails.application.secrets.leanpirates_startup_secret
end

The gem definition file: aarrr.rb

# (...)
module LeanPirates
  module Aarrr
    class << self
      attr_writer :configuration
    end

    def self.configuration
      @configuration ||= LeanPirates::Aarrr::Domain::Configuration.new
    end

    def self.reset
      @configuration = LeanPirates::Aarrr::Domain::Configuration.new
    end

    def self.configure
      yield(configuration)
    end
  end
end

The error

/src/app-ebusiness-v3/config/initializers/leanpirates_aarrr.rb:1:in <top (required)>: undefined method 'configure' for LeanPirates::Aarrr:Module (NoMethodError)

/src/app-ebusiness-v3/config/initializers/leanpirates_aarrr.rb:1:in `<top (required)>': undefined method `configure' for LeanPirates::Aarrr:Module (NoMethodError)
    from /home/ubuntu/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:287:in `load'
    from /home/ubuntu/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:287:in `block in load'
    from /home/ubuntu/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:259:in `load_dependency'
    from /home/ubuntu/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:287:in `load'
    (...)

This is for the opensource LeanPirates AARRR from https://github.com/lean-pirates/gem-aarrr/tree/simplification (branch simplification)

Upvotes: 3

Views: 2021

Answers (2)

hudsonmendes
hudsonmendes

Reputation: 559

Problem solved

@tadman guided me in the right direction with his explanation (thanks very much for that), although the problem was bigger than I could initially assess.

The Rails Autoloader was having trouble to load my files. Why? Because I tried to organise them.

The problem was

Namespacing! Long ago, when the gem was started, it felt reasonable to move everything into a /lib/gem folder. However, it proved to be the source of the problem.

With the namespacing not matching the folder structure properly, the Autoloader was having trouble loading the files, and they were not getting recognised along with the classes of my gem, etc.

How was the Namespacing sorted?

When you are doing your gems, make sure that you understand well namespacing. In my case, generating the plugin with the following command line sorted out the problem:

rails plugin new lean_pirates-aarrr

This line above created things in the way they should be for the auto-loader to pick up. It's not something we can complain about: Rails follows a lot the "convention over convention" paradigm.

My end structure was the following: (https://github.com/lean-pirates/gem-aarrr/tree/simplification)

- lib/
  -> generators/
    -> lean_pirates/
      -> aarrr/
        -> install/
          -> routines/*.rb
          -> templates/*.rb
          -> *.rb
  -> lean_pirates/
    -> aarrr/
      -> domain/*.rb
      -> helpers/*.rb
      -> *.rb

I'd be happier to make /generators and /gem at the root, and I'm sure it would be possible, but I don't really wanna fight the convention, so I'm pretty happy to leave it as is, at least for now.

If you are facing the same problem, fixing the folder structure might help the Autoloader to find your files. Change it, or configure it accordingly.

Upvotes: 1

tadman
tadman

Reputation: 211570

The Autoloader feature in Rails is very handy, it takes care of a ton of things automagically, but it's also not very smart. If a namespace is already defined it will not load additional files.

It's your obligation as a gem to require any and all support modules or classes that are necessary for your library to work properly.

Here's the problem in lib/gem/aarrr/version.rb:

module LeanPirates
  module Aarrr
      VERSION = '0.1.1'
  end
end

Now LeanPirates::Aarrr is already defined so no additional work by the autoloader is required. As such, your lib/gem/aarrr.rb is never loaded.

To fix this you need to avoid creating that namespace path. You should also ensure that require_paths is set properly in your .gemspec file so that lib/gem is referenced correctly. Right now you'd have to require 'gem/aarrr' which is really confusing and clunky.

I usually set up a plain-old VERSION file in the main gem directory that has nothing but the version string. The gemspec can read this in on-demand if required with File.read, or you can bake it into the .gemspec using a rake task. I prefer the latter approach as making a .gemspec with tons of arbitrary code in it is always over-complicating things.

Upvotes: 1

Related Questions