класс Rails::Generators::Base
Публичные методы класса
# File railties/lib/rails/generators/base.rb, line 236 def self.base_root __dir__ 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 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 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 Вызывает генератор на основе значения, заданного пользователем для заданного параметра «имя». При вызове этого метода создаётся параметр класса, и вы можете задать хэш для его настройки.
Примеры
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 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 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 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 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 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.