代码之家  ›  专栏  ›  技术社区  ›  Ken J

Ruby模块常量设置和读取

  •  1
  • Ken J  · 技术社区  · 7 年前

    我正在开发一个包含标准方法以及CLI(Thor)和API(Sinatra)的模块。我创建了一个子模块,其中包含一个继承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
    

    此“活动”是从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
    

    如果我不在Sinatra的跑步中添加“如果”!它将自动运行并接管模块中的其余方法:

    ...
    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
    $ ...
    

    我的问题是,即使在调用模块之前设置了运算常量,也无法识别它。

    为什么手术没有被识别,我如何才能识别? 有没有其他更直观/有用的方法让Sinatra在我呼叫模块时不开火?

    1 回复  |  直到 7 年前
        1
  •  2
  •   max pleaner    7 年前

    在API类定义中 run! 只要您需要该文件,就会立即执行该行。如果引用该类,它不会再次运行,就像您试图使用 def api 方法

    要解决此问题,您可以移动 命令转换为方法,并从Thor调用该方法:

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

    然后在Thor文件中:

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

    你可以推断 是一个类方法,因为它可以在类的范围内调用 释义 (不是在实例方法中),因此我定义了一个类方法来调用它。

    不过,不定义会更简单 def self.start ,而只需拨打 方法直接从Thor文件:

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