operation 0.0.1
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 +7 -0
- data/README.md +83 -0
- data/lib/operation.rb +36 -0
- data/lib/operation/version.rb +9 -0
- data/lib/operations.rb +11 -0
- data/spec/lib/operation_spec.rb +65 -0
- data/spec/spec_helper.rb +0 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4f94e9016bc8af451f55389d78d58f6123311d99
|
4
|
+
data.tar.gz: 18ff89827a6e314e669982c0b20e1420bbf8ef01
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4f4363d6801908c589fb62eefa8864620981026e175e52155a7abdc3b1c54e4932d36b6bf6050ea48c56368df12065c0be41926d63271b623512ae21978bc43c
|
7
|
+
data.tar.gz: dc133b43f1452a22d36d8e645f87837a69b33224bf5901a66370fdb5f72a559b03a60d7f2a5ecd42c113b88329819bee542bfe64f1d90030669409d3d3ba8b2f
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
## Operation
|
2
|
+
|
3
|
+
Imagine you have a class like this:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
class User
|
7
|
+
def delete(id)
|
8
|
+
@users.delete id
|
9
|
+
end
|
10
|
+
end
|
11
|
+
```
|
12
|
+
|
13
|
+
What does it return? True? The User? an ID? What if an error occured? How does anyone calling `User.delete 42` know what happened?
|
14
|
+
|
15
|
+
This is where `Operation` comes in. You would just **always** return an Operation. That Object holds information about what happened, like so:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
class User
|
19
|
+
def delete(id)
|
20
|
+
return Operation.new(code: :id_missing) unless id
|
21
|
+
return Operation.new(code: :invalid_id, id: id) unless id.match /[a-f]{8}/
|
22
|
+
|
23
|
+
user = @users[id]
|
24
|
+
if @users.delete id
|
25
|
+
Operation.new success:true, code: :user_deleted, user: user
|
26
|
+
else
|
27
|
+
Operation.new code: :deletion_failed
|
28
|
+
end
|
29
|
+
rescue ConnectionError
|
30
|
+
Operation.new code: :deletion_failed_badly
|
31
|
+
end
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
This will give you this joyful, consistent, conventional, implementation-unaware programming feeling:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
operation = User.delete 42
|
39
|
+
if operation.success?
|
40
|
+
puts "It worked! You deleted the user #{operation.meta.user.first_name}"
|
41
|
+
else
|
42
|
+
puts "Oh, could not delete User with ID #{operation.object} because #{operation.code}"
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
For your convenience you can use `Operations#failure` and `Operations.success`:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
class User
|
50
|
+
def delete(id)
|
51
|
+
return Operations.failure(:id_missing) unless id
|
52
|
+
return Operations.failure(:invalid_id, id: id) unless id.match /[a-f]{8}/
|
53
|
+
|
54
|
+
user = @users[id]
|
55
|
+
if @users.delete id
|
56
|
+
Operations.success :user_deleted, object: user
|
57
|
+
else
|
58
|
+
Operations.failure :deletion_failed
|
59
|
+
end
|
60
|
+
rescue ConnectionError
|
61
|
+
Operation.failure :deletion_failed_badly
|
62
|
+
end
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
`#object` is just a shortcut to `#meta.object`:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
operation = User.delete 42
|
70
|
+
operation.success? # => true
|
71
|
+
operation.object # => <#User id=42>
|
72
|
+
operation.meta # => <#Hashie::Mash object: <#User id=42>>
|
73
|
+
operation.metadata # => { object: <#User id=42> }
|
74
|
+
operation.failure? # => false
|
75
|
+
```
|
76
|
+
|
77
|
+
### Requirements
|
78
|
+
|
79
|
+
* Ruby >= 1.9
|
80
|
+
|
81
|
+
### Copyright
|
82
|
+
|
83
|
+
MIT 2014 halo. See [MIT-LICENSE](http://github.com/halo/operation/blob/master/MIT-LICENSE).
|
data/lib/operation.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'hashie/mash'
|
2
|
+
require 'operations' # <- Not that we need them here, but the developer using this gem might want them.
|
3
|
+
|
4
|
+
class Operation
|
5
|
+
|
6
|
+
attr_reader :metadata, :code
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@success = [true, 'true', 1, '1'].include? options[:success]
|
10
|
+
@code = options[:code].to_s.to_sym unless options[:code].to_s == ''
|
11
|
+
@metadata = options[:metadata]
|
12
|
+
end
|
13
|
+
|
14
|
+
def success?
|
15
|
+
!!@success
|
16
|
+
end
|
17
|
+
|
18
|
+
def failure?
|
19
|
+
!success?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Convenience Wrapper
|
23
|
+
def object
|
24
|
+
meta.object
|
25
|
+
end
|
26
|
+
|
27
|
+
def meta
|
28
|
+
if metadata.respond_to? :each_pair
|
29
|
+
Hashie::Mash.new metadata
|
30
|
+
elsif metadata
|
31
|
+
metadata
|
32
|
+
else
|
33
|
+
Hashie::Mash.new
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/operations.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module Operations
|
2
|
+
|
3
|
+
def self.success(code = :success, metadata = {})
|
4
|
+
Operation.new success: true, code: code, metadata: metadata
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.failure(code, metadata = {})
|
8
|
+
Operation.new success: false, code: code, metadata: metadata
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'operation'
|
3
|
+
|
4
|
+
describe Operation do
|
5
|
+
|
6
|
+
describe '#success' do
|
7
|
+
it 'handles different types of success' do
|
8
|
+
expect( Operation.new(success: true) ).to be_success
|
9
|
+
expect( Operation.new(success: 'true') ).to be_success
|
10
|
+
expect( Operation.new(success: 1) ).to be_success
|
11
|
+
expect( Operation.new(success: '1') ).to be_success
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#failure' do
|
16
|
+
it 'handles different types of failure' do
|
17
|
+
expect( Operation.new(success: false) ).to be_failure
|
18
|
+
expect( Operation.new(success: 'false') ).to be_failure
|
19
|
+
expect( Operation.new(success: 0) ).to be_failure
|
20
|
+
expect( Operation.new(success: '0') ).to be_failure
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#code' do
|
25
|
+
it 'is a Symbol if possible' do
|
26
|
+
expect( Operation.new(code: :normal).code ).to eq :normal
|
27
|
+
expect( Operation.new(code: 'normal').code ).to eq :normal
|
28
|
+
expect( Operation.new(code: 'it worked').code ).to eq :'it worked'
|
29
|
+
expect( Operation.new(code: 0).code ).to eq :'0'
|
30
|
+
expect( Operation.new(code: "\n").code ).to eq :"\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'may be nil' do
|
34
|
+
expect( Operation.new.code ).to be_nil
|
35
|
+
expect( Operation.new(code: nil).code ).to be_nil
|
36
|
+
expect( Operation.new(code: '').code ).to be_nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#metadata' do
|
41
|
+
it 'is whatever was passed in' do
|
42
|
+
expect( Operation.new(metadata: nil).metadata ).to be_nil
|
43
|
+
expect( Operation.new(metadata: []).metadata ).to eq []
|
44
|
+
expect( Operation.new(metadata: { one: :two }).metadata ).to eq one: :two
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#meta' do
|
49
|
+
it 'is a Mash for nil' do
|
50
|
+
expect( Operation.new.meta ).to be_instance_of Hashie::Mash
|
51
|
+
expect( Operation.new(metadata: nil).meta ).to be_instance_of Hashie::Mash
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'is the Mash of what was passed in' do
|
55
|
+
expect( Operation.new(metadata: {}).meta ).to be_instance_of Hashie::Mash
|
56
|
+
expect( Operation.new(metadata: { one: { two: :three } }).meta.one.two ).to eq :three
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'is the metadata if no Mash possible' do
|
60
|
+
expect( Operation.new(metadata: []).meta ).to eq []
|
61
|
+
expect( Operation.new(metadata: 'wow').meta ).to eq 'wow'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/spec/spec_helper.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: operation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- halo
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hashie
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: guard-rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rb-fsevent
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: See https://github.com/halo/operation
|
70
|
+
email:
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- README.md
|
76
|
+
- lib/operation.rb
|
77
|
+
- lib/operation/version.rb
|
78
|
+
- lib/operations.rb
|
79
|
+
- spec/lib/operation_spec.rb
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
homepage: https://github.com/halo/operation
|
82
|
+
licenses:
|
83
|
+
- MIT-LICENSE
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 2.2.2
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Implementation-agnostic method return status objects
|
105
|
+
test_files: []
|