hmvc-rails 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +34 -0
  3. data/CHANGELOG.md +5 -0
  4. data/CODE_OF_CONDUCT.md +84 -0
  5. data/Gemfile +20 -0
  6. data/Gemfile.lock +172 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +302 -0
  9. data/Rakefile +14 -0
  10. data/lib/generators/hmvc_rails/hmvc_rails_generator.rb +155 -0
  11. data/lib/generators/hmvc_rails/install_generator.rb +84 -0
  12. data/lib/generators/hmvc_rails/templates/configures/hmvc_rails.rb.tt +27 -0
  13. data/lib/generators/hmvc_rails/templates/configures/hmvc_rails_api.rb.tt +27 -0
  14. data/lib/generators/hmvc_rails/templates/controllers/controller.rb.tt +10 -0
  15. data/lib/generators/hmvc_rails/templates/extras/error_resource.rb.tt +31 -0
  16. data/lib/generators/hmvc_rails/templates/extras/error_response.rb.tt +21 -0
  17. data/lib/generators/hmvc_rails/templates/extras/exception.rb.tt +59 -0
  18. data/lib/generators/hmvc_rails/templates/forms/application_form.rb.tt +32 -0
  19. data/lib/generators/hmvc_rails/templates/forms/form.rb.tt +5 -0
  20. data/lib/generators/hmvc_rails/templates/operations/application_operation.rb.tt +11 -0
  21. data/lib/generators/hmvc_rails/templates/operations/operation.rb.tt +6 -0
  22. data/lib/generators/hmvc_rails/templates/validators/email_validator.rb.tt +10 -0
  23. data/lib/generators/hmvc_rails/templates/validators/uniqueness_validator.rb.tt +29 -0
  24. data/lib/generators/hmvc_rails/templates/views/view.erb.tt +1 -0
  25. data/lib/generators/hmvc_rails/templates/views/view.haml.tt +1 -0
  26. data/lib/generators/hmvc_rails/templates/views/view.slim.tt +1 -0
  27. data/lib/hmvc/rails/version.rb +7 -0
  28. data/lib/hmvc/rails.rb +35 -0
  29. data/lib/rubocop/cop/hmvc_rails/formal_style.rb +16 -0
  30. data/lib/rubocop/cop/hmvc_rails/operating_style.rb +29 -0
  31. data/lib/rubocop/cop/hmvc_rails_cops.rb +4 -0
  32. data/sig/hmvc/rails.rbs +6 -0
  33. metadata +74 -0
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ class HmvcRailsGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ class_option :action, type: :array, default: Hmvc::Rails.configuration.action
9
+ class_option :form, type: :array, default: Hmvc::Rails.configuration.form
10
+ class_option :parent_controller, type: :string, default: Hmvc::Rails.configuration.parent_controller
11
+ class_option :skip_form, type: :boolean, default: false
12
+ class_option :skip_view, type: :boolean, default: false
13
+
14
+ def generate
15
+ validate_options
16
+ create_controller
17
+ create_operation
18
+ create_form
19
+ create_view
20
+ end
21
+
22
+ private
23
+
24
+ def validate_options
25
+ return if behavior == :revoke
26
+
27
+ validate_name
28
+ validate_params
29
+ validate_form_option
30
+ validate_action_option
31
+ validate_parent_controller_option
32
+ validate_skip_form_option
33
+ validate_skip_view_option
34
+ end
35
+
36
+ def create_controller
37
+ template "controllers/controller.rb",
38
+ File.join("app/controllers", class_path.join("/"), "#{file_name}_controller.rb")
39
+ end
40
+
41
+ def create_operation
42
+ options[:action].each do |action|
43
+ @_action = action
44
+ template "operations/operation.rb", File.join("app/operations", file_path, "#{action}_operation.rb")
45
+ end
46
+ end
47
+
48
+ def create_form
49
+ return if options[:skip_form] || options[:form].blank?
50
+
51
+ forms = options[:form] & options[:action]
52
+ return puts "Warning: No forms created! Form and action controller does mismatch" if forms.blank?
53
+
54
+ forms.each do |action|
55
+ @_action = action
56
+ template "forms/form.rb", File.join("app/forms", file_path, "#{action}_form.rb")
57
+ end
58
+ end
59
+
60
+ def create_view
61
+ return if options[:skip_view] || Hmvc::Rails.configuration.view.blank?
62
+
63
+ views = Hmvc::Rails.configuration.view & options[:action]
64
+ return puts "Warning: No views created! View and action controller does mismatch" if views.blank?
65
+
66
+ view_engine = Rails.application&.config&.generators&.options&.dig(:rails, :template_engine) || "erb"
67
+ copy_view_template(views, view_engine)
68
+ rescue StandardError
69
+ copy_view_template(views, "erb")
70
+ end
71
+
72
+ def copy_view_template(views, view_engine)
73
+ views.each do |action|
74
+ @_action = action
75
+ template "views/view.#{view_engine}", File.join("app/views", file_path, "#{action}.html.#{view_engine}")
76
+ end
77
+ end
78
+
79
+ def argv
80
+ @argv ||= ARGV.map { |arg| arg.split("=") }.flatten
81
+ end
82
+
83
+ def validate_name
84
+ show_error_message("Invalid name arguments '#{argv[1]}'") if argv[1] && !argv[1].start_with?("-")
85
+ end
86
+
87
+ def validate_params
88
+ option_params = argv.select { |arg| arg.include?("-") }
89
+ wrong_options = option_params - %w[--action --form --parent-controller --skip-form --skip-view]
90
+ show_error_message("Invalid optional arguments '#{wrong_options.join(", ")}'") if wrong_options.present?
91
+ end
92
+
93
+ def validate_action_option
94
+ action_options = argv.select { |arg| arg == "--action" }
95
+ show_error_message("Optional '--action' is duplicated") if action_options.size > 1
96
+ end
97
+
98
+ def validate_form_option
99
+ form_options = argv.select { |arg| arg == "--form" }
100
+ show_error_message("Optional '--form' is duplicated") if form_options.size > 1
101
+ end
102
+
103
+ def validate_parent_controller_option
104
+ parent_options = argv.select { |arg| arg == "--parent-controller" }
105
+ show_error_message("Optional '--parent-controller' is duplicated") if parent_options.size > 1
106
+ index = argv.index("--parent-controller")
107
+ return unless index
108
+
109
+ if argv[index + 1].blank? || argv[index + 1].start_with?("-") ||
110
+ (argv[index + 2] && !argv[index + 2].start_with?("-"))
111
+ show_error_message("Option '--parent-controller' is not valid")
112
+ end
113
+ end
114
+
115
+ def validate_skip_form_option
116
+ index = argv.index("--skip-form")
117
+ return if index.blank? || argv[index + 1].blank? || argv[index + 1].start_with?("-")
118
+
119
+ show_error_message("Option '--skip-form' is not valid")
120
+ end
121
+
122
+ def validate_skip_view_option
123
+ index = argv.index("--skip-view")
124
+ return if index.blank? || argv[index + 1].blank? || argv[index + 1].start_with?("-")
125
+
126
+ show_error_message("Option '--skip-view' is not valid")
127
+ end
128
+
129
+ def show_error_message(message)
130
+ puts "Error:"
131
+ puts " #{message}"
132
+ puts "------"
133
+ puts `rails g hmvc_rails --help`
134
+ exit(1)
135
+ end
136
+
137
+ def path_notes(action)
138
+ case action
139
+ when "index" then "# [GET]..."
140
+ when "show" then "# [GET]..."
141
+ when "new" then "# [GET]..."
142
+ when "edit" then "# [GET]..."
143
+ when "create" then "# [POST]..."
144
+ when "update" then "# [PUT]..."
145
+ when "destroy" then "# [DELETE]..."
146
+ else "# [METHOD]..."
147
+ end
148
+ end
149
+
150
+ def add_file_traces
151
+ return unless Hmvc::Rails.configuration.file_traces
152
+
153
+ "# Created at: #{Time.now.strftime("%Y-%m-%d %H:%M %z")}\n# Creator: #{`git config user.email`}"
154
+ end
155
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails"
4
+ require "rails/generators"
5
+
6
+ module HmvcRails
7
+ module Generators
8
+ class InstallGenerator < Rails::Generators::Base
9
+ desc "Generate base files of the HMVC structure"
10
+
11
+ class_option :api, type: :boolean, default: false
12
+
13
+ source_root File.expand_path("templates", __dir__)
14
+
15
+ def generate
16
+ copy_configuration
17
+ copy_application_operator
18
+ copy_application_form
19
+ copy_validator
20
+ copy_api_error_handler
21
+ add_config_api_error_response
22
+ add_api_error_response
23
+ end
24
+
25
+ private
26
+
27
+ def copy_configuration
28
+ file_selected = options[:api] ? "configures/hmvc_rails_api.rb" : "configures/hmvc_rails.rb"
29
+ template file_selected, "config/initializers/hmvc_rails.rb"
30
+ end
31
+
32
+ def copy_application_operator
33
+ template "operations/application_operation.rb", "app/operations/application_operation.rb"
34
+ end
35
+
36
+ def copy_application_form
37
+ template "forms/application_form.rb", "app/forms/application_form.rb"
38
+ end
39
+
40
+ def copy_validator
41
+ template "validators/uniqueness_validator.rb", "app/validators/uniqueness_validator.rb"
42
+ template "validators/email_validator.rb", "app/validators/email_validator.rb"
43
+ end
44
+
45
+ def copy_api_error_handler
46
+ return unless options[:api]
47
+
48
+ template "extras/exception.rb", "lib/hmvc_rails/extras/exception.rb"
49
+ template "extras/error_resource.rb", "lib/hmvc_rails/extras/error_resource.rb"
50
+ template "extras/error_response.rb", "lib/hmvc_rails/extras/error_response.rb"
51
+ end
52
+
53
+ # rubocop:disable Layout/LineLength
54
+ def add_config_api_error_response
55
+ return if Rails.root.blank? || !options[:api] || behavior == :revoke
56
+
57
+ file_path = Rails.root.join("config", "application.rb")
58
+ if File.foreach(file_path).grep(/Application < Rails::Application/).any?
59
+ inject_into_file file_path, " # This setting to use the error handler of hmvc-rails\n config.eager_load_paths << Rails.root.join('lib', 'hmvc_rails')\n\n", after: "Application < Rails::Application\n"
60
+ else
61
+ puts "Warning: The hmvc_rails module could not be automatically loaded because the \"Application < Rails::Application\" flag was not found"
62
+ puts "Please manually add `config.eager_load_paths << Rails.root.join('lib', 'hmvc_rails')` to your `config/application.rb` to use hmvc-rails error response"
63
+ end
64
+ end
65
+
66
+ def add_api_error_response
67
+ return if Rails.root.blank? || !options[:api] || behavior == :revoke
68
+
69
+ file_path = Rails.root.join("app", "controllers", "application_controller.rb")
70
+ if File.foreach(file_path).grep(/ApplicationController < ActionController::API/).any?
71
+ inject_into_file file_path, " include Extras::ErrorResponse\n", after: "ApplicationController < ActionController::API\n"
72
+ else
73
+ puts "Warning: The error response module could not be automatically added because the \"ApplicationController < ActionController::API\" flag was not found"
74
+ puts "Please manually add `include Extras::ErrorResponse` to your application_controller.rb to use hmvc-rails error response"
75
+ end
76
+ end
77
+ # rubocop:enable Layout/LineLength
78
+
79
+ def add_file_traces
80
+ "# Created at: #{Time.now.strftime("%Y-%m-%d %H:%M %z")}\n# Creator: #{`git config user.email`}"
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ if Rails.env.development?
5
+ Hmvc::Rails.configure do |config|
6
+ # The controller files's parent class of controller. Default is ApplicationController
7
+ # config.parent_controller = "ApplicationController"
8
+
9
+ # Method when creating the controller files. Default is %w[index show new create edit update destroy]
10
+ # config.action = %w[index show new create edit update destroy]
11
+
12
+ # Method when creating the view files. Default is %w[index show new edit]
13
+ # config.view = %w[index show new edit]
14
+
15
+ # The form files's parent class. Default is ApplicationForm
16
+ # config.parent_form = "ApplicationForm"
17
+
18
+ # Method when creating the form files. Default is %w[new create edit update]
19
+ # config.form = %w[new create edit update]
20
+
21
+ # The operation files's parent class. Default is ApplicationOperation
22
+ # config.parent_operation = "ApplicationOperation"
23
+
24
+ # Save author name and timestamp to file. Default is true
25
+ # config.file_traces = true
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ if Rails.env.development?
5
+ Hmvc::Rails.configure do |config|
6
+ # The controller files's parent class of controller. Default is ApplicationController
7
+ # config.parent_controller = "ApplicationController"
8
+
9
+ # Method when creating the controller files. Default is %w[index show new create edit update destroy]
10
+ config.action = %w[index show create update destroy]
11
+
12
+ # Method when creating the view files. Default is %w[index show new edit]
13
+ config.view = %w[]
14
+
15
+ # The form files's parent class. Default is ApplicationForm
16
+ # config.parent_form = "ApplicationForm"
17
+
18
+ # Method when creating the form files. Default is %w[new create edit update]
19
+ config.form = %w[create update]
20
+
21
+ # The operation files's parent class. Default is ApplicationOperation
22
+ # config.parent_operation = "ApplicationOperation"
23
+
24
+ # Save author name and timestamp to file. Default is true
25
+ # config.file_traces = true
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ class <%= class_name %>Controller < <%= options[:parent_controller] %><% options[:action].each do |action| %>
5
+ <%= path_notes(action) %>
6
+ def <%= action %>
7
+ operator = <%= class_name %>::<%= action.humanize %>Operation.new(params)
8
+ operator.call
9
+ end
10
+ <% end %>end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ module Extras
5
+ class ErrorResource
6
+ include Exception
7
+
8
+ attr_reader :status, :code, :message
9
+
10
+ def initialize(exception)
11
+ hash = get_status_code(exception)
12
+ @code = hash[:code]
13
+ @status = hash[:status]
14
+ @message = exception.message
15
+ end
16
+
17
+ def as_json
18
+ return { code: code, field_error: field_errors } if status == UNPROCESSABLE_ENTITY[:status]
19
+
20
+ { code: code, message: message }
21
+ end
22
+
23
+ private
24
+
25
+ def field_errors
26
+ JSON.parse(message).map do |field, messages|
27
+ messages.map { |message_detail| { name: field, message: message_detail } }
28
+ end.flatten
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ module Extras
5
+ module ErrorResponse
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ rescue_from StandardError do |exception|
10
+ handle(exception)
11
+ end
12
+
13
+ private
14
+
15
+ def handle(exception)
16
+ error = ErrorResource.new(exception)
17
+ render json: error.as_json, status: error.status
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ module Extras
5
+ module Exception
6
+ BAD_REQUEST = { status: 400, code: :bad_request }.freeze
7
+ UNAUTHORIZED = { status: 401, code: :unauthorized }.freeze
8
+ FORBIDDEN = { status: 403, code: :forbidden }.freeze
9
+ NOT_FOUND = { status: 404, code: :not_found }.freeze
10
+ CONFLICT = { status: 409, code: :conflict }.freeze
11
+ UNPROCESSABLE_ENTITY = { status: 422, code: :unprocessable_entity }.freeze
12
+ INTERNAL_SERVER_ERROR = { status: 500, code: :internal_server_error }.freeze
13
+ NOT_IMPLEMENTED = { status: 501, code: :not_implemented }.freeze
14
+ SERVICE_UNAVAILABLE = { status: 503, code: :service_unavailable }.freeze
15
+
16
+ def get_status_code(exception)
17
+ case exception
18
+ when Exception::BadRequest, Exception::ResourceInvalid, ActionController::BadRequest
19
+ BAD_REQUEST
20
+ when Exception::SecurityError, Exception::Unauthorized
21
+ UNAUTHORIZED
22
+ when Exception::Forbidden, ActionController::InvalidAuthenticityToken
23
+ FORBIDDEN
24
+ when ActiveRecord::RecordNotFound
25
+ NOT_FOUND
26
+ when ActiveRecord::RecordNotUnique
27
+ CONFLICT
28
+ when Exception::UnprocessableEntity
29
+ UNPROCESSABLE_ENTITY
30
+ when Exception::NotImplemented
31
+ NOT_IMPLEMENTED
32
+ else
33
+ INTERNAL_SERVER_ERROR
34
+ end
35
+ end
36
+
37
+ class BadRequest < StandardError; end
38
+
39
+ class ResourceInvalid < StandardError; end
40
+
41
+ class SecurityError < StandardError; end
42
+
43
+ class Unauthorized < StandardError; end
44
+
45
+ class Forbidden < StandardError; end
46
+
47
+ class NotFound < StandardError; end
48
+
49
+ class ResourceNotFound < StandardError; end
50
+
51
+ class Conflict < StandardError; end
52
+
53
+ class UnprocessableEntity < ActiveRecord::RecordInvalid; end
54
+
55
+ class InternalServerError < StandardError; end
56
+
57
+ class NotImplemented < StandardError; end
58
+ end
59
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ class ApplicationForm
5
+ extend ActiveModel::Translation
6
+
7
+ include ActiveModel::Model
8
+ include ActiveModel::Attributes
9
+ include ActiveModel::Validations::Callbacks
10
+
11
+ def initialize(attributes = {})
12
+ self.class.attribute_names.each do |column|
13
+ self.class.attribute(column.to_sym)
14
+ end
15
+
16
+ super attributes
17
+ end
18
+
19
+ def valid!
20
+ raise ExceptionError::UnprocessableEntity, error_messages.to_json unless valid?
21
+ end
22
+
23
+ private
24
+
25
+ def error_messages
26
+ errors.messages.map { |key, value| { key => value.first } }
27
+ end
28
+
29
+ def attribute_names
30
+ []
31
+ end
32
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ class <%= class_name %>::<%= @_action.humanize %>Form < <%= Hmvc::Rails.configuration.parent_form %>
5
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ class ApplicationOperation
5
+ attr_reader :params, :current_user
6
+
7
+ def initialize(params, data = {})
8
+ @params = params
9
+ @current_user = data[:current_user]
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ class <%= class_name %>::<%= @_action.humanize %>Operation < <%= Hmvc::Rails.configuration.parent_operation %>
5
+ def call; end
6
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ class EmailValidator < ActiveModel::EachValidator
5
+ def validate_each(record, attribute, value)
6
+ return if value.blank? || /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i.match?(value)
7
+
8
+ record.errors.add(attribute, :invalid)
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ <%= add_file_traces %>
4
+ class UniquenessValidator < ActiveModel::EachValidator
5
+ def initialize(klass)
6
+ super
7
+ @klass = options[:model] if options[:model]
8
+ end
9
+
10
+ def validate_each(record, attribute)
11
+ record_org = record
12
+ attribute_org = attribute
13
+ attribute = options[:attribute].to_sym if options[:attribute]
14
+ base_attrs = {}
15
+ base_attrs[attribute] = record_org.send(attribute)
16
+
17
+ options[:scope]&.each do |scope_attribute|
18
+ base_attrs[scope_attribute] = record_org.send(scope_attribute)
19
+ end
20
+
21
+ record = if record_org.try(:record)
22
+ options[:model].where.not(id: record_org.send(:record).id).exists?(base_attrs)
23
+ else
24
+ options[:model].exists?(base_attrs)
25
+ end
26
+
27
+ record_org.errors.add(attribute_org, :taken) if record
28
+ end
29
+ end
@@ -0,0 +1 @@
1
+ <h1><%= @_action.camelize %></h1>
@@ -0,0 +1 @@
1
+ %h1= @_action.camelize
@@ -0,0 +1 @@
1
+ h1= @_action.camelize
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hmvc
4
+ module Rails
5
+ VERSION = "1.0.0"
6
+ end
7
+ end
data/lib/hmvc/rails.rb ADDED
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rails/version"
4
+
5
+ module Hmvc
6
+ module Rails
7
+ class Error < StandardError; end
8
+
9
+ class << self
10
+ attr_writer :configuration
11
+
12
+ def configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ def configure
17
+ yield(configuration)
18
+ end
19
+ end
20
+
21
+ class Configuration
22
+ attr_accessor :parent_controller, :action, :view, :form, :parent_form, :parent_operation, :file_traces
23
+
24
+ def initialize
25
+ @parent_controller = "ApplicationController"
26
+ @action = %w[index show new create edit update destroy]
27
+ @view = %w[index show new edit]
28
+ @form = %w[new create edit update]
29
+ @parent_form = "ApplicationForm"
30
+ @parent_operation = "ApplicationOperation"
31
+ @file_traces = true
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module HmvcRails
6
+ class FormalStyle < RuboCop::Cop::Base
7
+ def on_class(node)
8
+ class_name = node.children.first.children.last.to_s
9
+ return if class_name.end_with?("Form")
10
+
11
+ add_offense(node, message: "The form name does not match the desired format")
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module HmvcRails
6
+ class OperatingStyle < RuboCop::Cop::Base
7
+ def on_class(node)
8
+ class_name = node.children.first.children.last.to_s
9
+ return if class_name.end_with?("Operation")
10
+
11
+ add_offense(node, message: "The operation name does not match the desired format")
12
+ end
13
+
14
+ def on_def(node)
15
+ return unless node.children.first == :call
16
+
17
+ node.body.to_a.compact.each do |ast|
18
+ next if ast.is_a?(Symbol) && (ast.to_s.start_with?("step_") || ats.to_s == "super")
19
+
20
+ next if ast.is_a?(RuboCop::AST::SendNode) &&
21
+ (ast.children.last.to_s.start_with?("step_") || ast.children.last.to_s == "super")
22
+
23
+ add_offense(node, message: "Method works in \"call\" without prefix \"step_\"")
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "hmvc_rails/operating_style"
4
+ require_relative "hmvc_rails/formal_style"
@@ -0,0 +1,6 @@
1
+ module Hmvc
2
+ module Rails
3
+ VERSION: String
4
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ end
6
+ end