service_record 1.3.0 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3af5f714dc3195cb0877476b9d1a7c048549cd9c19ba40ab59a30d67a3d92ff0
4
- data.tar.gz: fc6cf02ec07809395a782754a3416bafcaf26e59c3a8af911233a69958585cf2
3
+ metadata.gz: 761226eff3ab278171ca2a9250b6fe089ceb53eeb2b1e221b680d250c3f1d2be
4
+ data.tar.gz: 567e4aa90fff412e1d42eba985a9e7a3f6397a53d622ec7e996503e22aa78a75
5
5
  SHA512:
6
- metadata.gz: ad3d7ab806691128d9790ea1f4d5e40f47b99435d0b68421b24d7c049af01783d942b2b39a9bf8357116e16d0d1bf728ce69ef73013b32dcc9630e1fe2d7ae54
7
- data.tar.gz: 46d7eecfa6bdfcb4b323ea6f5858c19e56689c160b1ef0265c49ff9633eaf3789a27b7bce1de7b8809127502109e66b95c961ae946f4f4cfc23f132c392d229b
6
+ metadata.gz: 24c06c7384fca171053cd271ef96107ee36753015bd4198ed1b6f87e4ea5fe68db663d4a7a9e7b50af6cd8a03d71bce575ff3e17d8ffba2045442b55e8dafb19
7
+ data.tar.gz: 2889e28b5f8507849beaef07ce99fd886063a4cf40c91d035ad92190788d8322d956e0315aa94a85a067471671a36d634171e84a26d56c65692fd651c0b998de
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # ServiceRecord
2
2
 
