From de0e63e1ff0a1cdbb3fe817d03cb3e33a9de2ccc Mon Sep 17 00:00:00 2001 From: Mohammed Date: Fri, 5 Aug 2022 12:49:03 +0200 Subject: [PATCH 1/2] add base generators --- .../request_migrations/install_generator.rb | 28 +++++++++++++++++++ .../request_migrations/migration_generator.rb | 28 +++++++++++++++++++ lib/generators/templates/base_migration.rb.tt | 26 +++++++++++++++++ lib/generators/templates/migration.rb.tt | 21 ++++++++++++++ .../templates/request_migrations.rb.tt | 18 ++++++++++++ request_migrations.gemspec | 1 + spec/generators/install_generator_spec.rb | 28 +++++++++++++++++++ spec/generators/migration_generator_spec.rb | 26 +++++++++++++++++ 8 files changed, 176 insertions(+) create mode 100644 lib/generators/request_migrations/install_generator.rb create mode 100644 lib/generators/request_migrations/migration_generator.rb create mode 100644 lib/generators/templates/base_migration.rb.tt create mode 100644 lib/generators/templates/migration.rb.tt create mode 100644 lib/generators/templates/request_migrations.rb.tt create mode 100644 spec/generators/install_generator_spec.rb create mode 100644 spec/generators/migration_generator_spec.rb diff --git a/lib/generators/request_migrations/install_generator.rb b/lib/generators/request_migrations/install_generator.rb new file mode 100644 index 0000000..64ca93e --- /dev/null +++ b/lib/generators/request_migrations/install_generator.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'rails/generators' + +module RequestMigrations + # Intial Files Generator class + class InstallGenerator < Rails::Generators::Base + namespace 'request_migrations:install' + + desc 'Generates a request_migrations initializer configuration plus a base migration file.' + + source_root File.expand_path('templates', __dir__) + + class_option :api_version, type: :string, aliases: '-v', default: '1.1', desc: 'API current version' + class_option :api_prev_version, type: :string, aliases: '-pv', default: '1.0', desc: 'API previoues version' + + def copy_base_file + copy_file '../../templates/base_migration.rb', 'app/migrations/base_migration.rb' + end + + def create_initializer + @version = options[:api_version] || '1.1' + @prev_version = options[:api_prev_version] || '1.0' + + template '../../templates/request_migrations.rb', 'config/initializers/request_migrations.rb' + end + end +end diff --git a/lib/generators/request_migrations/migration_generator.rb b/lib/generators/request_migrations/migration_generator.rb new file mode 100644 index 0000000..760de0a --- /dev/null +++ b/lib/generators/request_migrations/migration_generator.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'rails/generators' + +module RequestMigrations + # A default migration generator class + class MigrationGenerator < Rails::Generators::NamedBase + namespace 'request_migrations:migration' + + ACTIONS = %w[index show create update delete].freeze + DESCRIPTION = 'description goes here' + + source_root File.expand_path('../templates', __dir__) + + class_option :actions, aliases: '-a', type: :array, + desc: "Select specific actions to generate (#{ACTIONS.join(', ')})" + + class_option :description, aliases: '-d', type: :string, + desc: 'Add migration description' + + def start + @actions = options[:actions] || ACTIONS + @description = options[:description] || DESCRIPTION + + template 'migration.rb', "app/migrations/#{file_name}_migration.rb" + end + end +end diff --git a/lib/generators/templates/base_migration.rb.tt b/lib/generators/templates/base_migration.rb.tt new file mode 100644 index 0000000..b6bd518 --- /dev/null +++ b/lib/generators/templates/base_migration.rb.tt @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +class BaseMigration < RequestMigrations::Migration + # Provide a useful description of the change + # description %(description goes here) + + # Migrate inputs that contain a resource. The migration should mutate + # the input, whatever that may be. + # Replace resource below with the correct resource name, for eg: user + # migrate if: -> data { data in type: 'resource' } do |data| + # Mutate resource data + # Check link for more details https://github.com/keygen-sh/request_migrations#usage + # end + + # Migrate the response. This is where you provide the migration input. + # Replace api/v1/resources below with the correct endpoint name, for eg: api/v1/users + # response if: -> res { res.successful? && res.request.params in controller: 'api/v1/resources', + # action: 'show' } do |res| + # data = JSON.parse(res.body, symbolize_names: true) + + # Call our migrate definition above + # migrate!(data) + + # res.body = JSON.generate(data) + # end +end diff --git a/lib/generators/templates/migration.rb.tt b/lib/generators/templates/migration.rb.tt new file mode 100644 index 0000000..a822d1e --- /dev/null +++ b/lib/generators/templates/migration.rb.tt @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class class <%= file_name.singularize.camelize %>Migration < RequestMigrations::Migration + # Provide a useful description of the change + description %(<%= @description %>) + + # Migrate inputs that contain a resource_name. The migration should mutate + # the input, whatever that may be. + migrate if: -> data { data in type: 'resource_name' } do |data| + data[:key] = "value" + end + + response if: -> res { res.request.params in action: <%= @actions.map{ |action| "'#{action}'" }.join(' | ') %> } do |res| + data = JSON.parse(res.body, symbolize_names: true) + + # Call our migrate definition above + migrate!(data) + + res.body = JSON.generate(data) + end +end diff --git a/lib/generators/templates/request_migrations.rb.tt b/lib/generators/templates/request_migrations.rb.tt new file mode 100644 index 0000000..9e941cc --- /dev/null +++ b/lib/generators/templates/request_migrations.rb.tt @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +RequestMigrations.configure do |config| + # Define a resolver to determine the target version. Here, you can perform + # a lookup on the current user using request parameters, or simply use + # a header like we are here, defaulting to the latest version. + config.request_version_resolver = -> request { + # request.headers.fetch('Foo-Version') { config.current_version } + } + + # Define the latest version of our application. + config.current_version = <%= @version %> + + # Define previous versions and their migrations, in descending order. + config.versions = { + '<%= @prev_version %>' => %i[base_migration] + } +end diff --git a/request_migrations.gemspec b/request_migrations.gemspec index 5b89f7f..5499675 100644 --- a/request_migrations.gemspec +++ b/request_migrations.gemspec @@ -18,4 +18,5 @@ Gem::Specification.new do |spec| spec.add_dependency "semverse", "~> 3.0" spec.add_development_dependency "rspec-rails" + spec.add_development_dependency "generator_spec" end diff --git a/spec/generators/install_generator_spec.rb b/spec/generators/install_generator_spec.rb new file mode 100644 index 0000000..c2dc218 --- /dev/null +++ b/spec/generators/install_generator_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'generator_spec/test_case' +require 'generators/request_migrations/install_generator' + +RSpec.describe RequestMigrations::InstallGenerator, type: :generator do + include GeneratorSpec::TestCase + + destination File.expand_path('tmp', __dir__) + + after do + prepare_destination # cleanup the tmp directory + end + + before do + prepare_destination + run_generator + end + + it 'generates app/migrations/base_migration.rb' do + assert_file('app/migrations/base_migration.rb') + end + + it 'generates config/initializers/request_migrations.rb' do + assert_file('config/initializers/request_migrations.rb') + end +end diff --git a/spec/generators/migration_generator_spec.rb b/spec/generators/migration_generator_spec.rb new file mode 100644 index 0000000..5e1926f --- /dev/null +++ b/spec/generators/migration_generator_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'generator_spec/test_case' +require 'generators/request_migrations/migration_generator' + +RSpec.describe RequestMigrations::MigrationGenerator, type: :generator do + include GeneratorSpec::TestCase + + let(:file_name) { 'file_name' } + + destination File.expand_path('tmp', __dir__) + + after do + prepare_destination # cleanup the tmp directory + end + + before do + prepare_destination + run_generator [file_name] + end + + it 'generates app/migrations/#{file_name}_migration.rb' do + assert_file("app/migrations/#{file_name}_migration.rb") + end +end From 6175f015c048fdf0618f71d3bb85bfa9a84c548a Mon Sep 17 00:00:00 2001 From: Mohammed Date: Sat, 20 Aug 2022 15:51:57 +0200 Subject: [PATCH 2/2] add base generators instructions to Readme.md --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 24c1156..3886eb3 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,21 @@ Or install it yourself as: $ gem install request_migrations ``` +Next, you need to run generator: + +```bash +$ rails generate request_migrations:install # --api_version 1.1 --api_prev_version 1.0 # or -v 1.1 -pv 1.0 +``` + +This will generate the initializer file `request_migrations.rb` under `initializers` folder, and BaseMigration file `base_migration.rb` under `app/migrations/` folder as it's recommended folder for migrations files. + +Also, you can add more migration files using + + +```bash +$ rails generate request_migrations:migration user # --actions create update --description "doing some data migration" or -a create update -d "doing some data migration" +``` + ## Supported Rubies **`request_migrations` supports Ruby 3.1 and above.** We encourage you to upgrade if you're on an older