#ruby-on-rails #ruby #rails-generators
#ruby-on-rails #ruby #rails-генераторы
Вопрос:
Вероятно, я что-то недопонимаю с рабочим процессом rails generators, но после нескольких дней поиска по коду и документации я не могу найти решение проблемы.
Я создал пользовательский генератор каркасов для добавления некоторых дополнительных файлов и запустил сгенерированную миграцию сразу после создания файлов каркасов. С тем же подходом я пытаюсь откатить миграцию, поскольку первым делом, когда выполняется команда rails destroy my_scaffold, выполняется откат до удаления файла миграции.
мой пользовательский код генератора scaffold_meta.rb, который запускает команду db: migrate после создания файла миграции. Это рабочая часть.
require 'generators/resource/resource_generator'
module Rails
module Generators
class ScaffoldMetaGenerator < ResourceGenerator # :nodoc:
remove_hook_for :resource_controller
remove_class_option :actions
class_option :stylesheets, type: :boolean, desc: "Generate Stylesheets"
class_option :stylesheet_engine, desc: "Engine for Stylesheets"
class_option :assets, type: :boolean
class_option :resource_route, type: :boolean
class_option :scaffold_stylesheet, type: :boolean
class_option :steps, type: :boolean, default: 'step'
def handle_skip
@options = @options.merge(stylesheets: false) unless options[:assets]
@options = @options.merge(stylesheet_engine: false) unless options[:stylesheets] amp;amp; options[:scaffold_stylesheet]
end
hook_for :scaffold_controller, required: true
hook_for :assets do |assets|
invoke assets, [controller_name]
end
hook_for :stylesheet_engine do |stylesheet_engine|
if behavior == :invoke
invoke stylesheet_engine, [controller_name]
end
end
def mirate_if_invoke
if behavior == :invoke
say behavior.to_s ' migrate', :green
rake("db:migrate --trace")
end
end
invoke 'step'
end
end
end
предыдущий код заканчивается вызовом моего пользовательского model_generator.rb, который пытается выполнить откат перед удалением файла миграции.
require 'rails/generators/model_helpers'
module Rails
module Generators
class ModelGenerator < Rails::Generators::NamedBase # :nodoc:
include Rails::Generators::ModelHelpers
def rollback_if_revoke
if self.behavior == :revoke
say behavior.to_s ' rollback', :red
rake("db:rollback --trace")
end
end
argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
hook_for :orm, required: true, desc: "ORM to be invoked"
end
end
end
вывод генератора с поведением отзыва показывает, как предположительно вызывается rake db: rollback, но не имеет никакого эффекта.
$rails d scaffold_meta pez edad:integer nombre
Running via Spring preloader in process 8888
***revoke rollback
rake db:rollback --trace***
invoke active_record
remove db/migrate/20161013145014_create_pezs.rb
remove app/models/pez.rb
invoke rspec`
Любая помощь была бы очень признательна.
Ответ №1:
Я столкнулся с той же проблемой в Rails 4.7.0.
Я заметил, что rake db:rollback
это работало, когда behavior == :invoke
, но ничего не делало, когда behavior == :revoke
.
Глядя на rake
источник метода:
# GEMDIR/railties-4.2.7/lib/rails/generators/actions.rb:
# Runs the supplied rake task
#
# rake("db:migrate")
# rake("db:migrate", env: "production")
# rake("gems:install", sudo: true)
def rake(command, options={})
log :rake, command
env = options[:env] || ENV["RAILS_ENV"] || 'development'
sudo = options[:sudo] amp;amp; RbConfig::CONFIG['host_os'] !~ /mswin|mingw/ ? 'sudo ' : ''
in_root { run("#{sudo}#{extify(:rake)} #{command} RAILS_ENV=#{env}", verbose: false) }
end
run
Метод, вызываемый в переданном блоке in_root
, происходит из Thor::Actions
модуля:
# GEMDIR/thor-0.19.1/lib/thor/actions.rb:
# Executes a command returning the contents of the command.
#
# ==== Parameters
# command<String>:: the command to be executed.
# config<Hash>:: give :verbose => false to not log the status, :capture => true to hide to output. Specify :with
# to append an executable to command execution.
#
# ==== Example
#
# inside('vendor') do
# run('ln -s ~/edge rails')
# end
#
def run(command, config = {})
return unless behavior == :invoke
destination = relative_to_original_destination_root(destination_root, false)
desc = "#{command} from #{destination.inspect}"
if config[:with]
desc = "#{File.basename(config[:with].to_s)} #{desc}"
command = "#{config[:with]} #{command}"
end
say_status :run, desc, config.fetch(:verbose, true)
unless options[:pretend]
config[:capture] ? `#{command}` : system("#{command}")
end
end
Первая строка в методе return unless behavior == :invoke
замыкает вызов для выполнения исходной rake 'db:rollback'
команды.
У Raildies также есть Actions
модуль ( Rails::Generators::Actions
), который, похоже, следует invoke
revoke
logic Тора. Итак, я пришел к выводу, что лучше просто не пытаться выполнить откат, когда генератор находится в :revoke
состоянии.
В итоге я следовал соглашению Rails для создания файла миграции :invoke
, :revoke
его уничтожения и полагаюсь на то, что пользователь выполнит его вручную rake db:migrate
или rake db:rollback
при необходимости.
Надеюсь, это поможет.