класс Rails::Generators::Base
Публичные методы класса
# File railties/lib/rails/generators/base.rb, line 222 def self.base_root __dir__ end
Возвращает базовый корень для общего набора генераторов. Используется для динамической угадывания корня исходного кода по умолчанию.
# File railties/lib/rails/generators/base.rb, line 213 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 35
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 55 def self.hide! Rails::Generators.hide_namespace(namespace) end
Удобный метод для скрытия данного генератора из доступных при выполнении команды rails generate.
# File railties/lib/rails/generators/base.rb, line 168
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
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
Приведённый пример создаст опцию фреймворка тестирования и вызовет генератор на основе значения, предоставленного пользователем.
Например, если пользователь вызывает генератор контроллера следующим образом:
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"
Переключатели
Все хуки поставляются с переключателями для пользовательского интерфейса. Если вы не хотите использовать фреймворк тестирования, вы можете сделать:
rails generate controller Account --skip-test-framework
Или аналогично:
rails generate controller Account --no-test-framework
Логические хуки
В некоторых случаях вам может потребоваться предоставить логический хук. Например, разработчики webrat могут захотеть сделать webrat доступным для генератора контроллеров. Это можно сделать так:
Rails::Generators::ControllerGenerator.hook_for :webrat, type: :boolean
Затем, если вы хотите вызвать webrat, просто укажите:
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 48 def self.namespace(name = nil) return super if name @namespace ||= super.sub(/_generator$/, "").sub(/:generators:/, ":") end
Удобный метод для получения пространства имён из имени класса. Он такой же, как Thor по умолчанию, за исключением того, что генератор в конце класса удаляется.
# File railties/lib/rails/generators/base.rb, line 194
def self.remove_hook_for(*names)
remove_invocation(*names)
names.each do |name|
hooks.delete(name)
end
end Удаляет ранее добавленный хук.
remove_hook_for :orm
# File railties/lib/rails/generators/base.rb, line 28 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 385
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 314
def self.banner # :doc:
"rails generate #{namespace.sub(/^rails:/, '')} #{arguments.map(&:usage).join(' ')} [options]".gsub(/\s+/, " ")
end Использование баннера по умолчанию Rails.
# File railties/lib/rails/generators/base.rb, line 319
def self.base_name # :doc:
@base_name ||= begin
if base = name.to_s.split("::").first
base.underscore
end
end
end Устанавливает ::base_name, учитывая текущее пространство имён класса.
# File railties/lib/rails/generators/base.rb, line 346 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 351
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 411 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 340 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 329
def self.generator_name # :doc:
@generator_name ||= begin
if generator = name.to_s.split("::").last
generator.sub!(/Generator$/, "")
generator.underscore
end
end
end Удаляет пространства имён и получает имя генератора. Например, Rails::Generators::ModelGenerator вернёт «model» в качестве имени генератора.
# File railties/lib/rails/generators/base.rb, line 403
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 272
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 287
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 281 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 297 def namespace # :doc: Rails::Generators.namespace end
# File railties/lib/rails/generators/base.rb, line 301 def namespaced? # :doc: !options[:skip_namespace] && namespace end
# File railties/lib/rails/generators/base.rb, line 309
def namespaced_path # :doc:
@namespaced_path ||= namespace_dirs.join("/")
end # File railties/lib/rails/generators/base.rb, line 292
def wrap_with_namespace(content) # :doc:
content = indent(content).chomp
"module #{namespace.name}\n#{content}\nend\n"
end
© 2004–2019 David Heinemeier Hansson
Licensed under the MIT License.