activeduty 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/README.md +155 -1
- data/lib/active_duty/callbacks.rb +13 -6
- data/lib/active_duty/initializers.rb +89 -17
- data/lib/active_duty/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b879bfa0f660945b57f5b87a67ddef1bf55dd91fdece4c5dc07820d93950d90
|
4
|
+
data.tar.gz: 13c31dbba265e4d3e738a417595633deee7e837e23eaff04b5154b3f299ca77a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8833e8338c11c2cc0c398485268e0d3947079c3b109efc071ee025018e03959b051a6c2b9d4d44b00550071536816aaa9be6d68b7376773654425a7fdc4773e1
|
7
|
+
data.tar.gz: 44b5d6e28ab6ba25f9fd150a9b9df4f3f3ca670a33bd39d426e01b107688ab3aaa94dca3c20165503f995d9ea2571cb0ef969cb5da19e4845ef6adbcd91a2f5d
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,3 +1,157 @@
|
|
1
1
|
# ActiveDuty
|
2
2
|
|
3
|
-
Service objects.
|
3
|
+
Service objects, based loosely on [Interactor](https://github.com/collectiveidea/interactor).
|
4
|
+
|
5
|
+
## Design
|
6
|
+
|
7
|
+
Define the logic in `run` and call it with `call`:
|
8
|
+
|
9
|
+
## Basic usage
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
class AuthenticateUser < ActiveDuty::Base
|
13
|
+
def initialize(email, password)
|
14
|
+
@email, @password = email, password
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
if user = User.authenticate(@email, @password)
|
19
|
+
context.user = user
|
20
|
+
else
|
21
|
+
fail!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
Usage:
|
28
|
+
|
29
|
+
```
|
30
|
+
service = AuthenticateUser.new("josh@example.com", password: "password")
|
31
|
+
service.call
|
32
|
+
if service.success?
|
33
|
+
# do something
|
34
|
+
else
|
35
|
+
puts service.errors.inspect
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
## Advanced usage
|
40
|
+
|
41
|
+
### init_with
|
42
|
+
|
43
|
+
A DSL for initializing.
|
44
|
+
|
45
|
+
#### Ordered arguments
|
46
|
+
|
47
|
+
```
|
48
|
+
class AuthenticateUser < ActiveDuty::Base
|
49
|
+
init_with :username, :password
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
Is the equivalent of:
|
54
|
+
|
55
|
+
```
|
56
|
+
class AuthenticateUser < ActiveDuty::Base
|
57
|
+
attr_reader :username, :password
|
58
|
+
def initialize(username, password)
|
59
|
+
@username, @password = username, password
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
#### Keyword arguments
|
65
|
+
|
66
|
+
```
|
67
|
+
class AuthenticateUser < ActiveDuty::Base
|
68
|
+
init_with uname: :username, pw: :password
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
Is the equivalent of:
|
73
|
+
|
74
|
+
```
|
75
|
+
class AuthenticateUser < ActiveDuty::Base
|
76
|
+
attr_reader :username, :password
|
77
|
+
def initialize(uname:, pw:)
|
78
|
+
@username, @password = uname, pw
|
79
|
+
end
|
80
|
+
end
|
81
|
+
```
|
82
|
+
|
83
|
+
#### Defaults
|
84
|
+
|
85
|
+
```
|
86
|
+
class AuthenticateUser < ActiveDuty::Base
|
87
|
+
init_with :username, [:password, nil]
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
Is the equivalent of:
|
92
|
+
|
93
|
+
```
|
94
|
+
class AuthenticateUser < ActiveDuty::Base
|
95
|
+
attr_reader :username, :password
|
96
|
+
def initialize(username, password = nil)
|
97
|
+
@username, @password = username, password
|
98
|
+
end
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
#### Keyword arguments
|
103
|
+
|
104
|
+
```
|
105
|
+
class AuthenticateUser < ActiveDuty::Base
|
106
|
+
init_with uname: [nil, :username], pw: ["good-password", :password]
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
Is the equivalent of:
|
111
|
+
|
112
|
+
```
|
113
|
+
class AuthenticateUser < ActiveDuty::Base
|
114
|
+
attr_reader :username, :password
|
115
|
+
def initialize(uname: nil, pw: "good-password")
|
116
|
+
@username, @password = uname, pw
|
117
|
+
end
|
118
|
+
end
|
119
|
+
```
|
120
|
+
|
121
|
+
### Callbacks
|
122
|
+
|
123
|
+
Supports `after_initialize`, `before_call`, `after_call`. They use `ActiveModel::Callbacks` under the hood, so the API is familiar.
|
124
|
+
|
125
|
+
### Context
|
126
|
+
|
127
|
+
An `OpenStruct` for a setting information during the runtime of your service object. Exposed via `context`.
|
128
|
+
|
129
|
+
### Errors
|
130
|
+
|
131
|
+
Uses `ActiveModel::Errors` under the hood.
|
132
|
+
|
133
|
+
### Rollbacks
|
134
|
+
|
135
|
+
If your call fails and you need to do some housekeeping, define a rollback:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
class AuthenticateUser < ActiveDuty::Base
|
139
|
+
def rollback
|
140
|
+
# do something
|
141
|
+
end
|
142
|
+
end
|
143
|
+
```
|
144
|
+
|
145
|
+
Or class-level:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
class AuthenticateUser < ActiveDuty::Base
|
149
|
+
rollback do
|
150
|
+
# do something
|
151
|
+
end
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
### Failing
|
156
|
+
|
157
|
+
Need to fail? Call `fail!`
|
@@ -6,20 +6,27 @@ module ActiveDuty
|
|
6
6
|
define_model_callbacks :call, only: [:before, :after, :around]
|
7
7
|
|
8
8
|
def self.after_initialize(&block)
|
9
|
-
@
|
9
|
+
@_after_initialize_callbacks ||= []
|
10
|
+
@_after_initialize_callbacks << block
|
10
11
|
end
|
11
12
|
|
12
|
-
def self.
|
13
|
-
if defined?(@
|
14
|
-
@
|
13
|
+
def self._after_initialize_callbacks
|
14
|
+
if defined?(@_after_initialize_callbacks)
|
15
|
+
@_after_initialize_callbacks
|
15
16
|
else
|
16
17
|
nil
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
21
|
def after_initialize!
|
21
|
-
if self.class.
|
22
|
-
|
22
|
+
if self.class._after_initialize_callbacks
|
23
|
+
self.class._after_initialize_callbacks.each do |callback|
|
24
|
+
if callback.is_a?(Symbol)
|
25
|
+
send(callback)
|
26
|
+
else
|
27
|
+
instance_exec(self, &callback)
|
28
|
+
end
|
29
|
+
end
|
23
30
|
end
|
24
31
|
end
|
25
32
|
end
|
@@ -4,28 +4,100 @@ module ActiveDuty
|
|
4
4
|
module ClassMethods
|
5
5
|
def init_with(*args)
|
6
6
|
kwargs = args.extract_options!
|
7
|
-
|
8
7
|
if kwargs.empty?
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
init_from_ordered(args)
|
9
|
+
else
|
10
|
+
init_from_kw(kwargs)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# initialize from ordered arguments
|
17
|
+
#
|
18
|
+
# init_with :username, :password
|
19
|
+
# def initialize(username, password)
|
20
|
+
# @username = username
|
21
|
+
# @password = password
|
22
|
+
#
|
23
|
+
# init_with [:username], [:password, nil], [:email, "no email"], [:options, {}]
|
24
|
+
# def initialize(username, password = nil, email: "no email", options = {})
|
25
|
+
# @username = username
|
26
|
+
# @password = password
|
27
|
+
# @email = email
|
28
|
+
# @options = options
|
29
|
+
def init_from_ordered(args)
|
30
|
+
init_string = []
|
31
|
+
args.each do |arg|
|
32
|
+
str = ""
|
33
|
+
if arg.is_a?(Array)
|
34
|
+
if arg.size == 2
|
35
|
+
if arg[1].is_a?(String)
|
36
|
+
str << "#{arg[0]} = \"#{arg[1]}\""
|
37
|
+
else
|
38
|
+
str << "#{arg[0]} = #{arg[1]}"
|
39
|
+
end
|
40
|
+
else
|
41
|
+
str << "#{arg[0]}"
|
12
42
|
end
|
13
|
-
|
43
|
+
else
|
44
|
+
str << "#{arg}"
|
14
45
|
end
|
15
|
-
|
16
|
-
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
17
|
-
def initialize(#{kwargs.keys.map { |key| "#{key}:" }.join(', ')})
|
18
|
-
#{kwargs.map { |key, value|
|
19
|
-
"
|
20
|
-
instance_variable_set(:\"@#{value}\", #{key})
|
21
|
-
self.class.attr_reader :#{value}
|
22
|
-
"
|
23
|
-
}.join("\n")
|
24
|
-
}
|
25
|
-
end
|
26
|
-
METHOD
|
46
|
+
init_string << str
|
27
47
|
end
|
48
|
+
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
49
|
+
def initialize(#{init_string.join(', ')})
|
50
|
+
#{args.map { |arg|
|
51
|
+
if arg.is_a?(Array)
|
52
|
+
"instance_variable_set(:\"@#{arg[0]}\", #{arg[0]})
|
53
|
+
self.class.attr_reader :#{arg[0]}"
|
54
|
+
else
|
55
|
+
"instance_variable_set(:\"@#{arg}\", #{arg})
|
56
|
+
self.class.attr_reader :#{arg}"
|
57
|
+
end
|
58
|
+
}.join("\n")
|
59
|
+
}
|
60
|
+
end
|
61
|
+
METHOD
|
62
|
+
end
|
63
|
+
|
64
|
+
# Initialize with keyword args.
|
65
|
+
#
|
66
|
+
# { username: :user } will
|
67
|
+
# def initialize(username:)
|
68
|
+
# @user = username
|
69
|
+
#
|
70
|
+
# { username: ["Bob", :user] } will
|
71
|
+
# def initialize(username: "Bob")
|
72
|
+
# @user = username
|
73
|
+
def init_from_kw(args)
|
28
74
|
|
75
|
+
initializer_string = []
|
76
|
+
args.each do |key, values|
|
77
|
+
str = "#{key}:"
|
78
|
+
if values.is_a?(Array) && values.size == 2
|
79
|
+
if values[0].is_a?(String)
|
80
|
+
str += " \"#{values[0]}\""
|
81
|
+
else
|
82
|
+
str += "#{values[0]}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
initializer_string << str
|
86
|
+
end
|
87
|
+
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
88
|
+
def initialize(#{initializer_string.join(', ')})
|
89
|
+
#{args.map { |key, values|
|
90
|
+
if values.is_a?(Array)
|
91
|
+
"instance_variable_set(:\"@#{values[1]}\", #{key})
|
92
|
+
self.class.attr_reader :#{values[1]}"
|
93
|
+
else
|
94
|
+
"instance_variable_set(:\"@#{values}\", #{key})
|
95
|
+
self.class.attr_reader :#{values}"
|
96
|
+
end
|
97
|
+
}.join("\n")
|
98
|
+
}
|
99
|
+
end
|
100
|
+
METHOD
|
29
101
|
end
|
30
102
|
|
31
103
|
end
|
data/lib/active_duty/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeduty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Brody
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-07-
|
11
|
+
date: 2020-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -86,6 +86,7 @@ executables: []
|
|
86
86
|
extensions: []
|
87
87
|
extra_rdoc_files: []
|
88
88
|
files:
|
89
|
+
- CHANGELOG.md
|
89
90
|
- README.md
|
90
91
|
- lib/active_duty.rb
|
91
92
|
- lib/active_duty/base.rb
|