Ken J
Ken J

Reputation: 4562

Ruby Module Constant Set and Read

I'm developing a module that contains standard methods as well as CLI (Thor) and API (Sinatra). I've created a Submodule that includes a class that inherits Sinatra::Base:

module Monteverde
  module Activity
    def self.version
      "1.0.1"
    end

    class API < Sinatra::Base
      set :port, 22340
      get "/version" do
        Monteverde::Activity.version
      end
      run! if defined? Monteverde::OPERATION
    end
  end
end

This "Activity" is invokes from the CLI (Thor):

module Monteverde
  class CLI < Thor
    desc "api", "Start Activity API"
    def api
      Monteverde.const_set("OPERATION", "started")
      Monteverde::Activity::API
    end

    desc "aversion", "Get Activity Version"
    def aversion
      puts Monteverde::Activity.version
    end
  end
end

If I don't add an "if" to Sinatra's run! it will run automatically and take over the rest of the methods in the module:

...
class API < Sinatra::Base
  register Sinatra::DefaultRoutes
  set :port, 22340
  get "/version" do
    Monteverde::Activity.version
  end
  run!
end

$ ruby monteverde.rb aversion
$ == Sinatra (v2.0.0) has taken the stage on 22340 for development with backup from Puma
$ ...

My issue is that the OPERATION constant is not recognized even though it's set right before the module is called.

Why isn't OPERATION being recognized and how can I get it to be? Is there another more intuitive/useful way to get Sinatra not to fire when I call the module?

Upvotes: 1

Views: 374

Answers (1)

max pleaner
max pleaner

Reputation: 26778

In your API class definition, the run! line happens as soon as you require that file. It doesn't run again if you reference the class, as you're trying to do with the last line of your def api method.

To get around this, you can move the run! command into a method, and call that from Thor:

class API < Sinatra::Base
  # ... other stuff
  def self.start
    run! if defined? Monteverde::OPERATION
  end
end

Then in the Thor file:

 def api
   Monteverde.const_set("OPERATION", "started")
   Monteverde::Activity::API.start
 end

You can deduce that run! is a class method since it's callable in the scope of the class definition (not in an instance method), and so I define a class method to call it.

It would be simpler, though, to not define def self.start, and instead just call the run! method from the Thor file directly:

def api
  Monteverde::Activity::API.run!
end

Upvotes: 2

Related Questions