reactive_support 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +162 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +92 -0
- data/files.rb +19 -0
- data/lib/extensions/reactive_extensions.rb +41 -0
- data/lib/reactive_support/core_ext/array/access.rb +34 -0
- data/lib/reactive_support/core_ext/object/blank.rb +189 -0
- data/lib/reactive_support/core_ext/object/deep_dup.rb +54 -0
- data/lib/reactive_support/core_ext/object/duplicable.rb +39 -0
- data/lib/reactive_support/core_ext/object/exist.rb +14 -0
- data/lib/reactive_support/core_ext/object/inclusion.rb +39 -0
- data/lib/reactive_support/core_ext/object/instance_variables.rb +37 -0
- data/lib/reactive_support/core_ext/object/try.rb +46 -0
- data/lib/reactive_support/extensions/reactive_extensions.rb +41 -0
- data/lib/reactive_support.rb +15 -0
- data/reactive_support.gemspec +39 -0
- data/spec/array_spec.rb +71 -0
- data/spec/reactive_extensions_spec.rb +24 -0
- data/spec/reactive_support_spec.rb +314 -0
- data/spec/spec_helper.rb +18 -0
- data/version.rb +14 -0
- metadata +130 -0
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
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
|