【问题标题】:Ruby gem for Rails app: how to get `Rails.env` method without requiring Rails?Rails 应用程序的 Ruby gem:如何在不需要 Rails 的情况下获取“Rails.env”方法?
【发布时间】:2022-07-22 00:51:57
【问题描述】:

我有 RoR 经验,但我正在开发我的第一个宝石。

gem 专门用于 Rails 应用程序,我想在某些情况下依赖 Rails.env

我知道在 .gemspec 中要求 Rails 是一个坏主意(至少是不好的做法),因为 Rails 很大并且有很多自己的依赖项。

Rails.env 并不是我可以直接加入的扩展。

Rails.env 功能来自 railties,它本身依赖于 active_supportaction_dispatch 和其他一些东西:

require "rails/ruby_version_check"

require "pathname"

require "active_support"
require "active_support/core_ext/kernel/reporting"
require "active_support/core_ext/module/delegation"
require "active_support/core_ext/array/extract_options"
require "active_support/core_ext/object/blank"

require "rails/application"
require "rails/version"

require "active_support/railtie"
require "action_dispatch/railtie"

module Rails
  extend ActiveSupport::Autoload
  extend ActiveSupport::Benchmarkable

  autoload :Info
  autoload :InfoController
  autoload :MailersController
  autoload :WelcomeController

  class << self
    ...

    # Returns the current Rails environment.
    #
    #   Rails.env # => "development"
    #   Rails.env.development? # => true
    #   Rails.env.production? # => false
    def env
      @_env ||= ActiveSupport::EnvironmentInquirer.new(ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || "development")
    end

ActiveSupport::EnvironmentInquirer 只是让我能够执行Rails.env.production?,而我并不真正关心。

我也可以通过检查 ENV["RAILS_ENV"]ENV["RACK_ENV"] 来模仿这种行为,但如果 Rails.env 发生更改,则不会更改 ENV 变量:

3.0.2 :001 > Rails.env
 => "development" 
3.0.2 :005 > ENV["RAILS_ENV"]
 => "development" 
3.0.2 :006 > ENV["RACK_ENV"]
 => "development" 
3.0.2 :007 > Rails.env = 'test'
 => "test" 
3.0.2 :008 > Rails.env
 => "test" 
3.0.2 :009 > ENV["RAILS_ENV"]
 => "development" 
3.0.2 :010 > ENV["RACK_ENV"]
 => "development" 

或者我可以将类实例化为 PORO,但这似乎也是不好的做法:

module Rails
  def self.env
    @_env ||=
      ENV['RAILS_ENV'] ||
      ENV['RACK_ENV'] ||
      'development'
  end
end

现在我只是在 Rails 抛出名称错误时进行救援:

@environment =
  begin
    Rails.env
  rescue NameError
    'development'
  end

有没有标准的方法来完成这个,或者我的rescue 是最好的方法?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    您可以使用defined? 来检查是否定义了顶级常量Rails

    def rails_env
      ::Rails.env if defined?(::Rails)
    end
    

    如果您想更加安全:

    def rails_env
      ::Rails.env if defined?(::Rails) && ::Rails.respond_to?(:env)
    end
    

    强制使用纯字符串:(而不是 ActiveSupport::EnvironmentInquirer 实例)

    def rails_env
      ::Rails.env.to_s if defined?(::Rails) && ::Rails.respond_to?(:env)
    end
    

    有了上面你可以写:

    @environment = rails_env || 'development'
    

    【讨论】:

    • 回答得很好,我很欣赏你的回答中安全性的升级。
    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 2014-05-08
    • 2023-04-08
    相关资源
    最近更新 更多