ruby-try 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.
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper
4
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ruby-try.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'rspec', '~> 3.0.0'
8
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Orel Sokolov, RoR team
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,103 @@
1
+ Ruby Try
2
+ ========
3
+ This gem has two versions of `try()`.
4
+
5
+ * **Vanilla `try()`**
6
+ * This is RoR vanilla `try()` and `try!()`. Nothing new.
7
+ * **Boolean `try?()`**
8
+ * This is `try()` for boolean functions. It is returns `false` instead of `nil`, when trying to call
9
+ something like `nil.try(:some_boolean_method?)`
10
+
11
+ ```ruby
12
+ irb(main):001:0> require 'ruby-try'
13
+ => true
14
+ irb(main):002:0> nil.try(:admin?)
15
+ => nil
16
+ irb(main):003:0> nil.try?(:admin?)
17
+ => false
18
+ ```
19
+
20
+ Why boolean `try?`
21
+ =================
22
+
23
+ Imagine, we have something like this:
24
+ ```ruby
25
+ def admin_in_team?(team)
26
+ if m = team_members.find_by_team_id(team.id)
27
+ m.admin?
28
+ else
29
+ false
30
+ end
31
+ end
32
+ ```
33
+
34
+ Of course, it is better to write something like
35
+ ```
36
+ def admin_in_team?(team)
37
+ team_members.find_by_team_id(team.id).try(:admin?)
38
+ end
39
+ ```
40
+
41
+ But there is a TRAP! If `find_by_team_id(team.id)` returns `nil`,
42
+ `nil.try(:anything)` returns `nil`. Is it a reason for writing this HUGE `if`?
43
+ I don't think so.
44
+
45
+ First idea is to patch `try()`. But it is not best idea. Many developers expects
46
+ vanilla behavior from `try()`, so that's why a new `try?()` method appears. It is looks not
47
+ elegant, but one line is better than 5 with misty logic.
48
+
49
+
50
+ ## Installation
51
+
52
+ Add this line to your application's Gemfile:
53
+
54
+ ```ruby
55
+ gem 'ruby-try'
56
+ ```
57
+
58
+ And then execute:
59
+
60
+ $ bundle
61
+
62
+ Or install it yourself as:
63
+
64
+ $ gem install ruby-try
65
+
66
+ ## Documentation
67
+ Please, use specs to explore behavior of this gem. Or refer to RoR documentation.
68
+
69
+ ```
70
+ git clone https://github.com/OrelSokolov/ruby-try
71
+ cd ruby-try
72
+ bundle
73
+ rspec spec/
74
+ ```
75
+
76
+ ## Contributing
77
+
78
+ 1. Fork it ( https://github.com/OrelSokolov/ruby-try/fork )
79
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
80
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
81
+ 4. Push to the branch (`git push origin my-new-feature`)
82
+ 5. Create a new Pull Request
83
+
84
+
85
+ AUTHORS
86
+ ========
87
+
88
+ * [Oleg Orlov](https://github.com/OrelSokolov)
89
+ * [RoR team](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/try.rb)
90
+
91
+
92
+ LICENSE
93
+ =======
94
+
95
+ This gem is released under the MIT License.
96
+
97
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
98
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
99
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
100
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
101
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
102
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
103
+ THE SOFTWARE.
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,64 @@
1
+ class Object
2
+ def try(*a, &b)
3
+ if a.empty? && block_given?
4
+ yield self
5
+ else
6
+ public_send(*a, &b) if respond_to?(a.first)
7
+ end
8
+ end
9
+
10
+ # Same as #try, but will raise a NoMethodError exception if the receiving is not nil and
11
+ # does not implement the tried method.
12
+ def try!(*a, &b)
13
+ if a.empty? && block_given?
14
+ yield self
15
+ else
16
+ public_send(*a, &b)
17
+ end
18
+ end
19
+
20
+ def try?(*a, &b)
21
+ if a.empty? && block_given?
22
+ yield self
23
+ else
24
+ if respond_to?(a.first)
25
+ public_send(*a, &b)
26
+ else
27
+ nil.try?(*a, &b)
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ class NilClass
35
+ # Calling +try+ on +nil+ returns +nil+
36
+ # It becomes specially helpful when navigating through associations that may return +nil+.
37
+ #
38
+ # nil.try(:name) # => nil
39
+ #
40
+ # Without +try+
41
+ # @person && !@person.children.blank? && @person.children.first.name
42
+ #
43
+ # With +try+
44
+ # @person.try(:children).try(:first).try(:name)
45
+ #
46
+ def try(*args)
47
+ nil
48
+ end
49
+
50
+ # Calling +try?+ on +nil+ returns +false+
51
+ # With +try?+
52
+ # @person.try(:children).try(:first).try?(:has_dark_hairs?)
53
+ def try?(*args)
54
+ if args.first =~ /[?]$/
55
+ false
56
+ else
57
+ raise ArgumentError, "For non-boolean methods use only try()"
58
+ end
59
+ end
60
+
61
+ def try!(*args)
62
+ nil
63
+ end
64
+ end
@@ -0,0 +1,7 @@
1
+ require "ruby/try/version"
2
+
3
+ module Ruby
4
+ module Try
5
+ # Your code goes here...
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Ruby
2
+ module Try
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'ruby-try'
7
+ spec.version = '1.0.0'
8
+ spec.date = '2014-08-01'
9
+ spec.summary = "Provides RoR try() and extends it by new try?() method."
10
+ spec.description = <<-DESC
11
+ This gem has two versions of `try()`.
12
+
13
+ Vanilla `try()`
14
+ This is RoR vanilla `try()` and `try!()` methods. Nothing new.
15
+ Boolean `try?()`
16
+ It is returns `false` instead of `nil`, when trying to call something like
17
+ `nil.try?(:some_boolean_method?)`
18
+ DESC
19
+ spec.authors = ["Oleg Orlov"]
20
+ spec.email = 'orelcokolov@gmail.com'
21
+ spec.homepage = 'http://rubygems.org/gems/ruby-try'
22
+ spec.license = 'MIT'
23
+
24
+ spec.files = `git ls-files -z`.split("\x0")
25
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
26
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.6"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ end
@@ -0,0 +1,196 @@
1
+ require 'spec_helper'
2
+ require 'ruby-try'
3
+
4
+ #########################################################################3
5
+
6
+ shared_context "#try, method not exists" do
7
+ it "should return nil for general method" do
8
+ subject.try(:non_existing_method).should eq(nil)
9
+ end
10
+
11
+ it "should return nil for boolean method" do
12
+ subject.try(:non_existing_method?).should eq(nil)
13
+ end
14
+ end
15
+
16
+ #########################################################################3
17
+
18
+ shared_context "#try?, method exists" do
19
+ it "should raise an exception for general method" do
20
+ expect {subject.try?(:zero) }.to raise_error(ArgumentError)
21
+ end
22
+
23
+ end
24
+
25
+ shared_context "#try?, method not exists" do
26
+ it "should raise an exception for general method" do
27
+ expect {subject.try?(:non_existing_method) }.to raise_error(ArgumentError)
28
+ end
29
+
30
+ it "should return false for boolean method" do
31
+ subject.try?(:non_existing_method?).should eq(false)
32
+ end
33
+ end
34
+
35
+
36
+ #########################################################################3
37
+
38
+ shared_context "object with try" do
39
+ before do
40
+ allow_message_expectations_on_nil
41
+ subject.stub(:get_zero).and_return(0)
42
+ subject.stub(:zero?).and_return(true)
43
+ end
44
+
45
+ it { should respond_to(:try) }
46
+ it { should respond_to(:try?) }
47
+ it { should respond_to(:try!) }
48
+
49
+ it { should_not respond_to(:non_existing_method) }
50
+ it { should_not respond_to(:non_existing_method?) }
51
+
52
+ end
53
+
54
+ describe Object do
55
+ include_context 'object with try'
56
+
57
+
58
+ ###############################################################################
59
+
60
+ describe "#try" do
61
+ context "for existing method" do
62
+ include_context "#try, method exists"
63
+
64
+ it "should return value for general method" do
65
+ subject.try(:get_zero).should eq(0)
66
+ end
67
+
68
+ it "should return value for boolean method" do
69
+ subject.try(:zero?).should eq(true)
70
+ end
71
+ end
72
+
73
+ context "for non-existing method" do
74
+ include_context "#try, method not exists"
75
+
76
+ end
77
+
78
+ end
79
+
80
+ ###############################################################################
81
+
82
+ describe "#try?" do
83
+ context "for existing method" do
84
+ include_context "#try?, method exists"
85
+
86
+ it "should return value for boolean method" do
87
+ subject.try?(:zero?).should eq(true)
88
+ end
89
+ end
90
+
91
+ context "for non-existing method" do
92
+ include_context "#try?, method not exists"
93
+
94
+ end
95
+ end
96
+
97
+ ###############################################################################
98
+
99
+ describe "#try!" do
100
+ context "for existing method" do
101
+ it "should return value for general method" do
102
+ subject.try!(:get_zero).should eq(0)
103
+ end
104
+
105
+ it "should return value for boolean method" do
106
+ subject.try!(:zero?).should eq(true)
107
+ end
108
+ end
109
+
110
+ context "for non-existing method" do
111
+ it "should raise an exception for general method" do
112
+ expect {subject.try!(:non_existing_method) }.to raise_error(NoMethodError)
113
+ end
114
+
115
+ it "should raise an exception for boolean method" do
116
+ expect {subject.try!(:non_existing_method?) }.to raise_error(NoMethodError)
117
+ end
118
+ end
119
+ end
120
+
121
+ end
122
+
123
+ describe NilClass do
124
+ subject { nil }
125
+ include_context 'object with try'
126
+
127
+ ###############################################################################
128
+
129
+ describe "#try" do
130
+ context "for existing method" do
131
+ it "should return nil for general method" do
132
+ subject.try(:get_zero).should eq(nil)
133
+ end
134
+
135
+ it "should return nil for boolean method" do
136
+ subject.try(:zero?).should eq(nil)
137
+ end
138
+ end
139
+
140
+ context "for non-existing method" do
141
+ it "should return nil for general method" do
142
+ subject.try(:get_zero).should eq(nil)
143
+ end
144
+
145
+ it "should return nil for boolean method" do
146
+ subject.try(:zero?).should eq(nil)
147
+ end
148
+ end
149
+
150
+
151
+ end
152
+
153
+ ###############################################################################
154
+
155
+ describe "#try?" do
156
+ context "for existing method" do
157
+ include_context "#try?, method exists"
158
+
159
+ it "should return false for boolean method" do
160
+ subject.try?(:zero?).should eq(false)
161
+ end
162
+ end
163
+
164
+ context "for non-existing method" do
165
+ include_context "#try?, method not exists"
166
+ end
167
+ end
168
+
169
+ ###############################################################################
170
+
171
+ describe "#try!" do
172
+ context "for existing method" do
173
+
174
+ it "should return nil for boolean method" do
175
+ subject.try!(:zero?).should eq(nil)
176
+ end
177
+
178
+ it "should return nil for general method" do
179
+ subject.try!(:get_zero).should eq(nil)
180
+ end
181
+ end
182
+
183
+ context "for non-existing method" do
184
+
185
+ it "should return nil for general method" do
186
+ subject.try!(:non_existing_method).should eq(nil)
187
+ end
188
+
189
+ it "should return nil for boolean method" do
190
+ subject.try!(:non_existing_method?).should eq(nil)
191
+ end
192
+ end
193
+
194
+ end
195
+
196
+ end
@@ -0,0 +1,12 @@
1
+ RSpec.configure do |config|
2
+ config.mock_with :rspec do |c|
3
+ c.syntax = [:should, :expect] # Disable warnings
4
+ end
5
+ end
6
+
7
+
8
+ RSpec.configure do |config|
9
+ config.expect_with :rspec do |c|
10
+ c.syntax = [:should, :expect] # Disable warnings
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-try
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Oleg Orlov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-08-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.6'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.6'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '10.0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '10.0'
46
+ description: ! " This gem has two versions of `try()`. \n\n Vanilla `try()`\n
47
+ \ This is RoR vanilla `try()` and `try!()` methods. Nothing new.\n Boolean
48
+ `try?()`\n It is returns `false` instead of `nil`, when trying to call something
49
+ like \n `nil.try?(:some_boolean_method?)`\n"
50
+ email: orelcokolov@gmail.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - .gitignore
56
+ - .rspec
57
+ - Gemfile
58
+ - LICENSE.txt
59
+ - README.md
60
+ - Rakefile
61
+ - lib/ruby-try.rb
62
+ - lib/ruby/try.rb
63
+ - lib/ruby/try/version.rb
64
+ - ruby-try.gemspec
65
+ - spec/ruby_try_spec.rb
66
+ - spec/spec_helper.rb
67
+ homepage: http://rubygems.org/gems/ruby-try
68
+ licenses:
69
+ - MIT
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 1.8.23
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Provides RoR try() and extends it by new try?() method.
92
+ test_files:
93
+ - spec/ruby_try_spec.rb
94
+ - spec/spec_helper.rb