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 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
@@ -0,0 +1,9 @@
1
+ class Operation
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].compact.join('.')
8
+ end
9
+ 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
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: []