класс Rails::Application
A Engine ответственный за координацию всего процесса запуска.
Инициализация
Rails::Application отвечает за выполнение всех инициализаторов railties и engines. Также он выполняет некоторые инициализаторы bootstrap (проверьте Rails::Application::Bootstrap) и завершающие инициализаторы после выполнения всех остальных (проверьте Rails::Application::Finisher).
Конфигурация
Помимо предоставления той же конфигурации, что и Rails::Engine и Rails::Railtie, объект приложения имеет несколько специфических конфигураций, например, “cache_classes”, “consider_all_requests_local”, “filter_parameters”, “logger” и так далее.
Проверьте Rails::Application::Configuration, чтобы увидеть их все.
Маршруты
Объект приложения также отвечает за хранение маршрутов и их перезагрузку всякий раз, когда файлы изменяются в режиме разработки.
Средства промежуточного слоя
Приложение также отвечает за создание стека middleware.
Процесс запуска
Приложение также отвечает за настройку и выполнение процесса запуска. С момента, когда вы требуете “config/application.rb” в своем приложении, процесс запуска проходит так:
1) require "config/boot.rb" to setup load paths
2) require railties and engines
3) Define Rails.application as "class MyApp::Application < Rails::Application"
4) Run config.before_configuration callbacks
5) Load config/environments/ENV.rb
6) Run config.before_initialize callbacks
7) Run Railtie#initializer defined by railties, engines and application.
One by one, each engine sets up its load paths, routes and runs its config/initializers/* files.
8) Custom Railtie#initializers added by railties, engines and applications are executed
9) Build the middleware stack and run to_prepare callbacks
10) Run config.before_eager_load and eager_load! if eager_load is true
11) Run config.after_initialize callbacks Несколько приложений
Если вы решите определить несколько приложений, то первое приложение, которое будет инициализировано, будет установлено в Rails.application, если вы не переопределите его другим приложением.
Для создания нового приложения вы можете создать новый экземпляр класса, который уже был создан:
class Application < Rails::Application end first_application = Application.new second_application = Application.new(config: first_application.config)
В приведенном выше примере конфигурация первого приложения использовалась для инициализации второго приложения. Вы также можете использовать initialize_copy для одного из приложений, чтобы создать копию приложения, которая использует общую конфигурацию.
Если вы решите определить задачи Rake, исполнители или инициализаторы в приложении, отличном от Rails.application, то вы должны запустить их вручную.
Атрибуты
Публичные методы класса
# File railties/lib/rails/application.rb, line 103
def create(initial_variable_values = {}, &block)
new(initial_variable_values, &block).run_load_hooks!
end # File railties/lib/rails/application.rb, line 107 def find_root(from) find_root_with_flag "config.ru", from, Dir.pwd end
# File railties/lib/rails/application.rb, line 92 def inherited(base) super Rails.app_class = base add_lib_to_load_path!(find_root(base.called_from)) ActiveSupport.run_load_hooks(:before_configuration, base) end
# File railties/lib/rails/application.rb, line 99 def instance super.run_load_hooks! end
# File railties/lib/rails/application.rb, line 128
def initialize(initial_variable_values = {}, &block)
super()
@initialized = false
@reloaders = []
@routes_reloader = nil
@app_env_config = nil
@ordered_railties = nil
@railties = nil
@message_verifiers = {}
@ran_load_hooks = false
@executor = Class.new(ActiveSupport::Executor)
@reloader = Class.new(ActiveSupport::Reloader)
@reloader.executor = @executor
# are these actually used?
@initial_variable_values = initial_variable_values
@block = block
end Публичные методы экземпляра
# File railties/lib/rails/application.rb, line 222
def config_for(name, env: Rails.env)
if name.is_a?(Pathname)
yaml = name
else
yaml = Pathname.new("#{paths["config"].existent.first}/#{name}.yml")
end
if yaml.exist?
require "erb"
config = YAML.load(ERB.new(yaml.read).result) || {}
config = (config["shared"] || {}).merge(config[env] || {})
ActiveSupport::OrderedOptions.new.tap do |options|
options.update(NonSymbolAccessDeprecatedHash.new(config))
end
else
raise "Could not load configuration. No such file - #{yaml}"
end
rescue Psych::SyntaxError => e
raise "YAML syntax error occurred while parsing #{yaml}. " \
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
"Error: #{e.message}"
end Удобный способ загрузки config/foo.yml для текущей среды Rails.
Пример:
# config/exception_notification.yml: production: url: http://127.0.0.1:8080 namespace: my_app_production development: url: http://localhost:3001 namespace: my_app_development # config/environments/production.rb Rails.application.configure do config.middleware.use ExceptionNotifier, config_for(:exception_notification) end
# File railties/lib/rails/application.rb, line 300 def console(&blk) self.class.console(&blk) end
Пересылает все вызовы консоли в экземпляре нового приложения методу console, определенному в Rails::Railtie.
# File railties/lib/rails/application.rb, line 436 def credentials @credentials ||= encrypted(config.credentials.content_path, key_path: config.credentials.key_path) end
Расшифровывает хеш учетных данных, хранящийся в config/credentials.yml.enc. Этот файл зашифрован с помощью главного ключа Rails, который берется либо из ENV["RAILS_MASTER_KEY"], либо при загрузке config/master.key. Если для текущей среды существует отдельный файл учетных данных, он имеет приоритет. Таким образом, для среды production сначала ищется config/credentials/production.yml.enc, а главный ключ берется из ENV["RAILS_MASTER_KEY"] или при загрузке config/credentials/production.key. Поведение по умолчанию может быть переопределено установкой config.credentials.content_path и config.credentials.key_path.
# File railties/lib/rails/application.rb, line 467
def encrypted(path, key_path: "config/master.key", env_key: "RAILS_MASTER_KEY")
ActiveSupport::EncryptedConfiguration.new(
config_path: Rails.root.join(path),
key_path: Rails.root.join(key_path),
env_key: env_key,
raise_if_missing_key: config.require_master_key
)
end Сокращённый способ расшифровки зашифрованных конфигураций или файлов.
Для любого файла, добавленного с помощью вызова rails encrypted:edit, вызовите read, чтобы расшифровать файл с помощью главного ключа. Главный ключ хранится либо в config/master.key, либо в ENV["RAILS_MASTER_KEY"].
Rails.application.encrypted("config/mystery_man.txt.enc").read
# => "We've met before, haven't we?"
Также возможно интерпретировать зашифрованные файлы YAML с помощью config.
Rails.application.encrypted("config/credentials.yml.enc").config
# => { next_guys_line: "I don't think so. Where was it you think we met?" }
Любые конфигурации верхнего уровня также доступны напрямую в возвращаемом значении:
Rails.application.encrypted("config/credentials.yml.enc").next_guys_line
# => "I don't think so. Where was it you think we met?"
Файлы или конфигурации также могут быть зашифрованы с помощью пользовательского ключа. Чтобы расшифровать с ключом в ENV, используйте:
Rails.application.encrypted("config/special_tokens.yml.enc", env_key: "SPECIAL_TOKENS")
Или для расшифровки с помощью файла, который должен быть исключён из контроля версий, относительно Rails.root:
Rails.application.encrypted("config/special_tokens.yml.enc", key_path: "config/special_tokens.key")
# File railties/lib/rails/application.rb, line 248
def env_config
@app_env_config ||= begin
super.merge(
"action_dispatch.parameter_filter" => config.filter_parameters,
"action_dispatch.redirect_filter" => config.filter_redirect,
"action_dispatch.secret_key_base" => secret_key_base,
"action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
"action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local,
"action_dispatch.logger" => Rails.logger,
"action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner,
"action_dispatch.key_generator" => key_generator,
"action_dispatch.http_auth_salt" => config.action_dispatch.http_auth_salt,
"action_dispatch.signed_cookie_salt" => config.action_dispatch.signed_cookie_salt,
"action_dispatch.encrypted_cookie_salt" => config.action_dispatch.encrypted_cookie_salt,
"action_dispatch.encrypted_signed_cookie_salt" => config.action_dispatch.encrypted_signed_cookie_salt,
"action_dispatch.authenticated_encrypted_cookie_salt" => config.action_dispatch.authenticated_encrypted_cookie_salt,
"action_dispatch.use_authenticated_cookie_encryption" => config.action_dispatch.use_authenticated_cookie_encryption,
"action_dispatch.encrypted_cookie_cipher" => config.action_dispatch.encrypted_cookie_cipher,
"action_dispatch.signed_cookie_digest" => config.action_dispatch.signed_cookie_digest,
"action_dispatch.cookies_serializer" => config.action_dispatch.cookies_serializer,
"action_dispatch.cookies_digest" => config.action_dispatch.cookies_digest,
"action_dispatch.cookies_rotations" => config.action_dispatch.cookies_rotations,
"action_dispatch.use_cookies_with_metadata" => config.action_dispatch.use_cookies_with_metadata,
"action_dispatch.content_security_policy" => config.content_security_policy,
"action_dispatch.content_security_policy_report_only" => config.content_security_policy_report_only,
"action_dispatch.content_security_policy_nonce_generator" => config.content_security_policy_nonce_generator,
"action_dispatch.content_security_policy_nonce_directives" => config.content_security_policy_nonce_directives
)
end
end Хранит некоторые начальные параметры среды Rails, которые будут использованы посредниками и движками для их настройки.
# File railties/lib/rails/application.rb, line 306 def generators(&blk) self.class.generators(&blk) end
Пересылает все вызовы генераторов в экземпляре нового приложения методу generators, определенному в Rails::Railtie.
# File railties/lib/rails/application.rb, line 149 def initialized? @initialized end
Возвращает true, если приложение инициализировано.
# File railties/lib/rails/application.rb, line 288
def initializer(name, opts = {}, &block)
self.class.initializer(name, opts, &block)
end Отправляет инициализаторы методу initializer, определённому в модуле Rails::Initializable. Каждый класс Rails::Application имеет свой набор инициализаторов, как определено модулем Initializable.
# File railties/lib/rails/application.rb, line 311 def isolate_namespace(mod) self.class.isolate_namespace(mod) end
Отправляет метод isolate_namespace вверх по цепочке наследования.
# File railties/lib/rails/application.rb, line 173
def key_generator
# number of iterations selected based on consultation with the google security
# team. Details at https://github.com/rails/rails/pull/6952#issuecomment-7661220
@caching_key_generator ||= ActiveSupport::CachingKeyGenerator.new(
ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)
)
end Возвращает генератор ключей приложения.
# File railties/lib/rails/application.rb, line 199
def message_verifier(verifier_name)
@message_verifiers[verifier_name] ||= begin
secret = key_generator.generate_key(verifier_name.to_s)
ActiveSupport::MessageVerifier.new(secret)
end
end Возвращает объект верификатора сообщений.
Этот верификатор может использоваться для генерации и проверки подписанных сообщений в приложении.
Рекомендуется не использовать один и тот же верификатор для разных задач, поэтому вы можете получить разные верификаторы, передавая аргумент verifier_name.
Параметры
-
verifier_name- имя верификатора сообщений.
Примеры
message = Rails.application.message_verifier('sensitive_data').generate('my sensible data')
Rails.application.message_verifier('sensitive_data').verify(message)
# => 'my sensible data'
См. документацию ActiveSupport::MessageVerifier для получения дополнительной информации.
# File railties/lib/rails/application.rb, line 281 def rake_tasks(&block) self.class.rake_tasks(&block) end
Если вы пытаетесь определить набор задач Rake в экземпляре, они будут переданы задачам Rake, определённым в классе приложения.
# File railties/lib/rails/application.rb, line 168 def reload_routes! routes_reloader.reload! end
Перезагружает маршруты приложения независимо от того, изменились они или нет.
# File railties/lib/rails/application.rb, line 294 def runner(&blk) self.class.runner(&blk) end
Пересылает все вызовы runner в экземпляре нового приложения методу runner, определённому в Rails::Railtie.
# File railties/lib/rails/application.rb, line 419
def secret_key_base
if Rails.env.development? || Rails.env.test?
secrets.secret_key_base ||= generate_development_secret
else
validate_secret_key_base(
ENV["SECRET_KEY_BASE"] || credentials.secret_key_base || secrets.secret_key_base
)
end
end Значение #secret_key_base используется в качестве секретного входа для генератора ключей приложения, который, в свою очередь, используется для создания всех MessageVerifiers/MessageEncryptors, включая те, которые подписывают и шифруют куки.
В режимах разработки и тестирования оно генерируется случайным образом и сохраняется во временном файле в tmp/development_secret.txt.
Во всех остальных средах мы ищем его сначала в переменных среды, затем в credentials.secret_key_base и, наконец, в secrets.secret_key_base. Для большинства приложений правильное место для его хранения — в зашифрованном файле учетных данных.
# File railties/lib/rails/application.rb, line 394
def secrets
@secrets ||= begin
secrets = ActiveSupport::OrderedOptions.new
files = config.paths["config/secrets"].existent
files = files.reject { |path| path.end_with?(".enc") } unless config.read_encrypted_secrets
secrets.merge! Rails::Secrets.parse(files, env: Rails.env)
# Fallback to config.secret_key_base if secrets.secret_key_base isn't set
secrets.secret_key_base ||= config.secret_key_base
secrets
end
end Возвращает секреты, добавленные в config/secrets.yml.
Пример:
development: secret_key_base: 836fa3665997a860728bcb9e9a1e704d427cfc920e79d847d79c8a9a907b9e965defa4154b2b86bdec6930adbe33f21364523a6f6ce363865724549fdfc08553 test: secret_key_base: 5a37811464e7d378488b0f073e2193b093682e4e21f5d6f3ae0a4e1781e61a351fdc878a843424e81c73fb484a40d23f92c8dafac4870e74ede6e5e174423010 production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> namespace: my_app_production
Rails.application.secrets.namespace возвращает my_app_production в среде производства.
Защищённые методы экземпляра
# File railties/lib/rails/application.rb, line 574
def validate_secret_key_base(secret_key_base)
if secret_key_base.is_a?(String) && secret_key_base.present?
secret_key_base
elsif secret_key_base
raise ArgumentError, "`secret_key_base` for #{Rails.env} environment must be a type of String`"
else
raise ArgumentError, "Missing `secret_key_base` for '#{Rails.env}' environment, set this string with `rails credentials:edit`"
end
end
© 2004–2019 David Heinemeier Hansson
Licensed under the MIT License.