actionizer 0.3.0 → 0.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
  SHA1:
3
- metadata.gz: 0c2200e547ac2adeb77d8ab2394037f7006550c5
4
- data.tar.gz: d8865ebe73d8d765f8452b31db58ed24b804f69c
3
+ metadata.gz: 7d164afc660031126496b00a38e931702afd5814
4
+ data.tar.gz: ddd5bf72049506461b926b387355dffadfd4dc42
5
5
  SHA512:
6
- metadata.gz: cb086adc3bb250d211d585f92379ca3fa9292c4b5336676e49beb2cf59c0f18d2274f7137cd1480e2ef82a6f8854c20467b8d453788cb36fda5da85b0e134f94
7
- data.tar.gz: 63a124f87db6bd8ee1c6aa2808adfbe6a6cb82cfdf214ab56c9a7191a8e9f3e82e4f21df88f7bafd4cb2e475b3a99e52ad0adc875bfd488e82b6d6c11b9aead5
6
+ metadata.gz: e335eb30321f19c246d4087b6ad7aa824efbca9971b1aa1a0dc42c9c2d9bfe2fca5d9ceb59160aef88d49b8961c6a2a19fcad1e84f4d7d8ed7d9f7aa41017ebe
7
+ data.tar.gz: 9fc717ebadfb532442bc080ff3ff49300611ed1ef3a07eabad9c33f498ee7c074e7653e352a363576fd730e228af0447ab59ab8208ee6b43b77e220caef78daa
data/README.md CHANGED
@@ -24,82 +24,81 @@ Or install it yourself as:
24
24
 
25
25
  ## Usage
26
26
 
27
- Here's how you define an Action:
27
+ Include `Actionizer` in your class and define an instance method. That instance method will be automatically invoked when you call the class method of the same name. Any Action defined with `Actionizer` will automatically return a hash-like result you can check for `success?` or `failure?`.
28
28
 
29
- ```ruby
30
- module Action
31
- module Users
32
-
33
- class Create
34
- include Actionizer
29
+ Inputs are available on the `input` instance variable. Use `output` to set any variables you want returned in the result.
35
30
 
36
- def call
37
- # Do stuff here
38
- output.user = user
39
- end
40
- end
31
+ ```ruby
32
+ class CreateUser
33
+ include Actionizer
41
34
 
35
+ def call
36
+ # Some validation here...
37
+ output.user = User.create(name: input.name)
42
38
  end
43
39
  end
44
40
  ```
45
41
 
46
- You can immediately stop execution with the `fail!` method
42
+ Actions are successful by default:
47
43
  ```ruby
48
- module Action
49
- module Users
44
+ result = SuccessfulAction.call(id: 1234)
50
45
 
51
- class Delete
52
- include Actionizer
46
+ result.success?
47
+ #=> true
48
+ result.failure?
49
+ #=> false
50
+ ```
53
51
 
54
- def call
55
- # Possibly failing code here
56
- fail!(error: "Nope, didn't work") if failure_condition
52
+ You can immediately stop execution with the `fail!` method.
53
+ ```ruby
54
+ class DeleteAccount
55
+ include Actionizer
57
56
 
58
- # This code never runs
59
- output.foo = 'bar'
60
- end
61
- end
57
+ def run
58
+ # Possibly failing code here
59
+ fail!(error: "Nope, didn't work") if failure_condition
62
60
 
61
+ # This code never runs
62
+ output.foo = 'bar'
63
63
  end
64
64
  end
65
65
  ```
66
66
 
67
- Here's how you invoke it:
67
+ When an action fails with `fail!`, the result it returns will return false for `success?` and true for `failure?`.
68
68
  ```ruby
69
- module Action
70
- module Users
69
+ result = FailingAction.call(id: 1234)
71
70
 
72
- class Onboard
73
- include Actionizer
71
+ result.success?
72
+ #=> false
73
+ result.failure?
74
+ #=> true
75
+ ```
74
76
 
75
- def call
76
- result = Action::Users::Create.call(name: name, email: email)
77
- fail!(error: result.error) if result.failure?
77
+ The most common way to use Actionizer is to compose small pieces of functionality (which can themselves be Actions) into larger pieces of functionality to give that sequence of Actions a name and simple interface.
78
+ ```ruby
79
+ class OnboardUser
80
+ include Actionizer
78
81
 
