rails_use_case 0.0.1 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e353dd38951526d2e38dd2007380d710c8c6bdec5634a0daeefc9fe4ce4ab469
4
- data.tar.gz: c4624ac8f94c97634f84e03f89361947b0eea1da221e5654a718c5f015807285
3
+ metadata.gz: eccdc9b039ad948018925576475a8857da769828aef5f58f2426901b6cca77c3
4
+ data.tar.gz: 5ed1d23accbd83dda0428d7fc3f959366e49e5a2cb29e95ec1e641f1063d8942
5
5
  SHA512:
6
- metadata.gz: 2637b2676bc1cce54bbda93b1ee5a3a62bed6bc3adde5ed5fca63730fcaa5ae6bc0161786bc236383a24b649caebb0f1c61211a745ec81030fbaee41375bb3e3
7
- data.tar.gz: 55b19f9294a4a3993beb36e305e8a158f91b5a35ad16a4468a42c6822f60537802a05238ee2b82cd18acff27e59b5b3a1fdff6cd38a223132a330d4ecab4fbc7
6
+ metadata.gz: 931eb6a75e1d92604c5f1e33140a3ddd3c20f6cbad225814f4d6e75e801e95f09d3a738d778643221f29b82f2c188c2c007e4449313297bacfee4eacd41bacd2
7
+ data.tar.gz: aa4cc82f951293c672211129cdf27968bca51a218305982c55929b13ba5cafd9b60edcce5b89824b6ba4108ad0c8ec8dc3dbed6d06cc841ea04d0a4ed4b2aa1d
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # Rails Use Case gem
2
2
 
3
- Opinionated gem for UseCases and Services in rails.
3
+ Opinionated gem for UseCases and Services in rails to keep models and controllers slim.
4
+
5
+ The purpose of a UseCase is to contain reusable high level business logic which would normally be
6
+ located in the controller. Examples are: Place an item in the cart, create a new user or delete a comment.
7
+
8
+ The purpose of a Service is to contain low level non-domain code like communication with a API,
9
+ generating an export, upload via FTP or generating a PDF.
4
10
 
5
11
 
6
12
  ## Setup
