reactive_support 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a142b1256893c0aa5c9a3f28b9eb22a4ea88ee04
4
+ data.tar.gz: 9a988e249e3c15236caeb44bd61549555532a0f7
5
+ SHA512:
6
+ metadata.gz: dc50c7a5966a2b58b7a338d9c4b045958cca11a71efe3059812125a67280f612e71359fc10f4d38a7ed7cc408d6ac7a94c6bf07c7bdced0e25b9a68643dc50c8
7
+ data.tar.gz: 6f0c09ccafbab6e586d3fd54db73587bf5806247507213ef5f53e8c1a150260efe1975354deb53a7786d198b1d40bf2a921d7bbee86edfad64d6b03cf369bc26
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,162 @@
1
+ ## Contributing to ReactiveSupport
2
+ ReactiveSupport is a small project with only one maintainer (nice to meet you),
3
+ so your contributions are much appreciated. Here are some guidelines to improve
4
+ the chances your pull request will be accepted.
5
+
6
+ #### Summary Guidelines
7
+ The more of these guidelines you read, the more likely it is your pull request
8
+ will be accepted. That said, here is the TL;DR version. (Details are available in
9
+ later sections.)
10
+
11
+ DO...
12
+ * Expand existing functionality
13
+ * Fix bugs
14
+ * Add or improve tests and documentation
15
+ * Feel free to add new files as needed(make sure to add them to the
16
+ gemspec too!)
17
+ * Keep everything consistent with the ActiveSupport API
18
+ * Include robust, passing RSpec examples with your PR
19
+ * Include extensive [RDoc](https://github.com/rdoc/rdoc) comments
20
+ * Keep your code DRY and concise - be mindful of best practices
21
+ * Familiarize yourself with the metrics used on this project
22
+ * Familiarize yourself with the vision and values of this project
23
+ * Run the full test suite before making your PR
24
+ * File an issue report or message me if you have any questions
25
+ (I don't bite!)
26
+
27
+ DON'T...
28
+ * Worry that your pull request is too small - all improvements are welcome
29
+ * Break backward compatibility
30
+ * Modify existing functionality (unless required to fix a bug)
31
+ * Add dependencies
32
+ * Add functionality that is not present in ActiveSupport
33
+ * Submit a PR with breaking changes or no passing tests
34
+ * Submit changes that only work with particular tools, gemsets,
35
+ environments, or Ruby versions
36
+
37
+ Thank you for your contributions!
38
+
39
+ #### Types of Contributions
40
+ I'll consider all contributions, but the following would be
41
+ particularly helpful.
42
+
43
+ ##### Bug fixes
44
+ If you find a bug affecting ReactiveSupport's interaction with other gems,
45
+ frameworks, tools, platforms, rubies, or environments, your issue report
46
+ or patch is much appreciated. If your fix has to do with Rails, you will
47
+ also need to explain why ReactiveSupport would be included in a Rails project
48
+ since I can't think of a reason.
49
+
50
+ ##### Additional ActiveSupport methods
51
+ Most of the ActiveRecord methods I'm including are those that I find directly
52
+ relevant to [my other project](https://github.com/danascheider/canto). I
53
+ encourage pull requests that add methods that would be useful to you or others.
54
+
55
+ ##### Additional or improved tests or docs
56
+ ReactiveSupport uses RSpec and RDoc for testing and documentation, respectively.
57
+ Improvements in coverage or quality of tests and documentation are very helpful.
58
+
59
+ #### Project Vision
60
+ Your pull request is more likely to be successful if you keep ReactiveSupport's
61
+ vision and values in mind. This gem is:
62
+
63
+ ##### Unopinionated, agnostic, and independent
64
+ ReactiveSupport is intended to provide additional, useful functionality to all
65
+ Ruby developers. Successful pull requests will work regardless of platform,
66
+ environment, tooling, or gemsets, and will do so without adding dependencies.
67
+
68
+ ##### Stable and compatible
69
+ ReactiveSupport exists so users can have access to ActiveSupport's useful methods
70
+ without relying on Rails, whose frequent changes and reorganizations can hurt
71
+ projects relying on its components. Changes you submit must not adversely affect
72
+ backwards compatibility or break existing functionality. **This is the single most
73
+ important rule for contributing to ReactiveSupport.**
74
+
75
+ ##### Functionally identical to ActiveSupport
76
+ A person should be able to learn about a ReactiveSupport method by reading the
77
+ ActiveSupport documentation on the corresponding method. Note that this rule
78
+ is subordinated to the previous one. Stability and compatibility come first, always.
79
+
80
+ ##### Test-driven and test-first
81
+ ReactiveSupport development is guided by the principles of behavior-driven
82
+ development. Look at existing spec files and notice how many examples are included
83
+ for each method. Test coverage is measured by [Coveralls](http://coveralls.io),
84
+ and 100% coverage by robust, detailed tests is the standard for this project.
85
+
86
+ ##### Well documented
87
+ [Inch CI](http://inch-ci.org) is being used to evaluate the thoroughness of
88
+ ReactiveSupport's [RDoc](https://github.com/rdoc/rdoc) documentation.
89
+ Please include detailed documentation with your pull request.
90
+
91
+ ##### Mindful of metrics
92
+ As a perfectionistic and slightly neurotic individual, I have configured the
93
+ following tools for evaluating different aspects of the ReactiveSupport gem.
94
+ Please familiarize yourself with them:
95
+ * **[Travis CI](https://travis-ci.org)** is used to ensure all tests pass.
96
+ Commits that break Travis builds make me a
97
+ [sad panda](http://www.urbandictionary.com/define.php?term=sad+panda).
98
+ * **[Coveralls](https://coveralls.io)** is used to evaluate extent of
99
+ test coverage. The goal is 100% coverage, which is an achievable goal.
100
+ * **[CodeClimate](http://codeclimate.com)** is used to evaluate code
101
+ quality. I consider a CodeClimate score below 3.5 unacceptably low for
102
+ this project. (You can easily check your fork before submitting.)
103
+ * **[Inch CI](http://inch-ci.org)** is used to evaluate documentation.
104
+ Don't worry too much about what Inch says (it's newish and buggy), but
105
+ *do* take the time to include quality docs.
106
+
107
+ #### Style Guide
108
+ Development of ReactiveSupport is guided by best practices. This is a simple
109
+ gem and it should be DRY, concise, and thoroughly documented.
110
+ Here are some of the best practices and stylistic guidelines I like my projects
111
+ to adhere to:
112
+ * `unless` is preferred to `if not`
113
+ * Single-line blocks use curly braces
114
+ * Multi-line blocks use `do`...`end` syntax
115
+ * Single quotes are preferred to double quotes when there's a choice
116
+ * Fewer lines good, more lines bad (see below for examples)
117
+ * More files are better than large files*
118
+ * RSpec `describe` and `context` blocks are good
119
+ * RSpec `let` syntax is good
120
+ * RSpec examples should have a single point of failure
121
+
122
+ And here are some smells to avoid (may be OK in some cases):
123
+ * One RSpec example has multiple points of failure
124
+ * A value is hard-coded
125
+ * A method is more than 3 lines long or contains nested conditionals or blocks
126
+
127
+ Note that monkey patching is NOT considered a smell in ReactiveSupport as long
128
+ as it solves a problem not solved within the ReactiveSupport module itself.
129
+
130
+ \* But don't forget to update the gemspec!
131
+
132
+ ##### Examples: Fewer lines good, more lines bad
133
+ Lots of things can be reduced to a single line, especially blocks and conditionals.
134
+
135
+ # This:
136
+ array.map do |num|
137
+ puts "#{num} is now #{num + 1}"
138
+ num += 1
139
+ end
140
+
141
+ # Should be turned into this:
142
+ array.map {|item| puts "#{item} is now #{item += 1}" }
143
+
144
+ # And this:
145
+ if foo.defined?
146
+ puts "It's defined!"
147
+ else
148
+ puts "It's not defined!"
149
+ end
150
+
151
+ # Should look more like this:
152
+ puts foo.defined? ? "It's defined!" : "It's not defined!"
153
+
154
+ # And finally, this:
155
+ begin
156
+ return message = foo.message
157
+ rescue
158
+ "It didn't work"
159
+ end
160
+
161
+ # Needs to be written like this:
162
+ return foo.message rescue "It didn't work!"
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Dana Scheider
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.
22
+
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ ## ReactiveSupport [![Build Status](https://travis-ci.org/danascheider/reactive_support.svg?branch=master)](https://travis-ci.org/danascheider/reactive_support) [![Coverage Status](https://img.shields.io/coveralls/danascheider/reactive_support.svg)](https://coveralls.io/r/danascheider/reactive_support) [![Code Climate](https://codeclimate.com/github/danascheider/reactive_support/badges/gpa.svg)](https://codeclimate.com/github/danascheider/reactive_support) [![Inline docs](http://inch-ci.org/github/danascheider/reactive_support.svg?branch=master)](http://inch-ci.org/github/danascheider/reactive_support)
2
+ The ReactiveSupport gem provides a re-implementation of certain [ActiveSupport](https://github.com/rails/activesupport)
3
+ methods, allowing them to be used outside of the Rails ecosystem. This gem can
4
+ be used in any kind of project and is not dependent on any frameworks, gemsets, etc.
5
+ To add ReactiveSupport to your project, add this to your Gemfile and run `bundle install`:
6
+ <pre><code>gem 'reactive_record', '~> 0.1.0', git: 'https://github.com/danascheider/reactive_record'</code></pre>
7
+ To install locally:
8
+ <pre><code>sudo gem install reactive_record</code></pre>
9
+ Or if you're using RVM:
10
+ <pre><code>gem install reactive_record</code></pre>
11
+ Then, in your main project file, include:
12
+ <pre><code>require 'reactive_support'</code></pre>
13
+
14
+ ### Usage
15
+ In its current version, ReactiveSupport adds methods to Ruby's `Object` class, so
16
+ once required, its methods can be used on any object within your project, including
17
+ core Ruby classes.
18
+
19
+ Currently, ReactiveSupport's methods are a strict subset of ActiveSupport's. (This may
20
+ change in future versions, or most saliently, if ActiveSupport's API changes.)
21
+ That means that, while not all ActiveSupport methods are available, those that are can,
22
+ as of September 2014, be found in ActiveSupport's API documentation with no functional
23
+ differences. (This is true of ReactiveSupport 0.1.0 and ActiveSupport 4.1.6.)
24
+
25
+ ### FAQ
26
+ ##### Why not just use ActiveSupport?
27
+ There are three main reasons why you might prefer ReactiveSupport over ActiveSupport:
28
+ 1. Stability: ReactiveSupport is intended to work independently of Rails' rapidly changing
29
+ ecosystem. ReactiveSupport methods are guaranteed not to be transferred to other
30
+ Rails modules or refactored out. While ActiveSupport may be used independently of
31
+ Rails, its developers are still primarily focused on its place within Rails.
32
+ ReactiveSupport solves that problem.
33
+ 2. Simplicity: ReactiveSupport can be added to other projects without additional abstraction
34
+ layers, and it has no dependencies outside the development and test groups. You
35
+ don't have to worry about configuration, compatibility with other gems*, or
36
+ conflicting dependencies.
37
+ 3. Transparency: Rails is an enormous gem, and gets larger and more complex with each major version.
38
+ It is also opinionated, facilitating some development approaches while making
39
+ others inordinately difficult. ReactiveSupport is not large or complicated. Any
40
+ developer can read the documentation, or even the code itself, and know exactly what
41
+ he or she is dealing with.
42
+
43
+ \* I would not recommend using it in conjunction with ActiveSupport, though.
44
+
45
+ ##### This doesn't have very many methods. What gives?
46
+ ReactiveSupport is a spinoff from my other project, [Canto](https://github.com/danascheider/canto).
47
+ Consequently, the methods it includes are primarily those that I have found a use for
48
+ in Canto. As Canto grows, and as I have time, I will add more of ActiveSupport's
49
+ numerous useful methods to ReactiveSupport. In the meantime, I welcome contributions
50
+ and will respond quickly to pull requests.
51
+
52
+ ##### Is ReactiveSupport being maintained?
53
+ Yes. Since stability is one of the main advantages of ReactiveSupport, I will be taking
54
+ an "if it ain't broke, don't fix it" approach to maintaining it. An absence of recent
55
+ contributions should not be taken to mean it has fallen off my radar.
56
+
57
+ ##### Can I use ReactiveSupport in a Sinatra project/Puppet module/system utility/etc.?
58
+ Yes. ReactiveSupport is agnostic to the characteristics of your app, and there is no
59
+ reason it cannot be used in any app where you feel it is needed.
60
+
61
+ ##### What versions of Ruby are supported?
62
+ ReactiveSupport version 0.1.0 supports Ruby versions >= 1.9.3. [Travis-CI](https://travis-ci.org/danascheider/reactive_support) is set up to run tests against the most recent version
63
+ of JRuby as well (currently 1.7.16), but tests are currently failing and frankly,
64
+ I don't know JRuby well enough to fix them. Additional Rubies
65
+ may be supported in the future. Adding such support would be a welcome contribution
66
+ to the project.
67
+
68
+ ### Contributing
69
+ Contributions are welcome and I will respond promptly to all issue reports and pull
70
+ requests. Here are some guidelines to get started; I also encourage you to read the
71
+ full CONTRIBUTING.md file to ensure your pull request will be accepted as is:
72
+ * Include passing RSpec tests with your pull request. I aim for 100% test coverage.
73
+ * Run the whole test suite before you make your PR. Make sure your changes don't
74
+ break the rest of the gem.
75
+ * Make sure your changes are consistent with the functionality of ActiveSupport.
76
+ Users should be able to learn about a ReactiveSupport method by reading the
77
+ ActiveSupport docs for the corresponding ActiveSupport method.
78
+ * Don't add any new dependencies to ReactiveSupport, or methods that are specific
79
+ to a particular framework, gemset, or type of app.
80
+ * Include documentation. ReactiveSupport uses [Inch CI](http://inch-ci.org) to
81
+ evaluate the quality of documentation. Please help make it easy for others to
82
+ use and contribute to this project.
83
+ * Keep ReactiveSupport principles - stability, simplicity, and transparency - in mind.
84
+ Ideally, contributions should uphold these principles while expanding or
85
+ enhancing functionality.
86
+
87
+ ### Resources
88
+ * The [Rails guides](http://guides.rubyonrails.org/active_support_core_extensions.html) on
89
+ ActiveRecord give information about each of ReactiveSupport's methods.
90
+ * Those interested in contributing to ReactiveSupport are encouraged read up on
91
+ [Travis CI](http://travis-ci.org), [Coveralls](http://coveralls.io),
92
+ [CodeClimate](http://codeclimate.com), and [Inch CI](http://inch-ci.org).
data/files.rb ADDED
@@ -0,0 +1,19 @@
1
+ module ReactiveSupport
2
+ def self.files
3
+ Files::FILES.flatten
4
+ end
5
+
6
+ module Files
7
+ LIB_FILES = Dir.glob('./lib/**/*.rb').sort
8
+ BASE_FILES = %w(CONTRIBUTING.md
9
+ files.rb
10
+ LICENSE
11
+ Gemfile
12
+ README.md
13
+ reactive_support.gemspec
14
+ version.rb)
15
+ SPEC_FILES = Dir.glob('./spec/**/*.rb').sort
16
+
17
+ FILES = [BASE_FILES, LIB_FILES, SPEC_FILES]
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ require 'reactive_support'
2
+
3
+ # The ReactiveAddOns module consists of methods I wish ActiveSupport provided.
4
+ # These methods do not adhere to the ActiveSupport API. If you wish to include
5
+ # them in your project, you will need to put this in your main project file:
6
+ # require 'reactive_support/extensions'
7
+ #
8
+ # ReactiveExtensions includes ReactiveSupport, so you will need to remove any
9
+ # requires for ReactiveSupport as it will raise a SystemStackError.
10
+
11
+ module ReactiveExtensions
12
+
13
+ # The +#try_rescue+ method extends ReactiveSupport's +#try+ method so it
14
+ # rescues NoMethodErrors and TypeErrors as well as returning +nil+ when
15
+ # called on a +nil+ value.
16
+ #
17
+ # Like the +#try+ method, +#try_rescue+ takes 1 or more arguments. The first
18
+ # argument is the method to be called on the calling object, passed as a
19
+ # symbol. The others are zero or more arguments that will be passed through to
20
+ # that method, and +&block+ is an optional block that will be similarly passed through.
21
+ #
22
+ # Example of usage identical to +#try+:
23
+ # nil.try(:map) {|a| a.to_s } # => nil
24
+ # nil.try_rescue(:map) {|a| a.to_s } # => nil
25
+ #
26
+ # Example of usage calling a method that is not defined on the calling object:
27
+ # 10.try(:to_h) # => TypeError
28
+ # 10.try_rescue(:to_h) # => nil
29
+ #
30
+ # Example of usage with invalid arguments:
31
+ # %w(foo, bar, baz).try(:join, [:hello, :world]) # => TypeError
32
+ # %w(foo, bar, baz).try_rescue(:join, [:hello, :world]) # => nil
33
+
34
+ def try_rescue(*args, &block)
35
+ self.try(*args, &block) rescue nil
36
+ end
37
+ end
38
+
39
+ class Object
40
+ include ReactiveExtensions
41
+ end
@@ -0,0 +1,34 @@
1
+ class Array
2
+
3
+ # The +#from+ method returns the tail of the array starting at the given
4
+ # +position+.
5
+ # [1, 2, 3, 4, 5].from(2) # => [3, 4, 5]
6
+ # [1, 2, 3, 4, 5].from(0) # => [1, 2, 3, 4, 5]
7
+ # [1, 2, 3, 4, 5].from(-2) # => [4, 5]
8
+ #
9
+ # +#from+ returns an empty array if the receiving array is empty, the given
10
+ # +position+ exceeds the maximum index of the array, or the given +position+
11
+ # is lower than the array's minimum (i.e., largest negative) index.
12
+ # [].from(0) # => []
13
+ # [1, 2, 3, 4, 5].from(10) # => []
14
+ # [1, 2, 3, 4, 5].from(-10) # => []
15
+
16
+ def from(position)
17
+ self[position, length] || []
18
+ end
19
+
20
+ # The +#to+ method returns the beginning of the array up to and including
21
+ # the given +position+.
22
+ # [1, 2, 3, 4, 5].to(2) # => [1, 2, 3]
23
+ # [1, 2, 3, 4, 5].to(10) # => [1, 2, 3, 4, 5]
24
+ # [1, 2, 3, 4, 5].to(-2) # => [1, 2, 3, 4]
25
+ #
26
+ # +#to+ returns an empty array if the receiving array is empty or the given
27
+ # +position+ falls below the minimum (negative) index.
28
+ # [].to(0) # => []
29
+ # [1, 2, 3, 4, 5].to(-10) # => []
30
+
31
+ def to(position)
32
+ self[0..position]
33
+ end
34
+ end
@@ -0,0 +1,189 @@
1
+ # This file adds the +#blank?+ and +#present?+ methods to core Ruby classes
2
+ # The +#blank?+ method returns +true+ if the object is undefined, blank, false,
3
+ # empty, or nil. The +#present?+ method returns the opposite of +#blank?+
4
+
5
+ # Ruby's core String class. See documentation for version
6
+ # 2.1.3[http://ruby-doc.org/core-2.1.3/String.html],
7
+ # 2.0.0[http://ruby-doc.org/core-2.1.3/String.html], or
8
+ # 1.9.3[http://ruby-doc.org/core-2.0.0/String.html].
9
+
10
+ class String
11
+
12
+ # When called on a string, the +#blank?+ method returns +true+ if the string
13
+ # is empty or consists only of whitespace:
14
+ # ''.blank? # => true
15
+ # " \n ".blank? # => true
16
+ # 'foo'.blank? # => false
17
+
18
+ def blank?
19
+ !!(/\A[[:space:]]*\z/ =~ self) || self.empty?
20
+ end
21
+
22
+ # When called on a string, the +#present?+ method returns +true+ unless the
23
+ # string is empty or consists only of whitespace:
24
+ # 'foo'.present? # => true
25
+ # ''.present? # => false
26
+ # ' '.present? # => false
27
+
28
+ def present?
29
+ !blank?
30
+ end
31
+ end
32
+
33
+ # Ruby's core Array class. See documentation for version
34
+ # 2.1.3[http://ruby-doc.org/core-2.1.3/FalseClass.html],
35
+ # 2.0.0[http://ruby-doc.org/core-2.0.0/FalseClass.html], or
36
+ # 1.9.3[http://ruby-doc.org/core-1.9.3/FalseClass.html].
37
+
38
+ class Array
39
+
40
+ # When called on an array, the +#blank?+ method is aliased to +#empty?+
41
+ # and returns +true+ when the array has no elements. Note that +#blank?+
42
+ # returns +false+ if the array has elements that are themselves all blank:
43
+ # [].blank? # => true
44
+ # ['foo', 'bar'].blank? # => false
45
+ # [false, nil, ''].blank? # => false
46
+
47
+ alias_method :blank?, :empty?
48
+
49
+ # When called on an array, the +#present?+ method returns +true+ if the
50
+ # array has any elements. Note that +#present?+ also returns +true+ if the
51
+ # array consists of blank values:
52
+ # ['foo', 'bar'].present? # => true
53
+ # [false, nil].present? # => true
54
+ # [].present? # => false
55
+
56
+ def present?
57
+ !blank?
58
+ end
59
+ end
60
+
61
+ # Ruby's core Hash class. See documentation for version
62
+ # 2.1.3[http://ruby-doc.org/core-2.1.3/Hash.html],
63
+ # 2.0.0[http://ruby-doc.org/core-2.0.0/Hash.html], or
64
+ # 1.9.3[http://ruby-doc.org/core-1.9.3/Hash.html].
65
+
66
+ class Hash
67
+
68
+ # When called on a hash (or any enumerable), the +#blank?+ method is aliased
69
+ # to +#empty?+ and as such returns +true+ if the hash is empty:
70
+ # {}.blank? # => true
71
+ # { foo: 'bar' }.blank? # => false
72
+ # { foo: nil }.blank? # => false
73
+
74
+ alias_method :blank?, :empty?
75
+
76
+ # When called on a hash (or any enumerable), the +#present?+ method returns
77
+ # +true+ if the hash is not empty, even if its elements have blank values:
78
+ # { foo: :bar }.present? # => true
79
+ # { 'bar' => nil }.present? # => true
80
+ # {}.present? # => false
81
+
82
+ def present?
83
+ !blank?
84
+ end
85
+ end
86
+
87
+ # Ruby's core NilClass (the singleton class consisting of the +nil+ object).
88
+ # See documentation for version 2.1.3[http://ruby-doc.org/core-2.1.3/NilClass.html],
89
+ # 2.0.0[http://ruby-doc.org/core-2.0.0/NilClass.html], or
90
+ # 1.9.3[http://ruby-doc.org/core-1.9.3/NilClass.html].
91
+
92
+ class NilClass
93
+
94
+ # +nil+ is considered blank by definition; if +#blank?+ is called on +nil+,
95
+ # it will always return +true+:
96
+ # nil.blank? # => true
97
+ #
98
+ # # When the +foo+ variable is undefined or set to nil:
99
+ # foo.blank? # => true
100
+
101
+ def blank?
102
+ true
103
+ end
104
+
105
+ # Likewise, +nil+ is not present by definition; if +#present?+ is called on
106
+ # +nil+, it will always return +false+:
107
+ # nil.present? # => false
108
+ #
109
+ # # When the +foo+ variable is undefined or set to nil:
110
+ # foo.present? # => false
111
+
112
+ def present?
113
+ false
114
+ end
115
+ end
116
+
117
+ # Ruby's core TrueClass (the singleton class consisting of the +true+ object).
118
+ # See documentation for version 2.1.3[http://ruby-doc.org/core-2.1.3/TrueClass.html],
119
+ # 2.0.0[http://ruby-doc.org/core-2.0.0/TrueClass.html], or
120
+ # 1.9.3[http://ruby-doc.org/core-1.9.3/TrueClass.html].
121
+
122
+ class TrueClass
123
+
124
+ # +true+ is not blank by definition; when called on +true+, the +#blank?+
125
+ # method will return +false+:
126
+ # true.blank? # => false
127
+
128
+ def blank?
129
+ false
130
+ end
131
+
132
+ # +true+ is present by definition; when called on +true+, the +#present?+
133
+ # method will return +true+:
134
+ # true.present? # => true
135
+
136
+ def present?
137
+ true
138
+ end
139
+ end
140
+
141
+ # Ruby's core FalseClass (the singleton class consisting of the +false+ object).
142
+ # See documentation for version 2.1.3[http://ruby-doc.org/core-2.1.3/FalseClass.html],
143
+ # 2.0.0[http://ruby-doc.org/core-2.0.0/FalseClass.html], or
144
+ # 1.9.3[http://ruby-doc.org/core-1.9.3/FalseClass.html].
145
+
146
+ class FalseClass
147
+
148
+ # +false+ is blank by definition; when called on +false+, the +#blank?+
149
+ # method will return +true+:
150
+ # false.blank? # => true
151
+
152
+ def blank?
153
+ true
154
+ end
155
+
156
+ # +false+ is not present by definition; when called on +false+, the +#present?+
157
+ # method will return +false+:
158
+ # false.present? # => false
159
+
160
+ def present?
161
+ false
162
+ end
163
+ end
164
+
165
+ # Ruby's core Numeric class, the parent class of Integer, Fixnum, Bignum, Float,
166
+ # and Rational. See documentation for version 2.1.3[http://ruby-doc.org/core-2.1.3/Numeric.html],
167
+ # 2.0.0[http://ruby-doc.org/core-2.0.0/Numeric.html], or
168
+ # 1.9.3[http://ruby-doc.org/core-1.9.3/Numeric.html].
169
+
170
+ class Numeric
171
+
172
+ # Numbers can never be blank; when called on any +Numeric+ (including +Fixnum+,
173
+ # +Bignum+, +Float+, +Integer+, and +Rational+), the +#blank?+ method will
174
+ # return +false+:
175
+ # 10.blank? # => false
176
+
177
+ def blank?
178
+ false
179
+ end
180
+
181
+ # Numbers are always present; when called on any +Numeric+ (including +Fixnum+,
182
+ # +Bignum+, +Float+, +Integer+, and +Rational+), the +#present?+ method will
183
+ # return +true+:
184
+ # Math.PI.present? # => true
185
+
186
+ def present?
187
+ true
188
+ end
189
+ end
@@ -0,0 +1,54 @@
1
+ class Object
2
+
3
+ # The +#deep_dup+ method returns a duplicate of a duplicable object. If the
4
+ # object calling +#deep_dup+ is not duplicable, the object itself is returned.
5
+ # +#deep_dup+ is overwritten in the Array and Hash classes (see +./object/deep_dup.rb+).
6
+ # In those classes, it duplicates the object recursively so the members of the
7
+ # enumerable can be manipulated without affecting the original object.
8
+
9
+ def deep_dup
10
+ duplicable? ? self.dup : self
11
+ end
12
+ end
13
+
14
+ class Array
15
+
16
+ # When called on an array, the +#deep_dup+ method duplicates all the members
17
+ # of the array recursively, so that actions on the duplicate do not affect
18
+ # the original:
19
+ #
20
+ # arr = [1, 2, [3, 4]] # => [1, 2, [3, 4]]
21
+ # dup, deep = arr.dup, arr.deep_dup # => [1, 2, [3, 4]], [1, 2, [3, 4]]
22
+ #
23
+ # deep[2][1] = 5 # => [1, 2, [3, 5]]
24
+ # p arr # => [1, 2, [3, 4]]
25
+ #
26
+ # dup[2][1] = 5 # => [1, 2, [3, 5]]
27
+ # p arr # => [1, 2, [3, 5]]
28
+
29
+ def deep_dup
30
+ self.map {|item| item.deep_dup }
31
+ end
32
+ end
33
+
34
+ class Hash
35
+
36
+ # When called on a hash, the +#deep_dup+ method duplicates all the key-value
37
+ # pairs in the hash recursively, so that actions on the duplicate do not affect
38
+ # the original hash:
39
+ #
40
+ # hash = {a: {b: 2}} # => {a: {b: 2}}
41
+ # dup, deep = hash.dup, hash.deep_dup # => {a: {b: 2}}, {a: {b: 2}}
42
+ #
43
+ # deep[:a][:b] = 14 # => {a: {b: 14}}
44
+ # p hash # => {a: {b: 2}}
45
+ #
46
+ # dup[:a][:b] = 14 # => {a: {b: 14}}
47
+ # p hash # => {a: {b: 14}}
48
+
49
+ def deep_dup
50
+ self.each_with_object(dup) do |(key, value), hash|
51
+ hash[key.deep_dup] = value.deep_dup
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,39 @@
1
+ class Object
2
+
3
+ # The +#duplicable?+ method checks whether an object may be safely duplicated.
4
+ # It returns true, unless the object calling it has its own method called
5
+ # +#duplicable?+. The +#duplicable?+ method is defined for non-duplicable
6
+ # classes in +./object/duplicable.rb+.
7
+
8
+ def duplicable?
9
+ true
10
+ end
11
+ end
12
+
13
+ # Define +#duplicable?+ for all of the classes in the array.
14
+
15
+ [NilClass, FalseClass, TrueClass, Method, Symbol, Numeric].each do |klass|
16
+ klass.class_eval do
17
+ def duplicable?
18
+ false
19
+ end
20
+ end
21
+ end
22
+
23
+ require 'bigdecimal'
24
+
25
+ # BigDecimal class from Ruby's standard library. See documentation for version
26
+ # 2.1.3[http://www.ruby-doc.org/stdlib-2.1.3/libdoc/bigdecimal/rdoc/BigDecimal.html],
27
+ # 2.0.0[http://ruby-doc.org/stdlib-2.0.0/libdoc/bigdecimal/rdoc/BigDecimal.html], or
28
+ # 1.9.3[http://www.ruby-doc.org/stdlib-1.9.3/libdoc/bigdecimal/rdoc/BigDecimal.html].
29
+
30
+ class BigDecimal
31
+
32
+ # This is required for compatibility with Ruby 1.9.x. In Ruby 1.9.x,
33
+ # +dup+ is not allowed on a BigDecimal and raises a TypeError. Rescue
34
+ # the type error to simply return false.
35
+
36
+ def duplicable?
37
+ !!self.dup rescue super
38
+ end
39
+ end