guaranteed 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 68c2106aec66d9a30837abfe4d5e5525efe47aae
4
+ data.tar.gz: cc3cb198596eab977a55d2e5d92c40395bcdf89f
5
+ SHA512:
6
+ metadata.gz: dc419d2fc820c2fab345bf281ba53c639677a78cdbfbf2be28c03a53a909086bcbbeb9a3c9e04a8c11c94ccddaa8e8373a35a13a87dff1c903c57784dceee805
7
+ data.tar.gz: 2ceb544b8822d02421245e388dade94a0d7a1e95908573f01df6b1378dd10008c8dce5a1ad6df941a6c2c23d682dc24f383e168acd01568a4105a5755ee9fe7f
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Giannis Katsanos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,115 @@
1
+ # guaranteed
2
+
3
+ > Give me something for nothing!
4
+
5
+ ## What is this?
6
+
7
+ Guaranteed is a tiny library that ensures you always have an object to act upon. By eliminating continual checks for your objects' capabilities you can focus on your code's functionality.
8
+
9
+ Guaranteed's primary goal is to __eliminate nil checks__.
10
+
11
+ ## Hmmm... I'm not sure I need this
12
+
13
+ Hey, I'm with you here, you probably don't. Consider this a "nice to have" library. But the truth is that using the library can lead to much cleaner designs. Plus, it's almost zero overhead for your project. All you need is Ruby.
14
+
15
+ Here's the basic usage. Let's fire up `irb` and illustrate a frequent problem we face when coding.
16
+
17
+ ```ruby
18
+ # The most explicit approach
19
+ # Too verbose!
20
+ def username
21
+ user.nil? ? nil : user.name
22
+ end
23
+
24
+ # An improvement (arguably)
25
+ # What if the name attribute should return a boolean?
26
+ def username
27
+ user && user.name
28
+ end
29
+
30
+ # Rails developers think this is a neat trick :(
31
+ def username
32
+ user.try(:name)
33
+ end
34
+
35
+ # Guaranteed to the rescue!
36
+ def username
37
+ Guaranteed.Object(user).name
38
+ end
39
+ ```
40
+
41
+ ## I'm still not convinced
42
+
43
+ The above example is just scratching the surface of Guaranteed's abilities. Let's take a look at some more interesting examples.
44
+
45
+ Most common Ruby methods on objects are supported. They follow Ruby's implicit type conversions for an instance of [NilClass](https://ruby-doc.org/core-2.3.0/NilClass.html).
46
+
47
+ ```ruby
48
+ object = Guaranteed.Object(nil)
49
+
50
+ object.nil? # => true
51
+ !object # => true
52
+ object.to_a # => []
53
+ object.to_h # => {}
54
+ object.to_s # => ''
55
+ object.to_f # => 0.0
56
+ object.to_i # => 0
57
+ object.empty? # => true
58
+ ```
59
+
60
+ Need method chaining? You're covered.
61
+
62
+ ```ruby
63
+ object = Guaranteed.Object(nil)
64
+
65
+ object.this.will.definitely.not.work!
66
+ # => Returns self
67
+ ```
68
+
69
+ Agreed, this amount of method chaining breaks the [Law of Demeter](https://en.wikipedia.org/wiki/Law_of_Demeter). Sometimes reality hits you hard in the face though. Let's try the above example using [ActiveSupport::Object](http://api.rubyonrails.org/classes/Object.html).
70
+
71
+ ```ruby
72
+ # Ugh..
73
+ object.try(:this).try(:will).try(:definitely).try(:not).try(:work!)
74
+ # => nil
75
+ ```
76
+
77
+ Bonus Ruby idiom that's supported.
78
+
79
+ ```ruby
80
+ object = Guaranteed.Object(nil)
81
+
82
+ object.tap do |o|
83
+ o.name = 'Homer Simpson'
84
+ o.save!
85
+ end
86
+ # => Returns self
87
+ ```
88
+
89
+ Using Rails? I've got good news for you! The library supports some Rails-specific methods too.
90
+
91
+ ```ruby
92
+ object = Guaranteed.Object(nil)
93
+
94
+ object.present? # => false
95
+ object.as_json # => nil
96
+ object.to_json # => "null"
97
+ object.persisted? # => false
98
+ ```
99
+
100
+ ## OK, I'm sold. How do I install it?
101
+
102
+ ```
103
+ $ gem install guaranteed
104
+ # or add it to your Gemfile
105
+ ```
106
+
107
+ ## Can I contribute?
108
+
109
+ Yes, please. Feel free to fork the project and create your own branches. Consider creating a pull request back to this repo.
110
+
111
+ Remember, you can run the tests with
112
+
113
+ ```
114
+ $ rake
115
+ ```
@@ -0,0 +1,9 @@
1
+ require "rake/testtask"
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc 'Runs the tests'
8
+ task default: :test
9
+
@@ -0,0 +1,16 @@
1
+ require 'guaranteed/null_object'
2
+
3
+ module Guaranteed
4
+ # Ensures there is an object we can confidently pass messages to.
5
+ #
6
+ # @param value an object, instance of any class
7
+ # @return the same object or a NullObject for instances of NilClass.
8
+ def self.Object(value = nil)
9
+ case value
10
+ when nil
11
+ NullObject.new
12
+ else
13
+ value
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,63 @@
1
+ require 'forwardable'
2
+
3
+ module Guaranteed
4
+ # An implementation the Null Object pattern.
5
+ #
6
+ # Overrides some common Ruby and Rails methods to avoid continual
7
+ # type-checking. Delegates most of them to an intance of NilClass.
8
+ class NullObject
9
+ extend Forwardable
10
+
11
+ def_delegators :value, :nil?, :to_a, :to_s, :to_f, :to_i, :to_h
12
+
13
+ def persisted?
14
+ false
15
+ end
16
+
17
+ def present?
18
+ false
19
+ end
20
+
21
+ def empty?
22
+ true
23
+ end
24
+
25
+ def blank?
26
+ true
27
+ end
28
+
29
+ def tap
30
+ self
31
+ end
32
+
33
+ def !
34
+ true
35
+ end
36
+
37
+ def as_json(options = nil)
38
+ nil
39
+ end
40
+
41
+ def to_json
42
+ "null"
43
+ end
44
+
45
+ # Allows instances of the class to respond to any received message.
46
+ #
47
+ # Supports unlimited method chaining. Avoids NoMethodError in any
48
+ # part of the method chain.
49
+ def method_missing(method_name, *args, &block)
50
+ self
51
+ end
52
+
53
+ def respond_to_missing?(method_name, include_private = false)
54
+ true
55
+ end
56
+
57
+ private
58
+
59
+ def value
60
+ nil
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ module Guaranteed
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,25 @@
1
+ require 'minitest/autorun'
2
+ require 'guaranteed'
3
+
4
+ class TestGuaranteed < Minitest::Test
5
+ class Example
6
+ end
7
+
8
+ def test_object_returns_a_null_object_if_object_is_nil
9
+ object = Guaranteed.Object(nil)
10
+ assert_equal(Guaranteed::NullObject, object.class)
11
+ assert_equal(true, object.nil?)
12
+ end
13
+
14
+ def test_object_returns_the_object_if_object_is_not_nil
15
+ assert_equal('the-object', Guaranteed.Object('the-object'))
16
+ object = Example.new
17
+ assert_equal(object, Guaranteed.Object(object))
18
+ end
19
+
20
+ def test_object_can_chain_methods
21
+ res = Guaranteed.Object(nil).this.is.definitely.missing
22
+ assert_equal(true, res.nil?)
23
+ assert_equal(Guaranteed::NullObject, res.class)
24
+ end
25
+ end
@@ -0,0 +1,57 @@
1
+ require 'minitest/autorun'
2
+ require 'guaranteed/null_object'
3
+
4
+ class TestNullObject < Minitest::Test
5
+ def test_to_a_returns_an_empty_array
6
+ assert_equal([], Guaranteed::NullObject.new.to_a)
7
+ end
8
+
9
+ def test_to_s_returns_an_empty_string
10
+ assert_equal('', Guaranteed::NullObject.new.to_s)
11
+ end
12
+
13
+ def test_to_h_returns_an_empty_hash
14
+ assert_equal({}, Guaranteed::NullObject.new.to_h)
15
+ end
16
+
17
+ def test_to_i_returns_zero
18
+ assert_equal(0, Guaranteed::NullObject.new.to_i)
19
+ end
20
+
21
+ def test_to_f_returns_zero_float
22
+ assert_equal(0.0, Guaranteed::NullObject.new.to_i)
23
+ end
24
+
25
+ def test_present_returns_false
26
+ assert_equal(false, Guaranteed::NullObject.new.present?)
27
+ end
28
+
29
+ def test_empty_returns_true
30
+ assert_equal(true, Guaranteed::NullObject.new.empty?)
31
+ end
32
+
33
+ def test_blank_returns_true
34
+ assert_equal(true, Guaranteed::NullObject.new.blank?)
35
+ end
36
+
37
+ def test_not_returns_true
38
+ assert_equal(true, !Guaranteed::NullObject.new)
39
+ end
40
+
41
+ def test_as_json_returns_nil
42
+ assert_nil(Guaranteed::NullObject.new.as_json)
43
+ end
44
+
45
+ def test_to_json_returns_null
46
+ assert_equal("null", Guaranteed::NullObject.new.to_json)
47
+ end
48
+
49
+ def test_tap_returns_self
50
+ object = Guaranteed::NullObject.new
51
+ assert_equal(true, object.tap { |o| o.foo = 'bar' }.nil?)
52
+ end
53
+
54
+ def test_persisted_returns_false
55
+ assert_equal(false, Guaranteed::NullObject.new.persisted?)
56
+ end
57
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guaranteed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Giannis Katsanos
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-10-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |2
14
+ Guaranteed is a tiny library that ensures you always have an object to act upon.
15
+ It eliminates checks for your object's capabilities.
16
+ email: giannis.katsanos@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - LICENSE
22
+ - README.md
23
+ - Rakefile
24
+ - lib/guaranteed.rb
25
+ - lib/guaranteed/null_object.rb
26
+ - lib/guaranteed/version.rb
27
+ - test/test_guaranteed.rb
28
+ - test/test_null_object.rb
29
+ homepage: https://github.com/gkats/guaranteed
30
+ licenses:
31
+ - MIT
32
+ metadata: {}
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.3.6
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 2.6.11
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: Make something out of nothing!
53
+ test_files:
54
+ - test/test_guaranteed.rb
55
+ - test/test_null_object.rb