79
- result = Action::Users::SendWelcomeEmail.call(name: name, email: email)
80
- fail!(error: result.error) if result.failure?
81
- end
82
- end
82
+ def call
83
+ result = CreateUser.call(name: input.name, email: input.email)
84
+ fail!(error: result.error) if result.failure?
83
85
 
86
+ result = SendWelcomeEmail.deliver_now(name: input.name, email: input.email)
87
+ fail!(error: result.error) if result.failure?
84
88
  end
85
89
  end
86
90
  ```
87
91
 
88
- This pattern is so common, there's a shorthand: `call_and_check_failure!`
89
- ```ruby
90
- module Action
91
- module Users
92
92
 
93
- class Onboard
94
- include Actionizer
95
-
96
- def call
97
- # This code is identical to the example above
98
- call_and_check_failure!(Action::Users::Create, name: name, email: email)
99
- call_and_check_failure!(Action::Users::SendWelcomeEmail, name: name, email: email)
100
- end
101
- end
93
+ This pattern is so common, there's a shorthand: `<METHOD>_or_fail`. It works for any instance method defined on the class you specify.
94
+ ```ruby
95
+ class OnboardUser
96
+ include Actionizer
102
97
 
98
+ def call
99
+ # This code is identical to the example above
100
+ call_or_fail(CreateUser, name: input.name, email: input.email)
101
+ deliver_now_or_fail(SendWelcomeEmail, name: input.name, email: input.email)
103
102
  end
104
103
  end
105
104
  ```
data/actionizer.gemspec CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency 'bundler', '~> 1.11'
32
32
  spec.add_development_dependency 'rake', '~> 10.0'
33
33
  spec.add_development_dependency 'rspec', '~> 3.0'
34
- spec.add_development_dependency 'byebug', '~> 8.2'
34
+ spec.add_development_dependency 'pry-byebug', '~> 3.3'
35
35
  spec.add_development_dependency 'rubocop', '~> 0.37'
36
36
  spec.add_development_dependency 'simplecov', '~> 0.11'
37
37
  end
data/lib/actionizer.rb CHANGED
@@ -6,17 +6,25 @@ module Actionizer
6
6
  attr_reader :input, :output
7
7
 
8
8
  def self.included(base)
9
- base.class_eval do
10
- extend ClassMethods
11
- end
9
+ base.extend(ClassMethods)
12
10
  end
13
11
 
14
12
  module ClassMethods
15
- def call(inputs = {})
16
- new(inputs).tap(&:call).output
13
+ def method_missing(method_name, *args, &block)
14
+ instance = new(*args)
15
+
16
+ if instance.respond_to?(method_name)
17
+ instance.tap(&method_name).output
18
+ else
19
+ super
20
+ end
17
21
  rescue Actionizer::Failure => af
18
22
  af.output
19
23
  end
24
+
25
+ def respond_to_missing?(method_name, include_private = false)
26
+ new.respond_to?(method_name, include_private)
27
+ end
20
28
  end
21
29
 
22
30
  def initialize(initial_input = {})
@@ -32,14 +40,23 @@ module Actionizer
32
40
  raise Actionizer::Failure.new('Failed!', output)
33
41
  end
34
42
 
35
- def call_and_check_failure!(action_class, params = {})
43
+ # Allows you to call *_or_fail
44
+ def method_missing(method_name, *args, &block)
45
+ return super unless method_name.to_s.end_with?('_or_fail')
46
+
47
+ action_class, params = *args
48
+
36
49
  unless action_class.include? Actionizer
37
50
  raise ArgumentError, "#{action_class.name} must include Actionizer"
38
51
  end
39
52
 
40
- result = action_class.call(params)
53
+ result = action_class.send(method_name.to_s.chomp('_or_fail'), params)
41
54
  fail!(error: result.error) if result.failure?
42
55
 
43
56
  result
44
57
  end
58
+
59
+ def respond_to_missing?(method_name, _include_private = false)
60
+ method_name.to_s.end_with?('_or_fail')
61
+ end
45
62
  end
@@ -1,3 +1,3 @@
1
1
  module Actionizer
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Nichols
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-03 00:00:00.000000000 Z
11
+ date: 2016-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -67,19 +67,19 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: byebug
70
+ name: pry-byebug
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '8.2'
75
+ version: '3.3'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '8.2'
82
+ version: '3.3'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement