rails_use_case 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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