3
+ [![Gem](https://img.shields.io/gem/v/service_record)](https://rubygems.org/gems/service_record)
3
4
  [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/uxxman/service_record/CI)](https://github.com/uxxman/service_record/actions?query=workflow%3ACI)
4
5
  [![Code Climate coverage](https://img.shields.io/codeclimate/coverage/uxxman/service_record)](https://codeclimate.com/github/uxxman/service_record)
5
6
  [![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/uxxman/service_record)](https://codeclimate.com/github/uxxman/service_record)
6
- [![Gem](https://img.shields.io/gem/v/service_record)](https://rubygems.org/gems/service_record)
7
7
 
8
8
  An ActiveRecord lookalike but for business model requirements, a.k.a Service Objects.
9
9
 
10
10
  Rails is packed with amazing tools to get you started with building your new awesome project and enforces reliable and battle-tested guidelines. One of those guideline is "**thin controllers and fat models**", but sometimes (actually most of the time) its difficult to follow because most business requirements are not that simple like most CRUD operations.
11
11
 
12
- Enters, ServiceRecord. Its similar to ActiveRecord models but their sole purpose is to perform a big/complex/muilt-step task without bloating the controllers or models.
12
+ Enters, ServiceRecord, a tiny wrapper around basic goodies included in Rails. Its similar to ActiveRecord models but their sole purpose is to perform a big/complex/muilt-step task without bloating the controllers or models.
13
13
 
14
14
  ## Installation
15
15
 
@@ -66,9 +66,7 @@ The returned response from a service will have the following useful attributes/m
66
66
  * `result` contains returned value of service perform function
67
67
  * `errors` contains details about issues that occurr while performing the service
68
68
 
69
- There is a **perform!** (with a bang !) method which will raise **ServiceRecord::Failure** in case of service failure.
70
-
71
-
69
+ There is also a **perform!** (with a bang !) method which will raise **ServiceRecord::Failure** in case of service failure.
72
70
 
73
71
  ## Example
74
72
 
@@ -83,12 +81,12 @@ def sign_in
83
81
  errors = []
84
82
 
85
83
  # Basic validation
86
- errors << 'Email is required' if params[:email].blank?
87
- errors << 'Email is invalid' if params[:email].present? && /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i.match?(params[:email])
84
+ errors << 'Email is required' if params[:email].blank?
85
+ errors << 'Email is invalid' if params[:email].present? && /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i.match?(params[:email])
88
86
  errors << 'Password is required' if params[:password].blank?
89
87
 
90
88
  if errors.size == 0
91
- user = User.find_by(email: params[:email]).try(:authenticate, params[:password])
89
+ user = User.find_by(email: params[:email])&.try(:authenticate, params[:password])
92
90
 
93
91
  if user.present?
94
92
  token = JsonWebToken.encode(user_id: user.id)
@@ -119,9 +117,11 @@ class AuthenticateUser < ApplicationService
119
117
  def perform
120
118
  user = User.find_by(email: email).try(:authenticate, password)
121
119
 
122
- return JsonWebToken.encode(user_id: user.id) if user.present?
123
-
124
- errors.add :authentication, 'invalid credentials'
120
+ if user.present?
121
+ JsonWebToken.encode(user_id: user.id)
122
+ else
123
+ errors.add :authentication, 'invalid credentials'
124
+ end
125
125
  end
126
126
  end
127
127
 
@@ -174,7 +174,9 @@ Availble callbacks are `before_perform`, `after_perform` and `around_perform`. I
174
174
 
175
175
  ## Development
176
176
 
177
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
177
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
178
+
179
+ ServiceRecord uses appraisals to test the code base against multiple versions of Rails ActiveModel. When first developing, you need to run `bundle install` and then `bundle exec appraisal install`, to install the different gem sets. You can then run all appraisal files (like CI does), with `appraisal rake`.
178
180
 
179
181
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
180
182
 
@@ -2,13 +2,14 @@
2
2
 
3
3
  require 'active_model'
4
4
  require 'service_record/failure'
5
+ require 'service_record/response'
5
6
  require 'service_record/callbacks'
6
7
 
7
8
  module ServiceRecord
8
9
  # Base class to be extended by all service classes
9
10
  #
10
- # class MyService < ServiceRecord
11
- # end
11
+ # class MyService < ServiceRecord
12
+ # end
12
13
  #
13
14
  class Base
14
15
  include Callbacks
@@ -23,11 +24,14 @@ module ServiceRecord
23
24
  def self.perform(args = {})
24
25
  new.tap do |service|
25
26
  service.attributes = args
26
- break service unless service.valid?
27
27
 
28
- service.run_callbacks :perform do
29
- service.result = service.perform
28
+ if service.valid?
29
+ service.run_callbacks :perform do
30
+ service.result = service.perform
31
+ end
30
32
  end
33
+
34
+ return Response.new(service.result, service.errors)
31
35
  end
32
36
  end
33
37
 
@@ -39,16 +43,6 @@ module ServiceRecord
39
43
  raise Failure, service
40
44
  end
41
45
 
42
- # Checks the service for errors. Returns +true+ if no errors are found, +false+ otherwise.
43
- def success?
44
- errors.empty?
45
- end
46
-
47
- # Checks the service for errors. Returns +false+ if no errors are found, +true+ otherwise.
48
- def failure?
49
- !success?
50
- end
51
-
52
46
  # Each subclass must define the *perform* method
53
47
  def perform
54
48
  raise NotImplementedError
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ServiceRecord
4
+ # Response to be returned by a service when it finishes
5
+ class Response
6
+ attr_reader :result, :errors
7
+
8
+ def initialize(result, errors)
9
+ @result = result
10
+ @errors = errors
11
+ end
12
+
13
+ # Checks for errors. Returns +true+ if no errors are found, +false+ otherwise.
14
+ def success?
15
+ errors.empty?
16
+ end
17
+
18
+ # Checks for errors. Returns +false+ if no errors are found, +true+ otherwise.
19
+ def failure?
20
+ !success?
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ServiceRecord
4
- VERSION = '1.3.0'
4
+ VERSION = '1.4.0'
5
5
  end
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'service_record/base'
4
+ require 'service_record/version'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: service_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muhammad Usman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-28 00:00:00.000000000 Z
11
+ date: 2022-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.3'
33
+ version: '2.4'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.3'
40
+ version: '2.4'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -45,9 +45,6 @@ dependencies:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '13.0'
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: 13.0.1
51
48
  type: :development
52
49
  prerelease: false
53
50
  version_requirements: !ruby/object:Gem::Requirement
@@ -55,9 +52,6 @@ dependencies:
55
52
  - - "~>"
56
53
  - !ruby/object:Gem::Version
57
54
  version: '13.0'
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 13.0.1
61
55
  - !ruby/object:Gem::Dependency
62
56
  name: rspec
63
57
  requirement: !ruby/object:Gem::Requirement
@@ -78,88 +72,88 @@ dependencies:
78
72
  requirements:
79
73
  - - "~>"
80
74
  - !ruby/object:Gem::Version
81
- version: 0.5.1
75
+ version: 0.5.2
82
76
  type: :development
83
77
  prerelease: false
84
78
  version_requirements: !ruby/object:Gem::Requirement
85
79
  requirements:
86
80
  - - "~>"
87
81
  - !ruby/object:Gem::Version
88
- version: 0.5.1
82
+ version: 0.5.2
89
83
  - !ruby/object:Gem::Dependency
90
84
  name: rubocop-performance
91
85
  requirement: !ruby/object:Gem::Requirement
92
86
  requirements:
93
87
  - - "~>"
94
88
  - !ruby/object:Gem::Version
95
- version: '1.8'
89
+ version: '1.14'
96
90
  - - ">="
97
91
  - !ruby/object:Gem::Version
98
- version: 1.8.1
92
+ version: 1.14.3
99
93
  type: :development
100
94
  prerelease: false
101
95
  version_requirements: !ruby/object:Gem::Requirement
102
96
  requirements:
103
97
  - - "~>"
104
98
  - !ruby/object:Gem::Version
105
- version: '1.8'
99
+ version: '1.14'
106
100
  - - ">="
107
101
  - !ruby/object:Gem::Version
108
- version: 1.8.1
102
+ version: 1.14.3
109
103
  - !ruby/object:Gem::Dependency
110
104
  name: rubocop-rails
111
105
  requirement: !ruby/object:Gem::Requirement
112
106
  requirements:
113
107
  - - "~>"
114
108
  - !ruby/object:Gem::Version
115
- version: '2.8'
109
+ version: '2.15'
116
110
  - - ">="
117
111
  - !ruby/object:Gem::Version
118
- version: 2.8.1
112
+ version: 2.15.2
119
113
  type: :development
120
114
  prerelease: false
121
115
  version_requirements: !ruby/object:Gem::Requirement
122
116
  requirements:
123
117
  - - "~>"
124
118
  - !ruby/object:Gem::Version
125
- version: '2.8'
119
+ version: '2.15'
126
120
  - - ">="
127
121
  - !ruby/object:Gem::Version
128
- version: 2.8.1
122
+ version: 2.15.2
129
123
  - !ruby/object:Gem::Dependency
130
124
  name: rubocop-rake
131
125
  requirement: !ruby/object:Gem::Requirement
132
126
  requirements:
133
127
  - - "~>"
134
128
  - !ruby/object:Gem::Version
135
- version: 0.5.1
129
+ version: 0.6.0
136
130
  type: :development
137
131
  prerelease: false
138
132
  version_requirements: !ruby/object:Gem::Requirement
139
133
  requirements:
140
134
  - - "~>"
141
135
  - !ruby/object:Gem::Version
142
- version: 0.5.1
136
+ version: 0.6.0
143
137
  - !ruby/object:Gem::Dependency
144
138
  name: rubocop-rspec
145
139
  requirement: !ruby/object:Gem::Requirement
146
140
  requirements:
147
- - - ">="
148
- - !ruby/object:Gem::Version
149
- version: 1.44.1
150
141
  - - "~>"
151
142
  - !ruby/object:Gem::Version
152
- version: '2.0'
143
+ version: '2.12'
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: 2.12.1
153
147
  type: :development
154
148
  prerelease: false
155
149
  version_requirements: !ruby/object:Gem::Requirement
156
150
  requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: 1.44.1
160
151
  - - "~>"
161
152
  - !ruby/object:Gem::Version
162
- version: '2.0'
153
+ version: '2.12'
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: 2.12.1
163
157
  - !ruby/object:Gem::Dependency
164
158
  name: simplecov
165
159
  requirement: !ruby/object:Gem::Requirement
@@ -192,6 +186,7 @@ files:
192
186
  - lib/service_record/base.rb
193
187
  - lib/service_record/callbacks.rb
194
188
  - lib/service_record/failure.rb
189
+ - lib/service_record/response.rb
195
190
  - lib/service_record/version.rb
196
191
  homepage: https://github.com/uxxman/service_record
197
192
  licenses:
@@ -209,14 +204,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
209
204
  requirements:
210
205
  - - ">="
211
206
  - !ruby/object:Gem::Version
212
- version: 2.5.0
207
+ version: 2.7.5
213
208
  required_rubygems_version: !ruby/object:Gem::Requirement
214
209
  requirements:
215
210
  - - ">="
216
211
  - !ruby/object:Gem::Version
217
212
  version: '0'
218
213
  requirements: []
219
- rubygems_version: 3.3.3
214
+ rubygems_version: 3.3.7
220
215
  signing_key:
221
216
  specification_version: 4
222
217
  summary: Service objects for rails