класс Rails::Generators::Base
Методы публичного класса
# File railties/lib/rails/generators/base.rb, line 396
def self.add_shebang_option! # :doc:
class_option :ruby, type: :string, aliases: "-r", default: Thor::Util.ruby_command,
desc: "Path to the Ruby binary of your choice", banner: "PATH"
no_tasks {
define_method :shebang do
@shebang ||= begin
command = if options[:ruby] == Thor::Util.ruby_command
"/usr/bin/env #{File.basename(Thor::Util.ruby_command)}"
else
options[:ruby]
end
"#!#{command}"
end
end
}
end Небольшая макрокоманда для добавления Ruby в качестве опции генератора с соответствующим значением по умолчанию плюс вспомогательный метод экземпляра, называемый shebang.
# File railties/lib/rails/generators/base.rb, line 329
def self.banner # :doc:
"bin/rails generate #{namespace.delete_prefix("rails:")} #{arguments.map(&:usage).join(' ')} [options]".gsub(/\s+/, " ")
end Использование стандартного баннера Rails.
# File railties/lib/rails/generators/base.rb, line 334
def self.base_name # :doc:
@base_name ||= if base = name.to_s.split("::").first
base.underscore
end
end Устанавливает base_name с учётом текущего пространства имён класса.
# File railties/lib/rails/generators/base.rb, line 236 def self.base_root __dir__ end
Возвращает базовый корень для общего набора генераторов. Это используется для динамического определения корня исходных файлов по умолчанию.
# File railties/lib/rails/generators/base.rb, line 357 def self.default_aliases_for_option(name, options) # :doc: default_for_option(Rails::Generators.aliases, name, options, options[:aliases]) end
Возвращает значения псевдонимов по умолчанию для заданного имени опции, выполняя поиск в Rails::Generators.aliases.
# File railties/lib/rails/generators/base.rb, line 362
def self.default_for_option(config, name, options, default) # :doc:
if generator_name && (c = config[generator_name.to_sym]) && c.key?(name)
c[name]
elsif base_name && (c = config[base_name.to_sym]) && c.key?(name)
c[name]
elsif config[:rails].key?(name)
config[:rails][name]
else
default
end
end Возвращает значение по умолчанию для заданного имени опции, выполняя поиск в config.
# File railties/lib/rails/generators/base.rb, line 422 def self.default_generator_root # :doc: path = File.expand_path(File.join(base_name, generator_name), base_root) path if File.exist?(path) end
# File railties/lib/rails/generators/base.rb, line 227 def self.default_source_root return unless base_name && generator_name return unless default_generator_root path = File.join(default_generator_root, "templates") path if File.exist?(path) end
Возвращает корень исходных файлов по умолчанию для данного генератора. Используется внутри Rails для установки корня исходных файлов генераторов. Если требуется настройка корня исходных файлов, используйте source_root.
# File railties/lib/rails/generators/base.rb, line 351 def self.default_value_for_option(name, options) # :doc: default_for_option(Rails::Generators.options, name, options, options[:default]) end
Возвращает значение по умолчанию для заданного имени опции, выполняя поиск в Rails::Generators.options.
# File railties/lib/rails/generators/base.rb, line 41
def self.desc(description = nil)
return super if description
@desc ||= if usage_path
ERB.new(File.read(usage_path)).result(binding)
else
"Description:\n Create #{base_name.humanize.downcase} files for #{generator_name} generator."
end
end Попытка получить описание из файла USAGE в папке выше корня исходных файлов, в противном случае используется описание по умолчанию.
# File railties/lib/rails/generators/base.rb, line 342
def self.generator_name # :doc:
@generator_name ||= if generator = name.to_s.split("::").last
generator.delete_suffix!("Generator")
generator.underscore
end
end Удаляет пространства имён и получает имя генератора. Например, Rails::Generators::ModelGenerator вернёт «model» в качестве имени генератора.
# File railties/lib/rails/generators/base.rb, line 61 def self.hide! Rails::Generators.hide_namespace(namespace) end
Вспомогательный метод для скрытия этого генератора из доступных при выполнении команды rails generator.
# File railties/lib/rails/generators/base.rb, line 174
def self.hook_for(*names, &block)
options = names.extract_options!
in_base = options.delete(:in) || base_name
as_hook = options.delete(:as) || generator_name
names.each do |name|
unless class_options.key?(name)
defaults = if options[:type] == :boolean
{}
elsif [true, false].include?(default_value_for_option(name, options))
{ banner: "" }
else
{ desc: "#{name.to_s.humanize} to be invoked", banner: "NAME" }
end
class_option(name, defaults.merge!(options))
end
klass = self
singleton_class.define_method("#{name}_generator") do
value = class_options[name].default
Rails::Generators.find_by_namespace(klass.generator_name, value)
end
hooks[name] = [ in_base, as_hook ]
invoke_from_option(name, options, &block)
end
end Вызов генератора на основе значения, предоставленного пользователем для заданной опции с именем «name». Когда вызывается этот метод, создаётся опция класса, и вы можете задать хэш для её настройки.
Примеры
module Rails::Generators
class ControllerGenerator < Base
hook_for :test_framework, aliases: "-t"
end
end
Приведённый выше пример создаст опцию тестовой среды и вызовет генератор на основе введённого пользователем значения.
Например, если пользователь вызовет генератор контроллеров так:
$ bin/rails generate controller Account --test-framework=test_unit
Генератор контроллеров затем попытается вызвать следующие генераторы:
"rails:test_unit", "test_unit:controller", "test_unit"
Обратите внимание, что «rails:generators:test_unit» также может быть загружен; Rails ищет первые и последние части пространства имён. Это позволяет любому тестовому фреймворку подключаться к Rails, если он предоставляет указанные выше хуки.
Опции
Первая и последняя части, используемые для поиска вызываемого генератора, определяются на основе вызова класса hook_for, как показано в примере выше. Это можно настроить с помощью двух опций: :in и :as.
Предположим, вы создаёте генератор, которому нужно вызвать генератор контроллеров из test unit. Ваша первая попытка:
class AwesomeGenerator < Rails::Generators::Base hook_for :test_framework end
В этом случае поиск test_unit в качестве входных данных будет:
"test_unit:awesome", "test_unit"
Что не является желаемым поиском. Вы можете изменить его, указав опцию :as:
class AwesomeGenerator < Rails::Generators::Base hook_for :test_framework, as: :controller end
И теперь он будет искать:
"test_unit:controller", "test_unit"
Аналогично, если вы хотите также искать в пространстве имён rails, вам нужно указать значение :in:
class AwesomeGenerator < Rails::Generators::Base hook_for :test_framework, in: :rails, as: :controller end
И поиск будет таким же, как и раньше:
"rails:test_unit", "test_unit:controller", "test_unit"
Переключатели
Все хуки поставляются с переключателями для пользовательского интерфейса. Если вы не хотите использовать какой-либо тестовый фреймворк, вы можете сделать так:
$ bin/rails generate controller Account --skip-test-framework
Или аналогично:
$ bin/rails generate controller Account --no-test-framework
Булевы хуки
В некоторых случаях вам может понадобиться булевой хук. Например, разработчики webrat могут захотеть иметь webrat доступным для генератора контроллеров. Этого можно достичь следующим образом:
Rails::Generators::ControllerGenerator.hook_for :webrat, type: :boolean
Затем, если вы хотите вызвать webrat, просто укажите:
$ bin/rails generate controller Account --webrat
Поиск хуков аналогичен вышеупомянутому:
"rails:generators:webrat", "webrat:generators:controller", "webrat"
Пользовательские вызовы
Вы также можете передать блок в hook_for для настройки того, как будет вызываться хук. Блок получает два аргумента: экземпляр текущего класса и класс, который будет вызываться.
Например, в генераторе ресурсов контроллер должен вызываться с множественным именем класса. Но по умолчанию он вызывается с тем же именем, что и генератор ресурсов, то есть единственным. Чтобы изменить это, мы можем передать блок, чтобы настроить, как вызывается контроллер.
hook_for :resource_controller do |instance, controller| instance.invoke controller, [ instance.name.pluralize ] end
# File railties/lib/rails/generators/base.rb, line 54
def self.namespace(name = nil)
return super if name
@namespace ||= super.delete_suffix("_generator").sub(/:generators:/, ":")
end Вспомогательный метод для получения пространства имён из имени класса. Он аналогичен стандартному Thor, за исключением того, что генератор в конце класса удаляется.
# File railties/lib/rails/generators/base.rb, line 207
def self.remove_hook_for(*names)
remove_invocation(*names)
names.each do |name|
singleton_class.undef_method("#{name}_generator")
hooks.delete(name)
end
end Удаление ранее добавленного хука.
remove_hook_for :orm
# File railties/lib/rails/generators/base.rb, line 34 def self.source_root(path = nil) @_source_root = path if path @_source_root ||= default_source_root end
Возвращает корень исходных файлов для этого генератора, используя default_source_root в качестве значения по умолчанию.
# File railties/lib/rails/generators/base.rb, line 414
def self.usage_path # :doc:
paths = [
source_root && File.expand_path("../USAGE", source_root),
default_generator_root && File.join(default_generator_root, "USAGE")
]
paths.compact.detect { |path| File.exist? path }
end Приватные методы экземпляра
# File railties/lib/rails/generators/base.rb, line 287
def extract_last_module(nesting) # :doc:
nesting.inject(Object) do |last_module, nest|
break unless last_module.const_defined?(nest, false)
last_module.const_get(nest)
end
end Извлекает последний модуль из массива вложенных модулей.
# File railties/lib/rails/generators/base.rb, line 302
def indent(content, multiplier = 2) # :doc:
spaces = " " * multiplier
content.each_line.map { |line| line.blank? ? line : "#{spaces}#{line}" }.join
end # File railties/lib/rails/generators/base.rb, line 296 def module_namespacing(&block) # :doc: content = capture(&block) content = wrap_with_namespace(content) if namespaced? concat(content) end
Оборачивает блок с именем пространства текущего приложения, если пространство имен существует и не пропущено.
# File railties/lib/rails/generators/base.rb, line 312 def namespace # :doc: Rails::Generators.namespace end
# File railties/lib/rails/generators/base.rb, line 316 def namespaced? # :doc: !options[:skip_namespace] && namespace end
# File railties/lib/rails/generators/base.rb, line 324
def namespaced_path # :doc:
@namespaced_path ||= namespace_dirs.join("/")
end # File railties/lib/rails/generators/base.rb, line 307
def wrap_with_namespace(content) # :doc:
content = indent(content).chomp
"module #{namespace.name}\n#{content}\nend\n"
end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.