@@ -10,9 +16,124 @@ gem 'rails_use_case'
10
16
  ```
11
17
 
12
18
 
13
- ## Usage
19
+ ## Use Case
20
+
21
+ The purpose of a UseCase is to contain reusable high level business logic which would normally be
22
+ located in the controller. It defines a process via `step` definitions. A UseCase takes params
23
+ and has a outcome, which is successfully or failed. It doesn't have a configuration file and doesn't
24
+ log anything. Examples are: Place an item in the cart, create a new user or delete a comment.
25
+
26
+ Steps are executed in the defined order. Only when a step succeeds (returns true) the next step will
27
+ be executed. Steps can be skipped via `if` and `unless`.
28
+
29
+ The UseCase should assign the main record to `@record`. Calling save! without argument will try to
30
+ save that record or raises an exception. Also the `@record` will automatically passed into the outcome.
31
+
32
+ The params should always passed as hash and are automatically assigned to instance variables.
33
+
34
+ ### Example UseCase
35
+
36
+ ```ruby
37
+ class CreateBlogPost < Rails::UseCase
38
+ attr_accessor :title, :content, :author, :skip_notifications
39
+
40
+ validates :title, presence: true
41
+ validates :content, presence: true
42
+ validates :author, presence: true
43
+
44
+ step :build_post
45
+ step :save!
46
+ step :notify_subscribers, unless: -> { skip_notifications }
47
+
48
+
49
+ private def build_post
50
+ @record = BlogPost.new(
51
+ title: title,
52
+ content: content,
53
+ created_by: author,
54
+ type: :default
55
+ )
56
+ end
57
+
58
+ private def notify_subscribers
59
+ # ... send some mails ...
60
+ end
61
+ end
62
+ ```
63
+
64
+ Example usage of that UseCase:
65
+
66
+ ```ruby
67
+ result = CreateBlogPost.perform(
68
+ title: 'Super Awesome Stuff!',
69
+ content: 'Lorem Ipsum Dolor Sit Amet',
70
+ created_by: current_user,
71
+ skip_notifications: false
72
+ )
73
+
74
+ puts result.inspect
75
+ # => {
76
+ # success: true,
77
+ # record: BlogPost(...)
78
+ # errors: [],
79
+ # error: nil
80
+ # }
81
+ ```
82
+
83
+
84
+ ## Service
85
+
86
+ The purpose of a Service is to contain low level non-domain code like communication with a API,
87
+ generating an export, upload via FTP or generating a PDF. It takes params, has it's own configuration
88
+ and writes a log file.
89
+
90
+ It comes with call style invocation: `PDFGenerationService.(some, params)`
91
+
92
+ ### Example Service
93
+
94
+ ```ruby
95
+ class PDFGenerationService < Rails::Service
96
+ attr_reader :pdf_template, :values
97
+
98
+ # Constructor.
99
+ def initialize
100
+ super 'pdf_generation'
101
+ prepare
102
+ validate_libreoffice
103
+ end
104
+
105
+
106
+ # Entry point.
107
+ #
108
+ # @param [PdfTemplate] pdf_template PdfTemplate record.
109
+ # @param [Hash<String, String>] values Mapping of variables to their values.
110
+ #
111
+ # @returns [String] Path to PDF file.
112
+ def call(pdf_template, values = {})
113
+ @pdf_template = pdf_template
114
+ @values = prepare_variable_values(values)
115
+
116
+ write_odt_file
117
+ replace_variables
118
+ generate_pdf
119
+
120
+ @pdf_file_path
121
+ ensure
122
+ delete_tempfile
123
+ end
124
+ end
125
+ ```
126
+
127
+ ### Configuration
128
+
129
+ The service tries to automatically load a configuration from `config/services/[service_name].yml`
130
+ which is available via the `config` method.
131
+
132
+
133
+ ### Logging
14
134
 
15
- TODO
135
+ The service los to a separate log file `log/services/[service_name].log`. You can write additional
136
+ logs via `logger.info(msg)`.
16
137
 
17
138
 
18
139
  ## License
@@ -1,35 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_model/validations'
3
+ require 'active_model'
4
4
  require 'rails/use_case/outcome'
5
5
 
6
6
  module Rails
7
- # A UseCase is a class that contains high level business logic.
8
- # It's used to keep controllers and models slim.
9
- #
10
- # The difference to a Service is that a Service contains low level
11
- # non-domain code like communication with a API, generating an
12
- # export, etc., while a UseCase contains high level domain logic
13
- # like placing a item in the cart, submitting an order, etc.
14
- #
15
- # The logic of a UseCase is defined via steps. The next step is only
16
- # executed when the previous ones returned a truthy value.
17
- #
18
- # The UseCase should assign the main record to @record. Calling save!
19
- # without argument will try to save that record or raises an exception.
20
- #
21
- # A UseCase should raise the UseCase::Error exception for any
22
- # problems.
23
- #
24
- # UseCase also includes ActiveModel::Validations for simple yet
25
- # powerful validations. The validations are run automatically as first step.
26
- #
27
- # A UseCase can be called via .call(params) or .perform(params) and
28
- # always returns a instance of UseCase::Outcome. params should be a hash.
29
- class Rails::UseCase
7
+ # UseCase. See README.
8
+ class UseCase
30
9
  include Callable
31
10
  include ActiveModel::Validations
32
11
 
12
+ attr_reader :record
13
+
33
14
  class Error < StandardError; end
34
15
 
35
16
  class << self
@@ -115,13 +96,18 @@ module Rails
115
96
  # @param record [ApplicationModel] Record to save.
116
97
  # @raises [UseCase::Error] When record can't be saved.
117
98
  private def save!(record = nil)
118
- record ||= @record
99
+ if record.nil?
100
+ record = @record
101
+ name = :record
102
+ else
103
+ name = record.model_name.singular
104
+ end
119
105
 
120
106
  return false unless record
121
107
  return true if record.save
122
108
 
123
109
  errors.add(
124
- record.model_name.singular,
110
+ name,
125
111
  :invalid,
126
112
  message: record.errors.full_messages.join(', ')
127
113
  )
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Namespace
3
4
  module Rails; end
4
5
 
5
6
  require 'rails/callable'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_use_case
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Klein