haku 1.3.1 → 1.4.0

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: 5fcbccd5d1d9c9be3d0d66259a210f75e52392ba1d76a7eff4b0ef375caae684
4
- data.tar.gz: 93632c6b6124810c8d08a316a162b449f8680612dec73ffaa931f01490a65a9c
3
+ metadata.gz: ca30959f8f3163c1aa8c7179f0e4ff3d84b2c46b736733ddefdbc3071c433b08
4
+ data.tar.gz: 8f1aaff1f0b2c64480ca5310b42cd68892306b64ac366d7813e99cf2f2616fce
5
5
  SHA512:
6
- metadata.gz: f9fe64de95c0c910d76f0309e746298f20aad3e64ce7222b7e7300645387a585b42a850cfdae520a7a12d5771dbc64c46660a935d9ac658e2b838dff0c7cf55b
7
- data.tar.gz: 5f0d174e5e0676e8fcee566bdb4d980b6a732cf028da40eb9fc1849585757e226add08f8f210bbdbb591ba31425ab9ee337ef57984d6044585bb26b1da069609
6
+ metadata.gz: 89b65efe9dc09eff84a3cf25def2301afaab54c296f8e0eb4b620750addc71af6f222aace23774edfd4b737fd88aed36fb2511373ed7fb3116eb811e97736f27
7
+ data.tar.gz: 296982f10418908126079b27030d5061316703cf2dbe415b8e707414954fd08d6ac36f93a236d930f7c25f818fffbfc3e475b8548f7aefb922b6dd98dcb79c9d
data/.rubocop.yml CHANGED
@@ -15,11 +15,29 @@ AllCops:
15
15
  - "**/gemfiles/**/*"
16
16
  - "**/Appraisals"
17
17
  NewCops: enable
18
- TargetRubyVersion: 2.6
18
+ TargetRubyVersion: 2.7
19
19
 
20
20
  Layout/SpaceAroundEqualsInParameterDefault:
21
21
  EnforcedStyle: no_space
22
22
 
23
+ Metrics/ClassLength:
24
+ CountAsOne:
25
+ - array
26
+ - hash
27
+ - heredoc
28
+
29
+ Metrics/MethodLength:
30
+ CountAsOne:
31
+ - array
32
+ - hash
33
+ - heredoc
34
+
35
+ Metrics/ModuleLength:
36
+ CountAsOne:
37
+ - array
38
+ - hash
39
+ - heredoc
40
+
23
41
  Style/Documentation:
24
42
  Enabled: false
25
43
 
data/Appraisals CHANGED
@@ -1,11 +1,7 @@
1
- appraise "activesupport-6.0" do
2
- gem "activesupport", "6.0"
1
+ appraise "rails-6.1" do
2
+ gem "rails", "~> 6.1.0"
3
3
  end
4
4
 
5
- appraise "activesupport-6.1" do
6
- gem "activesupport", "6.1"
7
- end
8
-
9
- appraise "activesupport-7.0" do
10
- gem "activesupport", "7.0"
5
+ appraise "rails-7.0" do
6
+ gem "rails", "~> 7.0"
11
7
  end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.4.0] - 2022-09-19
4
+ - Improve `Haku::Eventable` module to support more data sources for event properties
5
+ - Add `Haku::Delayable` module to execute service object in background
6
+ - Improve README
7
+ - **Breaking**: Require `activesupport` >= 6.1
8
+ - **Breaking**: Require Ruby >= 2.7
9
+ - Fix CI test invocation
10
+
3
11
  ## [1.3.1] - 2022-04-27
4
12
  - Fix Haku::Controller
5
13
 
data/Gemfile.lock CHANGED
@@ -11,13 +11,13 @@ GIT
11
11
  PATH
12
12
  remote: .
13
13
  specs:
14
- haku (1.3.1)
15
- activesupport (>= 6.0, < 8.0)
14
+ haku (1.4.0)
15
+ activesupport (>= 6.1, < 8.0)
16
16
 
17
17
  GEM
18
18
  remote: https://rubygems.org/
19
19
  specs:
20
- activesupport (7.0.2.4)
20
+ activesupport (7.0.4)
21
21
  concurrent-ruby (~> 1.0, >= 1.0.2)
22
22
  i18n (>= 1.6, < 2)
23
23
  minitest (>= 5.1)
@@ -25,7 +25,7 @@ GEM
25
25
  ast (2.4.2)
26
26
  coderay (1.1.3)
27
27
  concurrent-ruby (1.1.10)
28
- i18n (1.10.0)
28
+ i18n (1.12.0)
29
29
  concurrent-ruby (~> 1.0)
