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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e1e044db947afd477d7b8042fbd679fdffbd8a63
4
- data.tar.gz: 021cfb1817dd007895a76184af0db53095c0c9a1
2
+ SHA256:
3
+ metadata.gz: 8847792f86f2c4162d832d2603abfb7f0f40208110ad339484851dfaeeb99cf4
4
+ data.tar.gz: ba9e8c0e1d46fb25d8408f430ba462e14e2ca386e5cd7b4c611d7787523448a0
5
5
  SHA512:
6
- metadata.gz: 0a88837defef4d2cc6f3c7167e0f891f73dd09ff6378a5719df8772e8a4f1bdd7cd22043ca29b3596d9e53d619c9a714d03c2107a27d3746150c8f3d167d2730
7
- data.tar.gz: ea8a66ec330153ba06932837a9795d7931c3741faed743c3ebdaa40e211ffde726a173121a84c6a91c89cca5561308373d04aca9d0a776764ce195d8f75694f2
6
+ metadata.gz: d4fa95128f6e3fcd15419705bf36d56c33b8da0ced34b068940a3ee3fe066feeada465f8257f5076a87f3e237bd0adfd83b377a1d68bf9e81a09240bae5be243
7
+ data.tar.gz: 8cc7cea6c22b3af310b039eee0f041f0ac5c48597d8cc13122771ffdef67a54dcf2ce8f2b77172ad3c6425e5598024d2ef48d95a7562083c94c3d1419348a7e0
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
+ [![Code Climate](https://codeclimate.com/github/nebulab/simple_command/badges/gpa.svg)](https://codeclimate.com/github/nebulab/simple_command)
2
+ [ ![Codeship Status for nebulab/simple_command](https://app.codeship.com/projects/45ce7790-8daf-0132-1412-669677a474c3/status?branch=master)](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(user, password)
37
- @user = user
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.authenticate(@email, @password)
48
+ if user = User.find_by(email: @email)&.authenticate(@password)
45
49
  return user
46
50
  else
47
- errors.add_error(authentication: I18n.t "authenticate_user.failure")
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[:user], session_params[:password])
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[:authentication])
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 add_error(key, value)
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| add_error key, 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
@@ -1,3 +1,3 @@
1
1
  module SimpleCommand
2
- VERSION = '0.0.8'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -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
 
@@ -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', '~> 1.7'
23
- s.add_development_dependency 'rake', '~> 10.0'
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 '#add_error' do
6
+ describe '#add' do
7
7
  before do
8
- errors.add_error :some_error, 'some error description'
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.add_error :some_error, 'some error description'
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
@@ -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.add_error(:some_error, 'some message')
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.add_error(:some_error, 'some message')
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.add_error(:some_error, 'some message')
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.8
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: 2015-01-19 00:00:00.000000000 Z
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: '1.7'
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: '1.7'
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: '10.0'
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: '10.0'
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
- rubyforge_project:
99
- rubygems_version: 2.4.5
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: