I have RoR experience, but I'm working on my first gem.
The gem is specifically for use in Rails apps and I want to rely on Rails.env
in several cases.
I know requiring Rails in the .gemspec
is a bad idea (at least bad practice) because Rails is big and comes with lots of its own dependencies.
But Rails.env
isn't exactly an extension I can just pull in.
Rails.env
functionality comes from railties
which itself relies on active_support
, action_dispatch
and a bunch of other things:
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
just gives me the ability to do Rails.env.production?
which I don't really care about.
I could also just mimic this behavior by checking for ENV["RAILS_ENV"]
and ENV["RACK_ENV"]
but if Rails.env
is changed, that doesn't change the ENV
variables:
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"
Or I could just instantiate the class as a PORO, but this also seems like bad practice:
module Rails
def self.env
@_env ||=
ENV['RAILS_ENV'] ||
ENV['RACK_ENV'] ||
'development'
end
end
Right now I'm just rescuing when Rails
throws a name error:
@environment =
begin
Rails.env
rescue NameError
'development'
end
Is there a standard way to accomplish this or is my rescue
the best way to proceed?
CodePudding user response:
You could use defined?
to check whether a top-level constant Rails
is defined:
def rails_env
::Rails.env if defined?(::Rails)
end
if you want to be extra safe:
def rails_env
::Rails.env if defined?(::Rails) && ::Rails.respond_to?(:env)
end
To enforce a plain string: (instead of a ActiveSupport::EnvironmentInquirer
instance)
def rails_env
::Rails.env.to_s if defined?(::Rails) && ::Rails.respond_to?(:env)
end
With the above you could write:
@environment = rails_env || 'development'