30
30
  method_source (1.0.0)
31
31
  minitest (5.15.0)
@@ -56,7 +56,7 @@ GEM
56
56
  rubocop (~> 1.0)
57
57
  ruby-progressbar (1.11.0)
58
58
  thor (1.2.1)
59
- tzinfo (2.0.4)
59
+ tzinfo (2.0.5)
60
60
  concurrent-ruby (~> 1.0)
61
61
  unicode-display_width (2.1.0)
62
62
 
data/README.md CHANGED
@@ -20,9 +20,18 @@ bundle install
20
20
 
21
21
  ## Usage
22
22
 
23
- ### Basic example
23
+ **Haku** is made up of four modules that add functionality to our service objects:
24
24
 
25
- ````ruby
25
+ * `Haku::Core`
26
+ * `Haku::Delayable`
27
+ * `Haku::Eventable`
28
+ * `Haku::Resourceable`
29
+
30
+ Additionally, it's available the `Haku::Controller` module for use in ours Rails controllers.
31
+
32
+ ### Haku::Core
33
+
34
+ ```ruby
26
35
  class Users::Update
27
36
  include Haku::Core
28
37
 
@@ -49,11 +58,98 @@ response = Users::Update.call(user: User.first, attributes: { name: "Javier" })
49
58
  response.success? # => true
50
59
  response.result # => { resource: <User id="1" ...> }
51
60
  response.resource # => <User id="1" ...>
52
- ````
61
+ ```
62
+
63
+ As you can see, if the payload passed to `success!` or `failure!` is a hash, each key of the hash can be accessed
64
+ directly in response object.
65
+
66
+ ### Haku::Delayable
67
+
68
+ #### Basic example
69
+
70
+ ```ruby
71
+ class Users::ComputeHours
72
+ include Haku::Core
73
+ include Haku::Delayable
74
+
75
+ input :user
76
+
77
+ def call
78
+ # compute expensive data for user
79
+ end
80
+ end
81
+
82
+ Users::ComputeHours.delayed.call(user: User.first)
83
+ ```
84
+
85
+ Use `delayed.call` instead of `call` for execute service object in background using `ActiveJob` job.
86
+
87
+ #### Customize job
88
+
89
+ ```ruby
90
+ Users::ComputeHours.delayed(job: OtherJob).call(user: User.first)
91
+ ```
92
+
93
+ #### Customize job options
94
+
95
+ ```ruby
96
+ Users::ComputeHours.delayed(job: OtherJob, queue: :low, priority: 2).call(user: User.first)
97
+ ```
98
+
99
+ You can pass the same options allowed by ActiveJob
100
+ [set](https://api.rubyonrails.org/v7.0.4/classes/ActiveJob/Core/ClassMethods.html#method-i-set) method:
101
+
102
+
103
+ ### Haku::Eventable
104
+
105
+ #### Basic example
106
+
107
+ ```ruby
108
+ class Users::Update
109
+ include Haku::Core
110
+ include Haku::Eventable
111
+
112
+ input :user, :attributes
113
+ event resource: :user
114
+
115
+ def call
116
+ success! resource: user
117
+ end
118
+ end
119
+
120
+ Users::Update.call(user: User.first, attributes: { name: "Javier" })
121
+
122
+ # => call Event.create(name: "user:update", resource: User.first)
123
+ ```
124
+
125
+ The `name` attribute are calculated using the custom proc from `event_name` config option. You can change it with
126
+
127
+ ```ruby
128
+ event name: 'custom:name', resource: :user
129
+ ```
53
130
 
54
- ### Using resourceable helpers
131
+ #### Properties passed to event model
55
132
 
56
- ````ruby
133
+ Properties that should be passed to event model are defined in `event_properties` config option and by
134
+ default are `actor` `resource`, `target` and `context`.
135
+
136
+ 1. Append base properties. For each property defined in `event_properties` config option, it will try to:
137
+ 1. If defined a instance variable `@event_<property>`, uses the instance variable value to get the value of property.
138
+ 2. If respond_to method called `event_<property>`, method is used to get the value of property.
139
+ 3. If defined a instance variable `@<property>`, uses the instance variable value to get the value of property.
140
+ 4. If respond_to method called `<property>`, method is used to get the value of property.
141
+ 5. In other case, the property is not appended.
142
+ 2. Append properties defined in `event` class method. Overwrites previous values. For each property, will try to:
143
+ 1. If is a block, it is called to get the value of property.
144
+ 2. If is a symbol:
145
+ 1. If defined a instance variable `@<property>`, uses the instance variable value to get the value of property.
146
+ 2. If respond_to `<property>`, method is used to get the value of property.
147
+ 3. In other case, uses the raw value.
148
+
149
+
150
+ ### Haku::Resourceable
151
+
152
+ ```ruby
57
153
  class Users::Update
58
154
  include Haku::Core
59
155
  include Haku::Resourceable
@@ -71,12 +167,15 @@ class Users::Update
71
167
  UserMailer.with(user: user).update.deliver_later
72
168
  end
73
169
  end
74
- ````
170
+ ```
171
+
75
172
 
76
- ### Controller helpers
173
+ ### Haku::Controller
77
174
 
78
175
  ```ruby
79
176
  class UsersController < ApplicationController
177
+ include Haku::Controller
178
+
80
179
  before_action :find_user
81
180
 
82
181
  def update
@@ -101,26 +200,6 @@ class UsersController < ApplicationController
101
200
  end
102
201
  ```
103
202
 
104
- ### Using eventable
105
-
106
- ````ruby
107
- class Users::Update
108
- include Haku::Core
109
- include Haku::Resourceable
110
- include Haku::Eventable
111
-
112
- input :user, :attributes
113
- event resource: :user
114
-
115
- def call
116
- update_resource(user, attributes)
117
- end
118
- end
119
-
120
- Users::Update.call(user: User.first, attributes: { name: "Javier" })
121
-
122
- # => call Event.create(name: "user:update", resource: User.first)
123
- ````
124
203
 
125
204
  ### Using parent class
126
205
 
@@ -135,6 +214,7 @@ class Users::Update < ApplicationAction
135
214
  end
136
215
  ```
137
216
 
217
+
138
218
  ## Configure
139
219
 
140
220
  ### Example
@@ -149,14 +229,13 @@ end
149
229
 
150
230
  ### Allowed options
151
231
 
152
- | Config | Description | Default value |
153
- |:-----------------------------------|:-------------------------------------------------------|:---------------------------------------------------------|
154
- | `enable_in_action_controller_base` | Include controller helpers in `ActionController::Base` | `true` |
155
- | `enable_in_action_controller_api` | Include controller helpers in `ActionController::API` | `true` |
156
- | `event_model` | Name of the model used for create events | `Event` |
157
- | `event_properties` | List of attributes passed from service to event model | `%i[actor resource target context]` |
158
- | `event_property_for_name` | Property used for name in event model | `:name` |
159
- | `event_name` | String or Proc to determine the event name | Custom Proc. Example: `user:created` for `Users::Create` |
232
+ | Config | Description | Default value |
233
+ |:--------------------------|:------------------------------------------------------|:--------------------------------------------------------|
234
+ | `event_model` | Name of the model used for create events | `Event` |
235
+ | `event_properties` | List of attributes passed from service to event model | `%i[actor resource target context]` |
236
+ | `event_property_for_name` | Property used for name in event model | `:name` |
237
+ | `event_name` | String or Proc to determine the event name | Custom Proc. Example: `user:create` for `Users::Create` |
238
+ | `job_queue` | String or Symbol with queue name | `default` |
160
239
 
161
240
 
162
241
  ## Resourceable
@@ -210,6 +289,7 @@ Call to `destroy` method of the `resource`. Invoke `success!` if the model is de
210
289
 
211
290
  For more info please view the [source code](lib/haku/resourceable.rb) of the module.
212
291
 
292
+
213
293
  ## Development
214
294
 
215
295
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
@@ -221,16 +301,19 @@ To release a new version, update the version number in `version.rb`, and then ru
221
301
  which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to
222
302
  [rubygems.org](https://rubygems.org).
223
303
 
304
+
224
305
  ## Contributing
225
306
 
226
307
  Bug reports and pull requests are welcome, please follow
227
308
  [Github Flow](https://docs.github.com/en/get-started/quickstart/github-flow).
228
309
 
310
+
229
311
  ## Code of Conduct
230
312
 
231
313
  Everyone interacting in the Haku project's codebases, issue trackers, chat rooms and mailing lists is expected to
232
314
  follow the [code of conduct](https://github.com/javierav/haku/blob/development/CODE_OF_CONDUCT.md).
233
315
 
316
+
234
317
  ## License
235
318
 
236
319
  Copyright © 2022 Javier Aranda. Released under the terms of the [MIT license](LICENSE).
@@ -2,13 +2,13 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "appraisal", "~> 2.4"
5
+ gem "appraisal", github: "excid3/appraisal", branch: "fix-bundle-env"
6
6
  gem "minitest", "~> 5.0"
7
7
  gem "pry", "~> 0.14"
8
8
  gem "rake", "~> 13.0"
9
9
  gem "rubocop", "~> 1.21"
10
10
  gem "rubocop-minitest", "~> 0.19"
11
11
  gem "rubocop-rake", "~> 0.6"
12
- gem "activesupport", "6.1"
12
+ gem "rails", "~> 6.1.0"
13
13
 
14
14
  gemspec path: "../"
@@ -2,13 +2,13 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "appraisal", "~> 2.4"
5
+ gem "appraisal", github: "excid3/appraisal", branch: "fix-bundle-env"
6
6
  gem "minitest", "~> 5.0"
7
7
  gem "pry", "~> 0.14"
8
8
  gem "rake", "~> 13.0"
9
9
  gem "rubocop", "~> 1.21"
10
10
  gem "rubocop-minitest", "~> 0.19"
11
11
  gem "rubocop-rake", "~> 0.6"
12
- gem "activesupport", "6.0"
12
+ gem "rails", "~> 7.0"
13
13
 
14
14
  gemspec path: "../"
data/lib/haku/core.rb CHANGED
@@ -14,6 +14,7 @@ module Haku
14
14
  attr_reader :params
15
15
 
16
16
  class_attribute :haku_inputs, default: []
17
+ class_attribute :haku_before_call_callbacks, default: []
17
18
  class_attribute :haku_success_callbacks, default: []
18
19
  class_attribute :haku_failure_callbacks, default: []
19
20
  end
@@ -35,6 +36,10 @@ module Haku
35
36
  self.haku_inputs += names
36
37
  end
37
38
 
39
+ def before_call(*methods)
40
+ self.haku_before_call_callbacks += methods
41
+ end
42
+
38
43
  def on_success(*methods)
39
44
  self.haku_success_callbacks += methods
40
45
  end
@@ -48,13 +53,16 @@ module Haku
48
53
 
49
54
  module Callable
50
55
  def call
51
- response = catch(:finish) { super }
56
+ response = catch(:finish) do
57
+ (self.class.send(:haku_before_call_callbacks) || []).each { |cb| send(cb) }
58
+ super
59
+ end
52
60
 
53
61
  status = response.is_a?(Finish) ? response.status : :success
54
62
  payload = response.is_a?(Finish) ? response.payload : response
55
63
 
56
64
  Result.new(status, payload).tap do
57
- _haku_run_callbacks(status)
65
+ haku_run_callbacks(status)
58
66
  end
59
67
  end
60
68
  end
@@ -77,7 +85,7 @@ module Haku
77
85
  throw :finish, Finish.new(:failure, data)
78
86
  end
79
87
 
80
- def _haku_run_callbacks(status)
88
+ def haku_run_callbacks(status)
81
89
  (self.class.send("haku_#{status}_callbacks") || []).each { |cb| send(cb) }
82
90
  end
83
91
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+ require "active_support/core_ext/string/inflections"
5
+
6
+ module Haku
7
+ module Delayable
8
+ extend ActiveSupport::Concern
9
+
10
+ if defined?(ActiveJob::Base)
11
+ class Job < ActiveJob::Base
12
+ def perform(klass, params)
13
+ klass.call(params)
14
+ end
15
+ end
16
+ end
17
+
18
+ class Delayed
19
+ def initialize(service, options={})
20
+ @service = service
21
+ @options = options.reverse_merge(
22
+ job: "::Haku::Delayable::Job",
23
+ queue: Haku.job_queue
24
+ )
25
+ end
26
+
27
+ def call(params={})
28
+ if job.present? && defined?(job)
29
+ job.set(@options).perform_later(@service, params)
30
+ else
31
+ @service.call(params)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def job
38
+ @job ||= begin
39
+ job = @options.delete(:job)
40
+ job.is_a?(String) ? job.safe_constantize : job
41
+ end
42
+ end
43
+ end
44
+
45
+ module ClassMethods
46
+ def delayed(options={})
47
+ ::Haku::Delayable::Delayed.new(self, options)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -47,21 +47,25 @@ module Haku
47
47
 
48
48
  def haku_event_data_base(data)
49
49
  Haku.event_properties.each do |property|
50
- data[property] = send(property) if respond_to?(property)
50
+ haku_event_data_base_value_for_property(data, property)
51
51
  end
52
52
  end
53
53
 
54
- def haku_process_value(value)
55
- if value.respond_to?(:call)
56
- instance_exec(&value)
57
- else
58
- value.is_a?(Symbol) ? send(value) : value
54
+ def haku_event_data_base_value_for_property(data, property)
55
+ if instance_variable_defined?("@event_#{property}")
56
+ data[property] = instance_variable_get("@event_#{property}")
57
+ elsif respond_to?("event_#{property}", true)
58
+ data[property] = send("event_#{property}")
59
+ elsif instance_variable_defined?("@#{property}")
60
+ data[property] = instance_variable_get("@#{property}")
61
+ elsif respond_to?(property, true)
62
+ data[property] = send(property)
59
63
  end
60
64
  end
61
65
 
62
66
  def haku_event_data_name(data, evt)
63
67
  key = Haku.event_property_for_name.to_sym
64
- data[key] = evt[key] || haku_process_value(Haku.event_name)
68
+ data[key] = haku_process_value(evt[key] || Haku.event_name)
65
69
  end
66
70
 
67
71
  def haku_event_data_values(data, evt)
@@ -70,6 +74,18 @@ module Haku
70
74
  end
71
75
  end
72
76
 
77
+ def haku_process_value(value)
78
+ if value.respond_to?(:call)
79
+ instance_exec(&value)
80
+ else
81
+ value.is_a?(Symbol) ? haku_process_symbol_value(value) : value
82
+ end
83
+ end
84
+
85
+ def haku_process_symbol_value(value)
86
+ instance_variable_defined?("@#{value}") ? instance_variable_get("@#{value}") : send(value)
87
+ end
88
+
73
89
  def haku_create_event(data)
74
90
  Haku.event_model.safe_constantize&.create(data)
75
91
  end
data/lib/haku/version.rb CHANGED
@@ -3,8 +3,8 @@
3
3
  module Haku
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 3
7
- TINY = 1
6
+ MINOR = 4
7
+ TINY = 0
8
8
  PRE = nil
9
9
 
10
10
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
data/lib/haku.rb CHANGED
@@ -4,6 +4,7 @@ require "active_support/core_ext/module/attribute_accessors"
4
4
  require "active_support/core_ext/string/inflections"
5
5
  require_relative "haku/controller"
6
6
  require_relative "haku/core"
7
+ require_relative "haku/delayable"
7
8
  require_relative "haku/eventable"
8
9
  require_relative "haku/resourceable"
9
10
  require_relative "haku/version"
@@ -16,6 +17,7 @@ module Haku
16
17
  chain = self.class.name.underscore.split("/")
17
18
  (chain[0...-1].map(&:singularize) + [chain.last]).join(":")
18
19
  }
20
+ mattr_accessor :job_queue, default: :default
19
21
 
20
22
  class << self
21
23
  def configure
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haku
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Javier Aranda
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-27 00:00:00.000000000 Z
11
+ date: 2022-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '6.0'
19
+ version: '6.1'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '8.0'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '6.0'
29
+ version: '6.1'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '8.0'
@@ -52,12 +52,12 @@ files:
52
52
  - LICENSE
53
53
  - README.md
54
54
  - Rakefile
55
- - gemfiles/activesupport_6.0.gemfile
56
- - gemfiles/activesupport_6.1.gemfile
57
- - gemfiles/activesupport_7.0.gemfile
55
+ - gemfiles/rails_6.1.gemfile
56
+ - gemfiles/rails_7.0.gemfile
58
57
  - lib/haku.rb
59
58
  - lib/haku/controller.rb
60
59
  - lib/haku/core.rb
60
+ - lib/haku/delayable.rb
61
61
  - lib/haku/eventable.rb
62
62
  - lib/haku/resourceable.rb
63
63
  - lib/haku/result.rb
@@ -67,8 +67,8 @@ licenses:
67
67
  - MIT
68
68
  metadata:
69
69
  homepage_uri: https://github.com/javierav/haku
70
- source_code_uri: https://github.com/javierav/haku/tree/v1.3.1
71
- changelog_uri: https://github.com/javierav/haku/blob/v1.3.1/CHANGELOG.md
70
+ source_code_uri: https://github.com/javierav/haku/tree/v1.4.0
71
+ changelog_uri: https://github.com/javierav/haku/blob/v1.4.0/CHANGELOG.md
72
72
  rubygems_mfa_required: 'true'
73
73
  post_install_message:
74
74
  rdoc_options:
@@ -79,7 +79,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 2.6.0
82
+ version: 2.7.0
83
83
  required_rubygems_version: !ruby/object:Gem::Requirement
84
84
  requirements:
85
85
  - - ">="
@@ -1,14 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal", "~> 2.4"
6
- gem "minitest", "~> 5.0"
7
- gem "pry", "~> 0.14"
8
- gem "rake", "~> 13.0"
9
- gem "rubocop", "~> 1.21"
10
- gem "rubocop-minitest", "~> 0.19"
11
- gem "rubocop-rake", "~> 0.6"
12
- gem "activesupport", "7.0"
13
-
14
- gemspec path: "../"