From 3fd1df8cf706c0a7b5740061c1ce1ade5b318e0e Mon Sep 17 00:00:00 2001 From: Luiz Eduardo Kowalski Date: Sun, 6 Jul 2025 01:31:51 +0200 Subject: [PATCH 1/3] Feature: Operation generator --- .../active_operator/operation_generator.rb | 31 +++++++++ .../templates/operation.rb.erb | 22 ++++++ .../operation_generator_test.rb | 69 +++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 lib/generators/active_operator/operation_generator.rb create mode 100644 lib/generators/active_operator/templates/operation.rb.erb create mode 100644 test/generators/active_operator/operation_generator_test.rb diff --git a/lib/generators/active_operator/operation_generator.rb b/lib/generators/active_operator/operation_generator.rb new file mode 100644 index 0000000..eeeb164 --- /dev/null +++ b/lib/generators/active_operator/operation_generator.rb @@ -0,0 +1,31 @@ +require 'rails/generators' +require 'active_support/inflector' + +module ActiveOperator + module Generators + class OperationGenerator < Rails::Generators::NamedBase + include Rails::Generators::ResourceHelpers + + check_class_collision suffix: "Operation" + + source_root File.expand_path("templates", __dir__) + + desc "Generates an operation with the given NAME." + + def create_operation_file + template "operation.rb.erb", "app/operations/#{operation_file_path}_operation.rb" + end + + private + + def file_name + @_file_name ||= super.sub(/_operation\z/i, "") + end + + def operation_file_path + name.underscore.sub(/_operation\z/i, "") + end + + end + end +end diff --git a/lib/generators/active_operator/templates/operation.rb.erb b/lib/generators/active_operator/templates/operation.rb.erb new file mode 100644 index 0000000..74792cb --- /dev/null +++ b/lib/generators/active_operator/templates/operation.rb.erb @@ -0,0 +1,22 @@ +class <%= class_name %>Operation < ApplicationOperator + def request + # faraday.get( + # "https://api.geocod.io/v1.8/geocode", + # { + # q: record.address, + # api_key: Rails.application.credentials.dig(:geocodio, :api_key), + # fields: "timezone" + # } + # ) + end + + def process + # result = response.dig("body", "results", 0) + + # record.update!( + # latitude: result.dig("location", "lat"), + # longitude: result.dig("location", "lng"), + # timezone: result.dig("fields", "timezone", "name") + # ) + end +end diff --git a/test/generators/active_operator/operation_generator_test.rb b/test/generators/active_operator/operation_generator_test.rb new file mode 100644 index 0000000..d3ee9b6 --- /dev/null +++ b/test/generators/active_operator/operation_generator_test.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require "test_helper" + +require "rails/generators" +require "generators/active_operator/operation_generator" + +module ActiveOperator + module Generators + class OperationGeneratorTest < Rails::Generators::TestCase + tests ActiveOperator::Generators::OperationGenerator + + destination File.expand_path("../../tmp", __dir__) + setup :prepare_destination + + def after_teardown + FileUtils.rm_rf destination_root + super + end + + test "should generate operation file with simple name" do + run_generator ["user"] + + assert_file "app/operations/user_operation.rb" + + operation_contents = File.read(File.join(destination_root, "app/operations/user_operation.rb")) + assert_match "class UserOperation < ApplicationOperator", operation_contents + assert_match "def request", operation_contents + assert_match "def process", operation_contents + end + + test "should generate operation file with nested directories" do + run_generator ["geocode/v1/pull"] + + assert_file "app/operations/geocode/v1/pull_operation.rb" + + operation_contents = File.read(File.join(destination_root, "app/operations/geocode/v1/pull_operation.rb")) + assert_match "class Geocode::V1::PullOperation < ApplicationOperator", operation_contents + end + + test "should generate operation file with deeply nested directories" do + run_generator ["api/v2/users/profile/update"] + + assert_file "app/operations/api/v2/users/profile/update_operation.rb" + + operation_contents = File.read(File.join(destination_root, "app/operations/api/v2/users/profile/update_operation.rb")) + assert_match "class Api::V2::Users::Profile::UpdateOperation < ApplicationOperator", operation_contents + end + + test "should handle operation suffix correctly" do + run_generator ["user_operation"] + + assert_file "app/operations/user_operation.rb" + + operation_contents = File.read(File.join(destination_root, "app/operations/user_operation.rb")) + assert_match "class UserOperation < ApplicationOperator", operation_contents + end + + test "should handle nested operation with operation suffix" do + run_generator ["geocode/v1/pull_operation"] + + assert_file "app/operations/geocode/v1/pull_operation.rb" + + operation_contents = File.read(File.join(destination_root, "app/operations/geocode/v1/pull_operation.rb")) + assert_match "class Geocode::V1::PullOperation < ApplicationOperator", operation_contents + end + end + end +end From 2e4b6e61bc33159eb42f709ea8ff84c287297e79 Mon Sep 17 00:00:00 2001 From: Luiz Eduardo Kowalski Date: Mon, 7 Jul 2025 00:58:37 +0200 Subject: [PATCH 2/3] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f2368a..712aee5 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ rails db:migrate ### 1. Define an Operation -Create operation classes that inherit from `ApplicationOperation`: +Generate an operation class by running `rails generate active_operator:operation [name]`. ```ruby class Geocoding::V1 < ApplicationOperation From 37ba88643826d146a3e7d932f42e8e55c3b0168b Mon Sep 17 00:00:00 2001 From: Luiz Eduardo Kowalski Date: Mon, 7 Jul 2025 23:55:25 +0200 Subject: [PATCH 3/3] Stop using Operation suffix --- .../active_operator/operation_generator.rb | 15 ++----------- .../templates/operation.rb.erb | 2 +- .../operation_generator_test.rb | 22 +++++++++---------- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/lib/generators/active_operator/operation_generator.rb b/lib/generators/active_operator/operation_generator.rb index eeeb164..398a7f8 100644 --- a/lib/generators/active_operator/operation_generator.rb +++ b/lib/generators/active_operator/operation_generator.rb @@ -6,26 +6,15 @@ module Generators class OperationGenerator < Rails::Generators::NamedBase include Rails::Generators::ResourceHelpers - check_class_collision suffix: "Operation" + check_class_collision source_root File.expand_path("templates", __dir__) desc "Generates an operation with the given NAME." def create_operation_file - template "operation.rb.erb", "app/operations/#{operation_file_path}_operation.rb" + template "operation.rb.erb", "app/operations/#{file_path}.rb" end - - private - - def file_name - @_file_name ||= super.sub(/_operation\z/i, "") - end - - def operation_file_path - name.underscore.sub(/_operation\z/i, "") - end - end end end diff --git a/lib/generators/active_operator/templates/operation.rb.erb b/lib/generators/active_operator/templates/operation.rb.erb index 74792cb..78d5f72 100644 --- a/lib/generators/active_operator/templates/operation.rb.erb +++ b/lib/generators/active_operator/templates/operation.rb.erb @@ -1,4 +1,4 @@ -class <%= class_name %>Operation < ApplicationOperator +class <%= class_name %> < ApplicationOperation def request # faraday.get( # "https://api.geocod.io/v1.8/geocode", diff --git a/test/generators/active_operator/operation_generator_test.rb b/test/generators/active_operator/operation_generator_test.rb index d3ee9b6..66b4577 100644 --- a/test/generators/active_operator/operation_generator_test.rb +++ b/test/generators/active_operator/operation_generator_test.rb @@ -21,10 +21,10 @@ def after_teardown test "should generate operation file with simple name" do run_generator ["user"] - assert_file "app/operations/user_operation.rb" + assert_file "app/operations/user.rb" - operation_contents = File.read(File.join(destination_root, "app/operations/user_operation.rb")) - assert_match "class UserOperation < ApplicationOperator", operation_contents + operation_contents = File.read(File.join(destination_root, "app/operations/user.rb")) + assert_match "class User < ApplicationOperation", operation_contents assert_match "def request", operation_contents assert_match "def process", operation_contents end @@ -32,19 +32,19 @@ def after_teardown test "should generate operation file with nested directories" do run_generator ["geocode/v1/pull"] - assert_file "app/operations/geocode/v1/pull_operation.rb" + assert_file "app/operations/geocode/v1/pull.rb" - operation_contents = File.read(File.join(destination_root, "app/operations/geocode/v1/pull_operation.rb")) - assert_match "class Geocode::V1::PullOperation < ApplicationOperator", operation_contents + operation_contents = File.read(File.join(destination_root, "app/operations/geocode/v1/pull.rb")) + assert_match "class Geocode::V1::Pull < ApplicationOperation", operation_contents end test "should generate operation file with deeply nested directories" do run_generator ["api/v2/users/profile/update"] - assert_file "app/operations/api/v2/users/profile/update_operation.rb" + assert_file "app/operations/api/v2/users/profile/update.rb" - operation_contents = File.read(File.join(destination_root, "app/operations/api/v2/users/profile/update_operation.rb")) - assert_match "class Api::V2::Users::Profile::UpdateOperation < ApplicationOperator", operation_contents + operation_contents = File.read(File.join(destination_root, "app/operations/api/v2/users/profile/update.rb")) + assert_match "class Api::V2::Users::Profile::Update < ApplicationOperation", operation_contents end test "should handle operation suffix correctly" do @@ -53,7 +53,7 @@ def after_teardown assert_file "app/operations/user_operation.rb" operation_contents = File.read(File.join(destination_root, "app/operations/user_operation.rb")) - assert_match "class UserOperation < ApplicationOperator", operation_contents + assert_match "class UserOperation < ApplicationOperation", operation_contents end test "should handle nested operation with operation suffix" do @@ -62,7 +62,7 @@ def after_teardown assert_file "app/operations/geocode/v1/pull_operation.rb" operation_contents = File.read(File.join(destination_root, "app/operations/geocode/v1/pull_operation.rb")) - assert_match "class Geocode::V1::PullOperation < ApplicationOperator", operation_contents + assert_match "class Geocode::V1::PullOperation < ApplicationOperation", operation_contents end end end