класс Rails::Application
Объект Engine с ответственностью за координацию всего процесса загрузки.
Инициализация
Rails::Application отвечает за выполнение инициализаторов всех railties и engines. Он также выполняет некоторые инициализаторы bootstrap (проверьте Rails::Application::Bootstrap) и завершающие инициализаторы, после выполнения всех остальных (проверьте Rails::Application::Finisher).
Configuration
Помимо предоставления той же конфигурации, что и Rails::Engine и Rails::Railtie, объект приложения имеет несколько специфических конфигураций, например, “cache_classes”, “consider_all_requests_local”, “filter_parameters”, “logger” и так далее.
Проверьте Rails::Application::Configuration, чтобы увидеть их все.
Маршруты
Объект приложения также отвечает за хранение маршрутов и их перезагрузку при изменении файлов в режиме разработки.
Средствами
Объект Application также отвечает за построение стека middleware.
Процесс загрузки
Приложение также отвечает за настройку и выполнение процесса загрузки. С момента запроса «config/application.rb» в вашем приложении процесс загрузки проходит так:
1) require "config/boot.rb" to set up 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 241
def config_for(name, env: Rails.env)
yaml = name.is_a?(Pathname) ? name : Pathname.new("#{paths["config"].existent.first}/#{name}.yml")
if yaml.exist?
require "erb"
all_configs = ActiveSupport::ConfigurationFile.parse(yaml).deep_symbolize_keys
config, shared = all_configs[env.to_sym], all_configs[:shared]
if config.is_a?(Hash)
ActiveSupport::OrderedOptions.new.update(shared&.deep_merge(config) || config)
else
config || shared
end
else
raise "Could not load configuration. No such file - #{yaml}"
end
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
# You can also store configurations in a shared section which will be
# merged with the environment configuration
# config/example.yml
shared:
foo:
bar:
baz: 1
development:
foo:
bar:
qux: 2
# development environment
Rails.application.config_for(:example)[:foo][:bar]
# => { baz: 1, qux: 2 } # File railties/lib/rails/application.rb, line 315 def console(&blk) self.class.console(&blk) end
Отправляет любой вызов консоли в экземпляре нового приложения в метод console , определённый в Rails::Railtie.
# File railties/lib/rails/application.rb, line 443 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 508
def eager_load!
if Rails.autoloaders.zeitwerk_enabled?
Rails.autoloaders.each(&:eager_load)
else
super
end
end Загружает код приложения с ускорением.
# File railties/lib/rails/application.rb, line 474
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 261
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.cookies_same_site_protection" => coerce_same_site_protection(config.action_dispatch.cookies_same_site_protection),
"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,
"action_dispatch.permissions_policy" => config.permissions_policy,
)
end
end Хранит некоторые начальные параметры среды, которые будут использованы middleware и модулями для их настройки.
# File railties/lib/rails/application.rb, line 321 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 303
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 332 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 296 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 309 def runner(&blk) self.class.runner(&blk) end
Отправляет любые вызовы runner в экземпляре нового приложения в метод runner , определённый в Rails::Railtie.
# File railties/lib/rails/application.rb, line 426
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.
Во всех остальных средах мы сначала ищем его в ENV, затем в credentials.secret_key_base и, наконец, в secrets.secret_key_base. Для большинства приложений правильное место для его хранения — в зашифрованном файле аутентификационных данных.
# File railties/lib/rails/application.rb, line 401
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 # File railties/lib/rails/application.rb, line 327 def server(&blk) self.class.server(&blk) end
Отправляет любые вызовы сервера в экземпляре нового приложения в метод server , определённый в Rails::Railtie.
Защищенные методы экземпляра
# File railties/lib/rails/application.rb, line 590
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 `bin/rails credentials:edit`"
end
end
© 2004–2020 David Heinemeier Hansson
Licensed under the MIT License.