operation 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|