класс 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 Возвращает значение по умолчанию для заданного имени опции, выполняя поиск в конфигурации.
# 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 Вызывает генератор, основанный на значении, предоставленном пользователем для заданной опции с именем «имя». Опция класса создаётся при вызове этого метода, и вы можете задать хэш для его настройки.
Примеры
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.