simple_command 0.0.9 → 0.1.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.rb +3 -0
- data/lib/simple_command/errors.rb +18 -0
- data/lib/simple_command/version.rb +1 -1
- data/spec/simple_command/errors_spec.rb +34 -0
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e1f9517aa67b971a3bf9f8a44789254c5bdcc0e790abba2dd154043d7654012a
|
4
|
+
data.tar.gz: d137bb78badaff5767a9dc692d685cd7d6280cf3413b0fd3df2c954922055c4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f1dde12a3f9d6258fd6d85fd9591aaec4c9bd1839de53b511224a924d5faba132de927c375fe56898fb87862c33c2379fcd0410e3f5ce2cd2abeb5e54378593
|
7
|
+
data.tar.gz: 70b63c426ec5e29060cdb9ce0b7c7457d84564b4ba109a481eb1cfe1779c1f2069bc1f878bb3c972abd1674bc3e1d0dfcd3a285cb9fc75e498c40eabe70a8c6e
|
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.add(
|
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 )
|
data/lib/simple_command.rb
CHANGED
@@ -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
|
|
@@ -13,5 +13,23 @@ module SimpleCommand
|
|
13
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
|
@@ -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
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrea Pavoni
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -95,8 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
requirements: []
|
98
|
-
|
99
|
-
rubygems_version: 2.4.5
|
98
|
+
rubygems_version: 3.0.6
|
100
99
|
signing_key:
|
101
100
|
specification_version: 4
|
102
101
|
summary: Easy way to build and manage commands (service objects)
|