-
-
Notifications
You must be signed in to change notification settings - Fork 38
Add dry-operation generators #171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 11 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
d3e5e78
Add dry-operation to default Gemfile
cllns 888c388
Add base Operation class, based on dry-operation
cllns 24d3d6b
Fix view spec
cllns bc2670a
Add Operation generators
cllns 1c37df3
Add empty `call` method definition
cllns a3f6a03
Remove ostruct
cllns d93dfc8
Merge branch 'main' into add-dry-operation
cllns 649bdcb
Allow slash separator for generator
cllns f74519f
Allow slash separator for generator
cllns 0f9f814
Rename module to admin
cllns 663abc6
Remove newlines in generated files
cllns 3b72feb
Remove input as default args
cllns 0f81a5c
Remove Operations namespace, generate in app/ or slices/SLICE_NAME/
cllns a5bd2f3
Prevent generating operation without namespace
cllns eb391ca
Revert "Prevent generating operation without namespace"
cllns 1023225
Add recommendation to add namespace to operations
cllns 6a3c32a
Change examples
cllns 8dc3de4
Switch to outputting directly, remove Files#recommend
cllns 8f90b33
x.x.x => 2.2.0
cllns 8e62aa3
Include Dry::Monads[:result] in base Action
cllns c2c54c9
Add explanatory comment, and include monads result on Slice action
cllns 9933c8a
Register command so it's available
cllns 9fc5e31
Require dry-monads
cllns ad0431d
Add require for slice action
cllns 0095497
Change note to past tense
cllns 29b02b9
Merge remote-tracking branch 'origin/main' into add-dry-operation
cllns e60248d
Remove inlude Dry::Monads in slice Action
cllns File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# frozen_string_literal: true | ||
|
||
require "dry/inflector" | ||
require "dry/files" | ||
require "shellwords" | ||
require_relative "../../../naming" | ||
require_relative "../../../errors" | ||
|
||
module Hanami | ||
module CLI | ||
module Commands | ||
module App | ||
module Generate | ||
# @since x.x.x | ||
# @api private | ||
class Operation < App::Command | ||
argument :name, required: true, desc: "Operation name" | ||
option :slice, required: false, desc: "Slice name" | ||
|
||
example [ | ||
%(add_book (MyApp::Operations::AddBook)), | ||
%(add_book --slice=admin (Admin::Operations::AddBook)), | ||
] | ||
attr_reader :generator | ||
private :generator | ||
|
||
# @since x.x.x | ||
# @api private | ||
def initialize( | ||
fs:, inflector:, | ||
generator: Generators::App::Operation.new(fs: fs, inflector: inflector), | ||
**opts | ||
) | ||
super(fs: fs, inflector: inflector, **opts) | ||
@generator = generator | ||
end | ||
|
||
# @since x.x.x | ||
# @api private | ||
def call(name:, slice: nil, **) | ||
slice = inflector.underscore(Shellwords.shellescape(slice)) if slice | ||
|
||
generator.call(app.namespace, name, slice) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# frozen_string_literal: true | ||
|
||
require "erb" | ||
require "dry/files" | ||
require_relative "../../errors" | ||
|
||
module Hanami | ||
module CLI | ||
module Generators | ||
module App | ||
# @since x.x.x | ||
# @api private | ||
class Operation | ||
# @since x.x.x | ||
# @api private | ||
def initialize(fs:, inflector:) | ||
@fs = fs | ||
@inflector = inflector | ||
end | ||
|
||
# @since x.x.x | ||
# @api private | ||
def call(app, key, slice) | ||
context = OperationContext.new(inflector, app, slice, key) | ||
|
||
if slice | ||
generate_for_slice(context, slice) | ||
else | ||
generate_for_app(context) | ||
end | ||
end | ||
|
||
private | ||
|
||
attr_reader :fs | ||
|
||
attr_reader :inflector | ||
|
||
def generate_for_slice(context, slice) | ||
slice_directory = fs.join("slices", slice) | ||
raise MissingSliceError.new(slice) unless fs.directory?(slice_directory) | ||
|
||
if context.namespaces.any? | ||
fs.mkdir(directory = fs.join(slice_directory, "operations", context.namespaces)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should hardcode (This comment also applies to all the other places we've hard-coded "operations" within this PR) |
||
fs.write(fs.join(directory, "#{context.name}.rb"), t("nested_slice_operation.erb", context)) | ||
else | ||
fs.mkdir(directory = fs.join(slice_directory, "operations")) | ||
fs.write(fs.join(directory, "#{context.name}.rb"), t("top_level_slice_operation.erb", context)) | ||
end | ||
end | ||
|
||
def generate_for_app(context) | ||
if context.namespaces.any? | ||
fs.mkdir(directory = fs.join("app", "operations", context.namespaces)) | ||
fs.write(fs.join(directory, "#{context.name}.rb"), t("nested_app_operation.erb", context)) | ||
else | ||
fs.mkdir(directory = fs.join("app", "operations")) | ||
fs.write(fs.join(directory, "#{context.name}.rb"), t("top_level_app_operation.erb", context)) | ||
end | ||
end | ||
|
||
def template(path, context) | ||
require "erb" | ||
|
||
ERB.new( | ||
File.read(__dir__ + "/operation/#{path}") | ||
).result(context.ctx) | ||
end | ||
|
||
alias_method :t, :template | ||
end | ||
end | ||
end | ||
end | ||
end |
12 changes: 12 additions & 0 deletions
12
lib/hanami/cli/generators/app/operation/nested_app_operation.erb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# frozen_string_literal: true | ||
|
||
module <%= camelized_app_name %> | ||
module Operations | ||
<%= module_namespace_declaration %> | ||
<%= module_namespace_offset %>class <%= camelized_name %> < <%= camelized_app_name %>::Operation | ||
<%= module_namespace_offset %> def call(input) | ||
<%= module_namespace_offset %> end | ||
<%= module_namespace_offset %>end | ||
<%= module_namespace_end %> | ||
end | ||
end |
12 changes: 12 additions & 0 deletions
12
lib/hanami/cli/generators/app/operation/nested_slice_operation.erb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# frozen_string_literal: true | ||
|
||
module <%= camelized_slice_name %> | ||
module Operations | ||
<%= module_namespace_declaration %> | ||
<%= module_namespace_offset %>class <%= camelized_name %> < <%= camelized_slice_name %>::Operation | ||
<%= module_namespace_offset %> def call(input) | ||
<%= module_namespace_offset %> end | ||
<%= module_namespace_offset %>end | ||
<%= module_namespace_end %> | ||
end | ||
end |
10 changes: 10 additions & 0 deletions
10
lib/hanami/cli/generators/app/operation/top_level_app_operation.erb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# frozen_string_literal: true | ||
|
||
module <%= camelized_app_name %> | ||
module Operations | ||
<%= module_namespace_offset %>class <%= camelized_name %> < <%= camelized_app_name %>::Operation | ||
<%= module_namespace_offset %> def call(input) | ||
<%= module_namespace_offset %> end | ||
<%= module_namespace_offset %>end | ||
end | ||
end |
10 changes: 10 additions & 0 deletions
10
lib/hanami/cli/generators/app/operation/top_level_slice_operation.erb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# frozen_string_literal: true | ||
|
||
module <%= camelized_slice_name %> | ||
module Operations | ||
<%= module_namespace_offset %>class <%= camelized_name %> < <%= camelized_slice_name %>::Operation | ||
<%= module_namespace_offset %> def call(input) | ||
<%= module_namespace_offset %> end | ||
<%= module_namespace_offset %>end | ||
end | ||
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative "slice_context" | ||
require "dry/files/path" | ||
|
||
module Hanami | ||
module CLI | ||
module Generators | ||
# @since x.x.x | ||
# @api private | ||
module App | ||
# @since x.x.x | ||
# @api private | ||
class OperationContext < SliceContext | ||
# TODO: move these constants somewhere that will let us reuse them | ||
KEY_SEPARATOR = %r{\.|/} | ||
private_constant :KEY_SEPARATOR | ||
|
||
NAMESPACE_SEPARATOR = "::" | ||
private_constant :NAMESPACE_SEPARATOR | ||
|
||
INDENTATION = " " | ||
private_constant :INDENTATION | ||
|
||
OFFSET = INDENTATION * 2 | ||
private_constant :OFFSET | ||
|
||
# @since x.x.x | ||
# @api private | ||
attr_reader :key | ||
|
||
# @since x.x.x | ||
# @api private | ||
def initialize(inflector, app, slice, key) | ||
@key = key | ||
super(inflector, app, slice, nil) | ||
end | ||
|
||
# @since x.x.x | ||
# @api private | ||
def namespaces | ||
@namespaces ||= key.split(KEY_SEPARATOR)[..-2] | ||
end | ||
|
||
# @since x.x.x | ||
# @api private | ||
def name | ||
@name ||= key.split(KEY_SEPARATOR)[-1] | ||
end | ||
|
||
# @api private | ||
# @since x.x.x | ||
# @api private | ||
def camelized_name | ||
inflector.camelize(name) | ||
end | ||
|
||
# @since x.x.x | ||
# @api private | ||
def module_namespace_declaration | ||
namespaces.each_with_index.map { |token, i| | ||
"#{OFFSET}#{INDENTATION * i}module #{inflector.camelize(token)}" | ||
}.join($/) | ||
end | ||
|
||
# @since x.x.x | ||
# @api private | ||
def module_namespace_end | ||
namespaces.each_with_index.map { |_, i| | ||
"#{OFFSET}#{INDENTATION * i}end" | ||
}.reverse.join($/) | ||
end | ||
|
||
# @since x.x.x | ||
# @api private | ||
def module_namespace_offset | ||
"#{OFFSET}#{INDENTATION * namespaces.count}" | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# auto_register: false | ||
# frozen_string_literal: true | ||
|
||
module <%= camelized_slice_name %> | ||
class Operation < <%= camelized_app_name %>::Operation | ||
end | ||
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# auto_register: false | ||
# frozen_string_literal: true | ||
|
||
require "dry/operation" | ||
|
||
module <%= camelized_app_name %> | ||
class Operation < Dry::Operation | ||
end | ||
end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.