better_service 2.0.0 → 2.1.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.
- checksums.yaml +4 -4
- data/LICENSE +2 -0
- data/README.md +98 -45
- data/Rakefile +7 -209
- data/config/locales/better_service.en.yml +15 -0
- data/lib/better_service/cache_service.rb +4 -4
- data/lib/better_service/concerns/instrumentation.rb +59 -14
- data/lib/better_service/concerns/serviceable/authorizable.rb +1 -1
- data/lib/better_service/concerns/serviceable/messageable.rb +70 -1
- data/lib/better_service/concerns/serviceable/repository_aware.rb +8 -3
- data/lib/better_service/concerns/workflowable/callbacks.rb +27 -27
- data/lib/better_service/concerns/workflowable/step.rb +39 -5
- data/lib/better_service/errors/better_service_error.rb +4 -0
- data/lib/better_service/errors/runtime/authorization_error.rb +4 -1
- data/lib/better_service/errors/runtime/database_error.rb +4 -1
- data/lib/better_service/errors/runtime/execution_error.rb +4 -1
- data/lib/better_service/errors/runtime/invalid_result_error.rb +28 -0
- data/lib/better_service/errors/runtime/resource_not_found_error.rb +4 -1
- data/lib/better_service/errors/runtime/validation_error.rb +4 -1
- data/lib/better_service/repository/base_repository.rb +1 -1
- data/lib/better_service/result.rb +110 -0
- data/lib/better_service/services/base.rb +216 -57
- data/lib/better_service/version.rb +1 -1
- data/lib/better_service/workflows/branch_group.rb +1 -1
- data/lib/better_service.rb +1 -6
- data/lib/generators/serviceable/action_generator.rb +11 -0
- data/lib/generators/serviceable/base_generator.rb +109 -0
- data/lib/generators/serviceable/create_generator.rb +11 -0
- data/lib/generators/serviceable/destroy_generator.rb +11 -0
- data/lib/generators/serviceable/index_generator.rb +11 -0
- data/lib/generators/serviceable/scaffold_generator.rb +29 -7
- data/lib/generators/serviceable/show_generator.rb +11 -0
- data/lib/generators/serviceable/templates/action_service.rb.tt +8 -3
- data/lib/generators/serviceable/templates/base_locale.en.yml.tt +53 -0
- data/lib/generators/serviceable/templates/base_service.rb.tt +78 -0
- data/lib/generators/serviceable/templates/base_service_test.rb.tt +64 -0
- data/lib/generators/serviceable/templates/create_service.rb.tt +29 -18
- data/lib/generators/serviceable/templates/destroy_service.rb.tt +16 -29
- data/lib/generators/serviceable/templates/index_service.rb.tt +16 -34
- data/lib/generators/serviceable/templates/repository.rb.tt +76 -0
- data/lib/generators/serviceable/templates/repository_test.rb.tt +124 -0
- data/lib/generators/serviceable/templates/show_service.rb.tt +10 -38
- data/lib/generators/serviceable/templates/update_service.rb.tt +24 -38
- data/lib/generators/serviceable/update_generator.rb +11 -0
- metadata +13 -12
- data/lib/better_service/concerns/serviceable/viewable.rb +0 -33
- data/lib/better_service/services/action_service.rb +0 -60
- data/lib/better_service/services/create_service.rb +0 -63
- data/lib/better_service/services/destroy_service.rb +0 -60
- data/lib/better_service/services/index_service.rb +0 -56
- data/lib/better_service/services/show_service.rb +0 -44
- data/lib/better_service/services/update_service.rb +0 -61
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
<% module_namespacing do -%>
|
|
4
|
-
class <%= class_name %>::ShowService <
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
# presenter <%= class_name %>Presenter
|
|
9
|
-
# presenter_options do
|
|
10
|
-
# { current_user: user }
|
|
11
|
-
# end
|
|
4
|
+
class <%= class_name %>::ShowService < <%= parent_class %>
|
|
5
|
+
# Action name for metadata
|
|
6
|
+
performed_action :showed
|
|
12
7
|
|
|
13
8
|
# Schema for validating params
|
|
14
9
|
schema do
|
|
@@ -17,39 +12,16 @@ class <%= class_name %>::ShowService < BetterService::Services::ShowService
|
|
|
17
12
|
|
|
18
13
|
# Phase 1: Search - Load the resource
|
|
19
14
|
search_with do
|
|
20
|
-
|
|
15
|
+
<% if using_base_service? -%>
|
|
16
|
+
{ object: <%= singular_table_name %>_repository.find(params[:id]) }
|
|
17
|
+
<% else -%>
|
|
18
|
+
{ object: user.<%= plural_table_name %>.find(params[:id]) }
|
|
19
|
+
<% end -%>
|
|
21
20
|
end
|
|
22
21
|
|
|
23
|
-
# Phase
|
|
24
|
-
# process_with do |data|
|
|
25
|
-
# data
|
|
26
|
-
# end
|
|
27
|
-
|
|
28
|
-
# Phase 4: Respond - Format response (optional override)
|
|
29
|
-
# Uses I18n message helper with fallback to default messages
|
|
30
|
-
#
|
|
31
|
-
# To customize messages, create config/locales/<%= plural_table_name %>_services.en.yml:
|
|
32
|
-
# en:
|
|
33
|
-
# <%= plural_table_name %>:
|
|
34
|
-
# services:
|
|
35
|
-
# show:
|
|
36
|
-
# success: "<%= human_name %> loaded successfully!"
|
|
37
|
-
#
|
|
38
|
-
# Then configure namespace: messages_namespace :<%= plural_table_name %>
|
|
22
|
+
# Phase 4: Respond - Format response
|
|
39
23
|
respond_with do |data|
|
|
40
|
-
|
|
24
|
+
success_for(data[:object], message("show.success"))
|
|
41
25
|
end
|
|
42
|
-
|
|
43
|
-
# Phase 5: Viewer - UI configuration (optional)
|
|
44
|
-
# viewer do |processed, transformed, result|
|
|
45
|
-
# {
|
|
46
|
-
# page_title: "<%= human_name %> ##{result[:resource].id}",
|
|
47
|
-
# breadcrumbs: [
|
|
48
|
-
# { label: "Home", url: "/" },
|
|
49
|
-
# { label: "<%= plural_table_name.titleize %>", url: "/<%= plural_table_name %>" },
|
|
50
|
-
# { label: "Show", url: "#" }
|
|
51
|
-
# ]
|
|
52
|
-
# }
|
|
53
|
-
# end
|
|
54
26
|
end
|
|
55
27
|
<% end -%>
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
<% module_namespacing do -%>
|
|
4
|
-
class <%= class_name %>::UpdateService <
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
class <%= class_name %>::UpdateService < <%= parent_class %>
|
|
5
|
+
# Action name for metadata
|
|
6
|
+
performed_action :updated
|
|
7
|
+
|
|
8
|
+
# Enable transaction wrapping
|
|
9
|
+
with_transaction true
|
|
8
10
|
|
|
9
11
|
# Schema for validating params
|
|
10
12
|
schema do
|
|
@@ -12,49 +14,33 @@ class <%= class_name %>::UpdateService < BetterService::Services::UpdateService
|
|
|
12
14
|
# Add your optional attributes here
|
|
13
15
|
end
|
|
14
16
|
|
|
15
|
-
# Authorization (optional) - Runs BEFORE search phase
|
|
16
|
-
# Uncomment and customize for your needs:
|
|
17
|
-
#
|
|
18
|
-
# authorize_with do
|
|
19
|
-
# # Example 1: Simple role check
|
|
20
|
-
# user.admin?
|
|
21
|
-
#
|
|
22
|
-
# # Example 2: Resource ownership check
|
|
23
|
-
# <%= file_name %> = <%= class_name %>.find(params[:id])
|
|
24
|
-
# <%= file_name %>.user_id == user.id
|
|
25
|
-
#
|
|
26
|
-
# # Example 3: Pundit integration
|
|
27
|
-
# <%= class_name %>Policy.new(user, <%= class_name %>.find(params[:id])).update?
|
|
28
|
-
#
|
|
29
|
-
# # Example 4: CanCanCan integration
|
|
30
|
-
# Ability.new(user).can?(:update, :<%= file_name %>)
|
|
31
|
-
# end
|
|
32
|
-
|
|
33
17
|
# Phase 1: Search - Load the resource
|
|
34
18
|
search_with do
|
|
35
|
-
|
|
19
|
+
<% if using_base_service? -%>
|
|
20
|
+
{ object: <%= singular_table_name %>_repository.find(params[:id]) }
|
|
21
|
+
<% else -%>
|
|
22
|
+
{ object: user.<%= plural_table_name %>.find(params[:id]) }
|
|
23
|
+
<% end -%>
|
|
36
24
|
end
|
|
37
25
|
|
|
38
26
|
# Phase 2: Process - Update the resource (runs in transaction)
|
|
27
|
+
# Uses update (not update!) to allow graceful validation handling
|
|
39
28
|
process_with do |data|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
29
|
+
record = data[:object]
|
|
30
|
+
|
|
31
|
+
if record.update(params.except(:id))
|
|
32
|
+
{ object: record }
|
|
33
|
+
else
|
|
34
|
+
failure_for(record)
|
|
35
|
+
end
|
|
43
36
|
end
|
|
44
37
|
|
|
45
|
-
# Phase 4: Respond - Format response
|
|
46
|
-
# Uses I18n message helper with fallback to default messages
|
|
47
|
-
#
|
|
48
|
-
# To customize messages, create config/locales/<%= plural_table_name %>_services.en.yml:
|
|
49
|
-
# en:
|
|
50
|
-
# <%= plural_table_name %>:
|
|
51
|
-
# services:
|
|
52
|
-
# update:
|
|
53
|
-
# success: "<%= human_name %> updated successfully!"
|
|
54
|
-
#
|
|
55
|
-
# Then configure namespace: messages_namespace :<%= plural_table_name %>
|
|
38
|
+
# Phase 4: Respond - Format response
|
|
56
39
|
respond_with do |data|
|
|
57
|
-
|
|
40
|
+
# Pass through failure responses
|
|
41
|
+
return data if data[:success] == false
|
|
42
|
+
|
|
43
|
+
success_for(data[:object], message("update.success"))
|
|
58
44
|
end
|
|
59
45
|
end
|
|
60
46
|
<% end -%>
|
|
@@ -9,6 +9,9 @@ module Serviceable
|
|
|
9
9
|
|
|
10
10
|
desc "Generate an Update service for modifying resources"
|
|
11
11
|
|
|
12
|
+
class_option :base_class, type: :string, default: nil,
|
|
13
|
+
desc: "Custom base class to inherit from (e.g., Articles::BaseService)"
|
|
14
|
+
|
|
12
15
|
def create_service_file
|
|
13
16
|
template "update_service.rb.tt", File.join("app/services", class_path, "#{file_name}/update_service.rb")
|
|
14
17
|
end
|
|
@@ -22,6 +25,14 @@ module Serviceable
|
|
|
22
25
|
def service_class_name
|
|
23
26
|
"#{class_name}::UpdateService"
|
|
24
27
|
end
|
|
28
|
+
|
|
29
|
+
def parent_class
|
|
30
|
+
options[:base_class] || "BetterService::Services::Base"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def using_base_service?
|
|
34
|
+
options[:base_class].present?
|
|
35
|
+
end
|
|
25
36
|
end
|
|
26
37
|
end
|
|
27
38
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: better_service
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- alessiobussolari
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-12-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -75,7 +75,7 @@ dependencies:
|
|
|
75
75
|
description: A powerful DSL-based framework for building Service Objects in Rails
|
|
76
76
|
with built-in support for validation, caching, presenters, and more.
|
|
77
77
|
email:
|
|
78
|
-
- alessio@
|
|
78
|
+
- alessio.bussolari@pandev.it
|
|
79
79
|
executables: []
|
|
80
80
|
extensions: []
|
|
81
81
|
extra_rdoc_files: []
|
|
@@ -95,7 +95,6 @@ files:
|
|
|
95
95
|
- lib/better_service/concerns/serviceable/repository_aware.rb
|
|
96
96
|
- lib/better_service/concerns/serviceable/transactional.rb
|
|
97
97
|
- lib/better_service/concerns/serviceable/validatable.rb
|
|
98
|
-
- lib/better_service/concerns/serviceable/viewable.rb
|
|
99
98
|
- lib/better_service/concerns/workflowable.rb
|
|
100
99
|
- lib/better_service/concerns/workflowable/callbacks.rb
|
|
101
100
|
- lib/better_service/concerns/workflowable/context.rb
|
|
@@ -110,6 +109,7 @@ files:
|
|
|
110
109
|
- lib/better_service/errors/runtime/authorization_error.rb
|
|
111
110
|
- lib/better_service/errors/runtime/database_error.rb
|
|
112
111
|
- lib/better_service/errors/runtime/execution_error.rb
|
|
112
|
+
- lib/better_service/errors/runtime/invalid_result_error.rb
|
|
113
113
|
- lib/better_service/errors/runtime/resource_not_found_error.rb
|
|
114
114
|
- lib/better_service/errors/runtime/runtime_error.rb
|
|
115
115
|
- lib/better_service/errors/runtime/transaction_error.rb
|
|
@@ -125,13 +125,8 @@ files:
|
|
|
125
125
|
- lib/better_service/presenter.rb
|
|
126
126
|
- lib/better_service/railtie.rb
|
|
127
127
|
- lib/better_service/repository/base_repository.rb
|
|
128
|
-
- lib/better_service/
|
|
128
|
+
- lib/better_service/result.rb
|
|
129
129
|
- lib/better_service/services/base.rb
|
|
130
|
-
- lib/better_service/services/create_service.rb
|
|
131
|
-
- lib/better_service/services/destroy_service.rb
|
|
132
|
-
- lib/better_service/services/index_service.rb
|
|
133
|
-
- lib/better_service/services/show_service.rb
|
|
134
|
-
- lib/better_service/services/update_service.rb
|
|
135
130
|
- lib/better_service/subscribers/log_subscriber.rb
|
|
136
131
|
- lib/better_service/subscribers/stats_subscriber.rb
|
|
137
132
|
- lib/better_service/version.rb
|
|
@@ -152,15 +147,21 @@ files:
|
|
|
152
147
|
- lib/generators/better_service/templates/presenter.rb.tt
|
|
153
148
|
- lib/generators/better_service/templates/presenter_test.rb.tt
|
|
154
149
|
- lib/generators/serviceable/action_generator.rb
|
|
150
|
+
- lib/generators/serviceable/base_generator.rb
|
|
155
151
|
- lib/generators/serviceable/create_generator.rb
|
|
156
152
|
- lib/generators/serviceable/destroy_generator.rb
|
|
157
153
|
- lib/generators/serviceable/index_generator.rb
|
|
158
154
|
- lib/generators/serviceable/scaffold_generator.rb
|
|
159
155
|
- lib/generators/serviceable/show_generator.rb
|
|
160
156
|
- lib/generators/serviceable/templates/action_service.rb.tt
|
|
157
|
+
- lib/generators/serviceable/templates/base_locale.en.yml.tt
|
|
158
|
+
- lib/generators/serviceable/templates/base_service.rb.tt
|
|
159
|
+
- lib/generators/serviceable/templates/base_service_test.rb.tt
|
|
161
160
|
- lib/generators/serviceable/templates/create_service.rb.tt
|
|
162
161
|
- lib/generators/serviceable/templates/destroy_service.rb.tt
|
|
163
162
|
- lib/generators/serviceable/templates/index_service.rb.tt
|
|
163
|
+
- lib/generators/serviceable/templates/repository.rb.tt
|
|
164
|
+
- lib/generators/serviceable/templates/repository_test.rb.tt
|
|
164
165
|
- lib/generators/serviceable/templates/service_test.rb.tt
|
|
165
166
|
- lib/generators/serviceable/templates/show_service.rb.tt
|
|
166
167
|
- lib/generators/serviceable/templates/update_service.rb.tt
|
|
@@ -185,14 +186,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
185
186
|
requirements:
|
|
186
187
|
- - ">="
|
|
187
188
|
- !ruby/object:Gem::Version
|
|
188
|
-
version: 3.
|
|
189
|
+
version: 3.2.0
|
|
189
190
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
190
191
|
requirements:
|
|
191
192
|
- - ">="
|
|
192
193
|
- !ruby/object:Gem::Version
|
|
193
194
|
version: '0'
|
|
194
195
|
requirements: []
|
|
195
|
-
rubygems_version: 3.5.
|
|
196
|
+
rubygems_version: 3.5.11
|
|
196
197
|
signing_key:
|
|
197
198
|
specification_version: 4
|
|
198
199
|
summary: DSL-based Service Objects framework for Rails
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module BetterService
|
|
4
|
-
module Concerns
|
|
5
|
-
module Serviceable
|
|
6
|
-
module Viewable
|
|
7
|
-
extend ActiveSupport::Concern
|
|
8
|
-
|
|
9
|
-
included do
|
|
10
|
-
class_attribute :_viewer_enabled, default: false
|
|
11
|
-
class_attribute :_viewer_block, default: nil
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
class_methods do
|
|
15
|
-
def viewer(enabled = true, &block)
|
|
16
|
-
self._viewer_enabled = enabled
|
|
17
|
-
self._viewer_block = block if block_given?
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
private
|
|
22
|
-
|
|
23
|
-
def viewer_enabled?
|
|
24
|
-
self.class._viewer_enabled && self.class._viewer_block.present?
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def execute_viewer(processed, transformed, result)
|
|
28
|
-
instance_exec(processed, transformed, result, &self.class._viewer_block)
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "base"
|
|
4
|
-
|
|
5
|
-
module BetterService
|
|
6
|
-
module Services
|
|
7
|
-
# ActionService - Specialized service for custom actions/transitions
|
|
8
|
-
#
|
|
9
|
-
# Returns: { resource: {}, metadata: { action: :custom_action_name } }
|
|
10
|
-
#
|
|
11
|
-
# Example:
|
|
12
|
-
# class Orders::ConfirmService < BetterService::Services::ActionService
|
|
13
|
-
# action_name :confirmed # Sets metadata action
|
|
14
|
-
#
|
|
15
|
-
# schema do
|
|
16
|
-
# required(:id).filled(:integer)
|
|
17
|
-
# end
|
|
18
|
-
#
|
|
19
|
-
# search_with do
|
|
20
|
-
# { resource: user.orders.find(params[:id]) }
|
|
21
|
-
# end
|
|
22
|
-
#
|
|
23
|
-
# process_with do |data|
|
|
24
|
-
# order = data[:resource]
|
|
25
|
-
# order.update!(status: 'confirmed', confirmed_at: Time.current)
|
|
26
|
-
# { resource: order }
|
|
27
|
-
# end
|
|
28
|
-
# end
|
|
29
|
-
class ActionService < Services::Base
|
|
30
|
-
# Default action_name to nil - subclasses MUST set it
|
|
31
|
-
self._action_name = nil
|
|
32
|
-
|
|
33
|
-
def self.action_name(name)
|
|
34
|
-
self._action_name = name.to_sym
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Default schema - requires id parameter for actions
|
|
38
|
-
schema do
|
|
39
|
-
required(:id).filled
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
private
|
|
43
|
-
|
|
44
|
-
# Override respond to ensure resource key is present
|
|
45
|
-
def respond(data)
|
|
46
|
-
# Get base result (from custom respond_with block or default)
|
|
47
|
-
if self.class._respond_block
|
|
48
|
-
result = instance_exec(data, &self.class._respond_block)
|
|
49
|
-
else
|
|
50
|
-
result = success_result("Action completed successfully", data)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Ensure resource key exists (default to nil if not provided)
|
|
54
|
-
result[:resource] ||= nil
|
|
55
|
-
|
|
56
|
-
result
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "base"
|
|
4
|
-
|
|
5
|
-
module BetterService
|
|
6
|
-
module Services
|
|
7
|
-
# CreateService - Specialized service for creating new resources
|
|
8
|
-
#
|
|
9
|
-
# Returns: { resource: {}, metadata: { action: :created } }
|
|
10
|
-
#
|
|
11
|
-
# Example:
|
|
12
|
-
# class Orders::CreateService < BetterService::Services::CreateService
|
|
13
|
-
# schema do
|
|
14
|
-
# required(:title).filled(:string)
|
|
15
|
-
# required(:total).filled(:decimal)
|
|
16
|
-
# end
|
|
17
|
-
#
|
|
18
|
-
# search_with do
|
|
19
|
-
# {}
|
|
20
|
-
# end
|
|
21
|
-
#
|
|
22
|
-
# process_with do |data|
|
|
23
|
-
# order = user.orders.create!(
|
|
24
|
-
# title: params[:title],
|
|
25
|
-
# total: params[:total]
|
|
26
|
-
# )
|
|
27
|
-
# { resource: order }
|
|
28
|
-
# end
|
|
29
|
-
# end
|
|
30
|
-
class CreateService < Services::Base
|
|
31
|
-
# Set action_name for metadata
|
|
32
|
-
self._action_name = :created
|
|
33
|
-
|
|
34
|
-
# Enable database transactions by default for create operations
|
|
35
|
-
with_transaction true
|
|
36
|
-
|
|
37
|
-
# Enable automatic cache invalidation for create operations
|
|
38
|
-
self._auto_invalidate_cache = true
|
|
39
|
-
|
|
40
|
-
# Default empty schema - subclasses MUST override with specific validations
|
|
41
|
-
schema do
|
|
42
|
-
# Override in subclass with required fields
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
private
|
|
46
|
-
|
|
47
|
-
# Override respond to ensure resource key is present
|
|
48
|
-
def respond(data)
|
|
49
|
-
# Get base result (from custom respond_with block or default)
|
|
50
|
-
if self.class._respond_block
|
|
51
|
-
result = instance_exec(data, &self.class._respond_block)
|
|
52
|
-
else
|
|
53
|
-
result = success_result("Resource created successfully", data)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Ensure resource key exists (default to nil if not provided)
|
|
57
|
-
result[:resource] ||= nil
|
|
58
|
-
|
|
59
|
-
result
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "base"
|
|
4
|
-
|
|
5
|
-
module BetterService
|
|
6
|
-
module Services
|
|
7
|
-
# DestroyService - Specialized service for deleting resources
|
|
8
|
-
#
|
|
9
|
-
# Returns: { resource: {}, metadata: { action: :deleted } }
|
|
10
|
-
#
|
|
11
|
-
# Example:
|
|
12
|
-
# class Orders::DestroyService < BetterService::Services::DestroyService
|
|
13
|
-
# schema do
|
|
14
|
-
# required(:id).filled(:integer)
|
|
15
|
-
# end
|
|
16
|
-
#
|
|
17
|
-
# search_with do
|
|
18
|
-
# { resource: user.orders.find(params[:id]) }
|
|
19
|
-
# end
|
|
20
|
-
#
|
|
21
|
-
# process_with do |data|
|
|
22
|
-
# order = data[:resource]
|
|
23
|
-
# order.destroy!
|
|
24
|
-
# { resource: order }
|
|
25
|
-
# end
|
|
26
|
-
# end
|
|
27
|
-
class DestroyService < Services::Base
|
|
28
|
-
# Set action_name for metadata
|
|
29
|
-
self._action_name = :deleted
|
|
30
|
-
|
|
31
|
-
# Enable database transactions by default for destroy operations
|
|
32
|
-
with_transaction true
|
|
33
|
-
|
|
34
|
-
# Enable automatic cache invalidation for destroy operations
|
|
35
|
-
self._auto_invalidate_cache = true
|
|
36
|
-
|
|
37
|
-
# Default schema - requires id parameter
|
|
38
|
-
schema do
|
|
39
|
-
required(:id).filled
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
private
|
|
43
|
-
|
|
44
|
-
# Override respond to ensure resource key is present
|
|
45
|
-
def respond(data)
|
|
46
|
-
# Get base result (from custom respond_with block or default)
|
|
47
|
-
if self.class._respond_block
|
|
48
|
-
result = instance_exec(data, &self.class._respond_block)
|
|
49
|
-
else
|
|
50
|
-
result = success_result("Resource deleted successfully", data)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Ensure resource key exists (default to nil if not provided)
|
|
54
|
-
result[:resource] ||= nil
|
|
55
|
-
|
|
56
|
-
result
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "base"
|
|
4
|
-
|
|
5
|
-
module BetterService
|
|
6
|
-
module Services
|
|
7
|
-
# IndexService - Specialized service for list/collection endpoints
|
|
8
|
-
#
|
|
9
|
-
# Returns: { items: [], metadata: { action: :index, stats: {}, pagination: {} } }
|
|
10
|
-
#
|
|
11
|
-
# Example:
|
|
12
|
-
# class Orders::IndexService < BetterService::Services::IndexService
|
|
13
|
-
# search_with do
|
|
14
|
-
# { items: user.orders.to_a }
|
|
15
|
-
# end
|
|
16
|
-
#
|
|
17
|
-
# process_with do |data|
|
|
18
|
-
# {
|
|
19
|
-
# items: data[:items],
|
|
20
|
-
# metadata: {
|
|
21
|
-
# stats: { total: data[:items].count },
|
|
22
|
-
# pagination: { page: params[:page] || 1 }
|
|
23
|
-
# }
|
|
24
|
-
# }
|
|
25
|
-
# end
|
|
26
|
-
# end
|
|
27
|
-
class IndexService < Services::Base
|
|
28
|
-
# Set action_name for metadata
|
|
29
|
-
self._action_name = :index
|
|
30
|
-
|
|
31
|
-
# Default schema - can be overridden in subclasses
|
|
32
|
-
schema do
|
|
33
|
-
optional(:page).filled(:integer, gteq?: 1)
|
|
34
|
-
optional(:per_page).filled(:integer, gteq?: 1, lteq?: 100)
|
|
35
|
-
optional(:search).maybe(:string)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
# Override respond to ensure items key is present
|
|
41
|
-
def respond(data)
|
|
42
|
-
# Get base result (from custom respond_with block or default)
|
|
43
|
-
if self.class._respond_block
|
|
44
|
-
result = instance_exec(data, &self.class._respond_block)
|
|
45
|
-
else
|
|
46
|
-
result = success_result("Operation completed successfully", data)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Ensure items key exists (default to empty array if not provided)
|
|
50
|
-
result[:items] ||= []
|
|
51
|
-
|
|
52
|
-
result
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "base"
|
|
4
|
-
|
|
5
|
-
module BetterService
|
|
6
|
-
module Services
|
|
7
|
-
# ShowService - Specialized service for single resource detail endpoints
|
|
8
|
-
#
|
|
9
|
-
# Returns: { resource: {}, metadata: { action: :show } }
|
|
10
|
-
#
|
|
11
|
-
# Example:
|
|
12
|
-
# class Orders::ShowService < BetterService::Services::ShowService
|
|
13
|
-
# search_with do
|
|
14
|
-
# { resource: user.orders.find(params[:id]) }
|
|
15
|
-
# end
|
|
16
|
-
# end
|
|
17
|
-
class ShowService < Services::Base
|
|
18
|
-
# Set action_name for metadata
|
|
19
|
-
self._action_name = :show
|
|
20
|
-
|
|
21
|
-
# Default schema - requires id parameter
|
|
22
|
-
schema do
|
|
23
|
-
required(:id).filled
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
# Override respond to ensure resource key is present
|
|
29
|
-
def respond(data)
|
|
30
|
-
# Get base result (from custom respond_with block or default)
|
|
31
|
-
if self.class._respond_block
|
|
32
|
-
result = instance_exec(data, &self.class._respond_block)
|
|
33
|
-
else
|
|
34
|
-
result = success_result("Operation completed successfully", data)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Ensure resource key exists (default to nil if not provided)
|
|
38
|
-
result[:resource] ||= nil
|
|
39
|
-
|
|
40
|
-
result
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "base"
|
|
4
|
-
|
|
5
|
-
module BetterService
|
|
6
|
-
module Services
|
|
7
|
-
# UpdateService - Specialized service for updating existing resources
|
|
8
|
-
#
|
|
9
|
-
# Returns: { resource: {}, metadata: { action: :updated } }
|
|
10
|
-
#
|
|
11
|
-
# Example:
|
|
12
|
-
# class Orders::UpdateService < BetterService::Services::UpdateService
|
|
13
|
-
# schema do
|
|
14
|
-
# required(:id).filled(:integer)
|
|
15
|
-
# optional(:title).filled(:string)
|
|
16
|
-
# end
|
|
17
|
-
#
|
|
18
|
-
# search_with do
|
|
19
|
-
# { resource: user.orders.find(params[:id]) }
|
|
20
|
-
# end
|
|
21
|
-
#
|
|
22
|
-
# process_with do |data|
|
|
23
|
-
# order = data[:resource]
|
|
24
|
-
# order.update!(params.except(:id))
|
|
25
|
-
# { resource: order }
|
|
26
|
-
# end
|
|
27
|
-
# end
|
|
28
|
-
class UpdateService < Services::Base
|
|
29
|
-
# Set action_name for metadata
|
|
30
|
-
self._action_name = :updated
|
|
31
|
-
|
|
32
|
-
# Enable database transactions by default for update operations
|
|
33
|
-
with_transaction true
|
|
34
|
-
|
|
35
|
-
# Enable automatic cache invalidation for update operations
|
|
36
|
-
self._auto_invalidate_cache = true
|
|
37
|
-
|
|
38
|
-
# Default schema - requires id parameter
|
|
39
|
-
schema do
|
|
40
|
-
required(:id).filled
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
private
|
|
44
|
-
|
|
45
|
-
# Override respond to ensure resource key is present
|
|
46
|
-
def respond(data)
|
|
47
|
-
# Get base result (from custom respond_with block or default)
|
|
48
|
-
if self.class._respond_block
|
|
49
|
-
result = instance_exec(data, &self.class._respond_block)
|
|
50
|
-
else
|
|
51
|
-
result = success_result("Resource updated successfully", data)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Ensure resource key exists (default to nil if not provided)
|
|
55
|
-
result[:resource] ||= nil
|
|
56
|
-
|
|
57
|
-
result
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|