simple_command 0.0.8 → 0.2.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 +5 -5
- data/README.md +51 -7
- data/lib/simple_command/errors.rb +20 -2
- data/lib/simple_command/version.rb +1 -1
- data/lib/simple_command.rb +5 -2
- data/simple_command.gemspec +2 -2
- data/spec/simple_command/errors_spec.rb +37 -3
- data/spec/simple_command_spec.rb +3 -3
- metadata +14 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8847792f86f2c4162d832d2603abfb7f0f40208110ad339484851dfaeeb99cf4
|
|
4
|
+
data.tar.gz: ba9e8c0e1d46fb25d8408f430ba462e14e2ca386e5cd7b4c611d7787523448a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d4fa95128f6e3fcd15419705bf36d56c33b8da0ced34b068940a3ee3fe066feeada465f8257f5076a87f3e237bd0adfd83b377a1d68bf9e81a09240bae5be243
|
|
7
|
+
data.tar.gz: 8cc7cea6c22b3af310b039eee0f041f0ac5c48597d8cc13122771ffdef67a54dcf2ce8f2b77172ad3c6425e5598024d2ef48d95a7562083c94c3d1419348a7e0
|
data/README.md
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
[](https://codeclimate.com/github/nebulab/simple_command)
|
|
2
|
+
[ ](https://app.codeship.com/projects/60741)
|
|
3
|
+
|
|
1
4
|
# SimpleCommand
|
|
2
5
|
|
|
3
6
|
A simple, standardized way to build and use _Service Objects_ (aka _Commands_) in Ruby
|
|
@@ -31,34 +34,46 @@ Here's a basic example of a command that authenticates a user
|
|
|
31
34
|
class AuthenticateUser
|
|
32
35
|
# put SimpleCommand before the class' ancestors chain
|
|
33
36
|
prepend SimpleCommand
|
|
37
|
+
include ActiveModel::Validations
|
|
34
38
|
|
|
35
39
|
# optional, initialize the command with some arguments
|
|
36
|
-
def initialize(
|
|
37
|
-
@
|
|
40
|
+
def initialize(email, password)
|
|
41
|
+
@email = email
|
|
38
42
|
@password = password
|
|
39
43
|
end
|
|
40
44
|
|
|
41
45
|
# mandatory: define a #call method. its return value will be available
|
|
42
46
|
# through #result
|
|
43
47
|
def call
|
|
44
|
-
if user = User.
|
|
48
|
+
if user = User.find_by(email: @email)&.authenticate(@password)
|
|
45
49
|
return user
|
|
46
50
|
else
|
|
47
|
-
errors.
|
|
51
|
+
errors.add(:base, :failure)
|
|
48
52
|
end
|
|
49
53
|
nil
|
|
50
54
|
end
|
|
51
55
|
end
|
|
52
56
|
```
|
|
53
57
|
|
|
58
|
+
in your locale file
|
|
59
|
+
```yaml
|
|
60
|
+
# config/locales/en.yml
|
|
61
|
+
en:
|
|
62
|
+
activemodel:
|
|
63
|
+
errors:
|
|
64
|
+
models:
|
|
65
|
+
authenticate_user:
|
|
66
|
+
failure: Wrong email or password
|
|
67
|
+
```
|
|
68
|
+
|
|
54
69
|
Then, in your controller:
|
|
55
70
|
|
|
56
71
|
```ruby
|
|
57
72
|
class SessionsController < ApplicationController
|
|
58
73
|
def create
|
|
59
74
|
# initialize and execute the command
|
|
60
|
-
# NOTE: `.call` is a shortcut for `.new(args).call
|
|
61
|
-
command = AuthenticateUser.call(session_params[:
|
|
75
|
+
# NOTE: `.call` is a shortcut for `.new(args).call`
|
|
76
|
+
command = AuthenticateUser.call(session_params[:email], session_params[:password])
|
|
62
77
|
|
|
63
78
|
# check command outcome
|
|
64
79
|
if command.success?
|
|
@@ -66,7 +81,7 @@ class SessionsController < ApplicationController
|
|
|
66
81
|
session[:user_token] = command.result.secret_token
|
|
67
82
|
redirect_to root_path
|
|
68
83
|
else
|
|
69
|
-
flash.now[:alert] = t(command.errors
|
|
84
|
+
flash.now[:alert] = t(command.errors.full_messages.to_sentence)
|
|
70
85
|
render :new
|
|
71
86
|
end
|
|
72
87
|
end
|
|
@@ -79,6 +94,35 @@ class SessionsController < ApplicationController
|
|
|
79
94
|
end
|
|
80
95
|
```
|
|
81
96
|
|
|
97
|
+
## Test with Rspec
|
|
98
|
+
Make the spec file `spec/commands/authenticate_user_spec.rb` like:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
describe AuthenticateUser do
|
|
102
|
+
subject(:context) { described_class.call(username, password) }
|
|
103
|
+
|
|
104
|
+
describe '.call' do
|
|
105
|
+
context 'when the context is successful' do
|
|
106
|
+
let(:username) { 'correct_user' }
|
|
107
|
+
let(:password) { 'correct_password' }
|
|
108
|
+
|
|
109
|
+
it 'succeeds' do
|
|
110
|
+
expect(context).to be_success
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
context 'when the context is not successful' do
|
|
115
|
+
let(:username) { 'wrong_user' }
|
|
116
|
+
let(:password) { 'wrong_password' }
|
|
117
|
+
|
|
118
|
+
it 'fails' do
|
|
119
|
+
expect(context).to be_failure
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
```
|
|
125
|
+
|
|
82
126
|
## Contributing
|
|
83
127
|
|
|
84
128
|
1. Fork it ( https://github.com/nebulab/simple_command/fork )
|
|
@@ -2,7 +2,7 @@ module SimpleCommand
|
|
|
2
2
|
class NotImplementedError < ::StandardError; end
|
|
3
3
|
|
|
4
4
|
class Errors < Hash
|
|
5
|
-
def
|
|
5
|
+
def add(key, value, _opts = {})
|
|
6
6
|
self[key] ||= []
|
|
7
7
|
self[key] << value
|
|
8
8
|
self[key].uniq!
|
|
@@ -10,8 +10,26 @@ module SimpleCommand
|
|
|
10
10
|
|
|
11
11
|
def add_multiple_errors(errors_hash)
|
|
12
12
|
errors_hash.each do |key, values|
|
|
13
|
-
values.each { |value|
|
|
13
|
+
values.each { |value| add key, value }
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
|
+
|
|
17
|
+
def each
|
|
18
|
+
each_key do |field|
|
|
19
|
+
self[field].each { |message| yield field, message }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def full_messages
|
|
24
|
+
map { |attribute, message| full_message(attribute, message) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
def full_message(attribute, message)
|
|
29
|
+
return message if attribute == :base
|
|
30
|
+
attr_name = attribute.to_s.tr('.', '_').capitalize
|
|
31
|
+
"%s %s" % [attr_name, message]
|
|
32
|
+
end
|
|
33
|
+
|
|
16
34
|
end
|
|
17
35
|
end
|
data/lib/simple_command.rb
CHANGED
|
@@ -5,8 +5,8 @@ module SimpleCommand
|
|
|
5
5
|
attr_reader :result
|
|
6
6
|
|
|
7
7
|
module ClassMethods
|
|
8
|
-
def call(*args)
|
|
9
|
-
new(*args).call
|
|
8
|
+
def call(*args, **kwargs)
|
|
9
|
+
new(*args, **kwargs).call
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -26,12 +26,15 @@ module SimpleCommand
|
|
|
26
26
|
def success?
|
|
27
27
|
called? && !failure?
|
|
28
28
|
end
|
|
29
|
+
alias_method :successful?, :success?
|
|
29
30
|
|
|
30
31
|
def failure?
|
|
31
32
|
called? && errors.any?
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def errors
|
|
36
|
+
return super if defined?(super)
|
|
37
|
+
|
|
35
38
|
@errors ||= Errors.new
|
|
36
39
|
end
|
|
37
40
|
|
data/simple_command.gemspec
CHANGED
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
|
19
19
|
s.test_files = s.files.grep(/^(test|spec|features)\//)
|
|
20
20
|
s.require_paths = ['lib']
|
|
21
21
|
|
|
22
|
-
s.add_development_dependency 'bundler'
|
|
23
|
-
s.add_development_dependency 'rake'
|
|
22
|
+
s.add_development_dependency 'bundler'
|
|
23
|
+
s.add_development_dependency 'rake'
|
|
24
24
|
s.add_development_dependency 'rspec', '~> 3.1'
|
|
25
25
|
end
|
|
@@ -3,9 +3,9 @@ require 'spec_helper'
|
|
|
3
3
|
describe SimpleCommand::Errors do
|
|
4
4
|
let(:errors) { SimpleCommand::Errors.new }
|
|
5
5
|
|
|
6
|
-
describe '#
|
|
6
|
+
describe '#add' do
|
|
7
7
|
before do
|
|
8
|
-
errors.
|
|
8
|
+
errors.add :some_error, 'some error description'
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
it 'adds the error' do
|
|
@@ -13,7 +13,7 @@ describe SimpleCommand::Errors do
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
it 'adds the same error only once' do
|
|
16
|
-
errors.
|
|
16
|
+
errors.add :some_error, 'some error description'
|
|
17
17
|
expect(errors[:some_error]).to eq(['some error description'])
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -35,4 +35,38 @@ describe SimpleCommand::Errors do
|
|
|
35
35
|
expect(errors[:another_error]).to eq(errors_list[:another_error])
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
|
+
|
|
39
|
+
describe '#each' do
|
|
40
|
+
let(:errors_list) do
|
|
41
|
+
{
|
|
42
|
+
email: ['taken'],
|
|
43
|
+
password: ['blank', 'too short']
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
before { errors.add_multiple_errors(errors_list) }
|
|
48
|
+
|
|
49
|
+
it 'yields each message for the same key independently' do
|
|
50
|
+
expect { |b| errors.each(&b) }.to yield_control.exactly(3).times
|
|
51
|
+
expect { |b| errors.each(&b) }.to yield_successive_args(
|
|
52
|
+
[:email, 'taken'],
|
|
53
|
+
[:password, 'blank'],
|
|
54
|
+
[:password, 'too short']
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe '#full_messages' do
|
|
60
|
+
before do
|
|
61
|
+
errors.add :attr1, 'has an error'
|
|
62
|
+
errors.add :attr2, 'has an error'
|
|
63
|
+
errors.add :attr2, 'has two errors'
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "returrns the full messages array" do
|
|
67
|
+
expect(errors.full_messages).to eq ["Attr1 has an error", "Attr2 has an error", "Attr2 has two errors"]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|
|
38
72
|
end
|
data/spec/simple_command_spec.rb
CHANGED
|
@@ -40,7 +40,7 @@ describe SimpleCommand do
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
it 'is false if something went wrong' do
|
|
43
|
-
command.errors.
|
|
43
|
+
command.errors.add(:some_error, 'some message')
|
|
44
44
|
expect(command.call.success?).to be_falsy
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -69,7 +69,7 @@ describe SimpleCommand do
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
it 'is true if something went wrong' do
|
|
72
|
-
command.errors.
|
|
72
|
+
command.errors.add(:some_error, 'some message')
|
|
73
73
|
expect(command.call.failure?).to be_truthy
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -93,7 +93,7 @@ describe SimpleCommand do
|
|
|
93
93
|
|
|
94
94
|
context 'with errors' do
|
|
95
95
|
before do
|
|
96
|
-
command.errors.
|
|
96
|
+
command.errors.add(:some_error, 'some message')
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
it 'has a key with error message' do
|
metadata
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: simple_command
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrea Pavoni
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-04-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '0'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
33
|
+
version: '0'
|
|
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: '
|
|
40
|
+
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rspec
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,7 +80,7 @@ homepage: http://github.com/nebulab/simple_command
|
|
|
80
80
|
licenses:
|
|
81
81
|
- MIT
|
|
82
82
|
metadata: {}
|
|
83
|
-
post_install_message:
|
|
83
|
+
post_install_message:
|
|
84
84
|
rdoc_options: []
|
|
85
85
|
require_paths:
|
|
86
86
|
- lib
|
|
@@ -95,9 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: '0'
|
|
97
97
|
requirements: []
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
signing_key:
|
|
98
|
+
rubygems_version: 3.2.20
|
|
99
|
+
signing_key:
|
|
101
100
|
specification_version: 4
|
|
102
101
|
summary: Easy way to build and manage commands (service objects)
|
|
103
102
|
test_files:
|