reactive_support 0.1.2
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 +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 [](https://travis-ci.org/danascheider/reactive_support) [](https://coveralls.io/r/danascheider/reactive_support) [](https://codeclimate.com/github/danascheider/reactive_support) [](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
|