simple_command 0.0.9 → 1.0.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: dd27f8350ae4a2243a2f2bde7f2481edda37ee2e
4
- data.tar.gz: dcf03e07231a348a26747e94d346c20c77d119c5
2
+ SHA256:
3
+ metadata.gz: 709a8e79d062fc2df30ceb2515a4996dac770a1a06b26cfedef243b560fa86d4
4
+ data.tar.gz: 6b30945ca6b05353376bb3636f42c501d7c349ded063adc98706628ced2ecc03
5
5
  SHA512:
6
- metadata.gz: 3c2ddec2804d8f4c60376bb562e8e82cf753fcbed65dfd8713cfecec668592c2b67267d1bd1036db5507dd999ddb6083fc12b402f2b3f8da7d7da262024881c6
7
- data.tar.gz: 471b1498238e7a5e444d2f61af683ed78c823dc24b300dcd7f38f2629f50e187731fb3d4adc6b38b4178f03bb2fc36e2e435ae017c7e25b865f02b81be108899
6
+ metadata.gz: 5e9a41d79fe67caa53d69c54d690958f62eae87ef54c8e966360854adb4b1716580446255ccf5767a35aaea9f45ac53c1d20b0686b5ff30cd715ac37074d5d8c
7
+ data.tar.gz: 5ac692c46307b7f034658608b8217e5a367587b91760ca7f38aebb8cca3612eae9b29f3069ddb896b6ffbadd8b12f600609ebcc6b38c2f06f395358c9dc5655b
@@ -0,0 +1,23 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+
8
+ runs-on: ubuntu-latest
9
+
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ ruby: ["2.7", "3.0", "3.1", ruby-head, jruby-9.3, jruby-head]
14
+
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ bundler-cache: true # 'bundle install' and cache gems
21
+ ruby-version: ${{ matrix.ruby }}
22
+ - name: Run tests
23
+ run: bundle exec rake
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(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 )
@@ -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 key, value }
13
+ SimpleCommand::Utils.array_wrap(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
@@ -0,0 +1,14 @@
1
+ module SimpleCommand
2
+ module Utils
3
+ # Borrowed from active_support/core_ext/array/wrap
4
+ def self.array_wrap(object)
5
+ if object.nil?
6
+ []
7
+ elsif object.respond_to?(:to_ary)
8
+ object.to_ary || [object]
9
+ else
10
+ [object]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module SimpleCommand
2
- VERSION = '0.0.9'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -1,12 +1,13 @@
1
1
  require 'simple_command/version'
2
+ require 'simple_command/utils'
2
3
  require 'simple_command/errors'
3
4
 
4
5
  module SimpleCommand
5
6
  attr_reader :result
6
7
 
7
8
  module ClassMethods
8
- def call(*args)
9
- new(*args).call
9
+ def call(*args, **kwargs)
10
+ new(*args, **kwargs).call
10
11
  end
11
12
  end
12
13
 
@@ -26,12 +27,15 @@ module SimpleCommand
26
27
  def success?
27
28
  called? && !failure?
28
29
  end
30
+ alias_method :successful?, :success?
29
31
 
30
32
  def failure?
31
33
  called? && errors.any?
32
34
  end
33
35
 
34
36
  def errors
37
+ return super if defined?(super)
38
+
35
39
  @errors ||= Errors.new
36
40
  end
37
41
 
@@ -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
@@ -19,20 +19,66 @@ describe SimpleCommand::Errors do
19
19
  end
20
20
 
21
21
  describe '#add_multiple_errors' do
22
- let(:errors_list) do
23
- {
22
+ it 'populates itself with the added errors' do
23
+ errors_list = {
24
24
  some_error: ['some error description'],
25
25
  another_error: ['another error description']
26
26
  }
27
- end
28
27
 
29
- before do
30
28
  errors.add_multiple_errors errors_list
31
- end
32
29
 
33
- it 'populates itself with the added errors' do
34
30
  expect(errors[:some_error]).to eq(errors_list[:some_error])
35
31
  expect(errors[:another_error]).to eq(errors_list[:another_error])
36
32
  end
33
+
34
+ it 'copies errors from another SimpleCommand::Errors object' do
35
+ command_errors = SimpleCommand::Errors.new
36
+ command_errors.add :some_error, "was found"
37
+ command_errors.add :some_error, "happened again"
38
+
39
+ errors.add_multiple_errors command_errors
40
+
41
+ expect(errors[:some_error]).to eq(["was found", "happened again"])
42
+ end
43
+
44
+ it "ignores nil values" do
45
+ errors.add_multiple_errors({:foo => nil})
46
+
47
+ expect(errors[:foo]).to eq nil
48
+ end
37
49
  end
50
+
51
+ describe '#each' do
52
+ let(:errors_list) do
53
+ {
54
+ email: ['taken'],
55
+ password: ['blank', 'too short']
56
+ }
57
+ end
58
+
59
+ before { errors.add_multiple_errors(errors_list) }
60
+
61
+ it 'yields each message for the same key independently' do
62
+ expect { |b| errors.each(&b) }.to yield_control.exactly(3).times
63
+ expect { |b| errors.each(&b) }.to yield_successive_args(
64
+ [:email, 'taken'],
65
+ [:password, 'blank'],
66
+ [:password, 'too short']
67
+ )
68
+ end
69
+ end
70
+
71
+ describe '#full_messages' do
72
+ before do
73
+ errors.add :attr1, 'has an error'
74
+ errors.add :attr2, 'has an error'
75
+ errors.add :attr2, 'has two errors'
76
+ end
77
+
78
+ it "returrns the full messages array" do
79
+ expect(errors.full_messages).to eq ["Attr1 has an error", "Attr2 has an error", "Attr2 has two errors"]
80
+ end
81
+
82
+ end
83
+
38
84
  end
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.9
4
+ version: 1.0.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-23 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
@@ -59,6 +59,7 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - ".github/workflows/ci.yml"
62
63
  - ".gitignore"
63
64
  - ".rspec"
64
65
  - ".rubocop.yml"
@@ -69,6 +70,7 @@ files:
69
70
  - Rakefile
70
71
  - lib/simple_command.rb
71
72
  - lib/simple_command/errors.rb
73
+ - lib/simple_command/utils.rb
72
74
  - lib/simple_command/version.rb
73
75
  - simple_command.gemspec
74
76
  - spec/factories/missed_call_command.rb
@@ -80,7 +82,7 @@ homepage: http://github.com/nebulab/simple_command
80
82
  licenses:
81
83
  - MIT
82
84
  metadata: {}
83
- post_install_message:
85
+ post_install_message:
84
86
  rdoc_options: []
85
87
  require_paths:
86
88
  - lib
@@ -95,9 +97,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
97
  - !ruby/object:Gem::Version
96
98
  version: '0'
97
99
  requirements: []
98
- rubyforge_project:
99
- rubygems_version: 2.4.5
100
- signing_key:
100
+ rubygems_version: 3.2.20
101
+ signing_key:
101
102
  specification_version: 4
102
103
  summary: Easy way to build and manage commands (service objects)
103
104
  test_files: