reactive_support 0.4.0.beta3 → 0.5.0.beta
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 +4 -4
- data/lib/reactive_support/core_ext/array.rb +1 -0
- data/lib/reactive_support/core_ext/hash/keys.rb +154 -0
- data/lib/reactive_support/core_ext/hash.rb +1 -0
- data/lib/reactive_support/core_ext/object/deep_dup.rb +2 -0
- data/lib/reactive_support/core_ext/object.rb +1 -0
- data/lib/reactive_support/core_ext.rb +1 -0
- data/lib/reactive_support.rb +2 -2
- data/reactive_support.gemspec +2 -2
- data/spec/hash_spec.rb +117 -0
- data/version.rb +2 -2
- metadata +8 -8
- data/lib/reactive_support/extensions/array_extensions.rb +0 -51
- data/lib/reactive_support/extensions/hash_extensions.rb +0 -135
- data/lib/reactive_support/extensions/object_extensions.rb +0 -48
- data/lib/reactive_support/extensions/proc_extensions.rb +0 -29
- data/lib/reactive_support/extensions/reactive_extensions.rb +0 -12
- data/spec/reactive_extensions_spec.rb +0 -246
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e484324b27a831addea4d4f31a5a4343219dae84
|
4
|
+
data.tar.gz: 69b6a58c8ab40a915a92f6f2f87da0719edf918a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 273d1eaf8a1db8b34e9b0e71dc08fd8af31ef0d6d4f4fa408d53d37d87e3e49a2e84bc8b17a51c459bf5458958fbbf662f8d4ad6f5c8a929a1d6bcb7dce9562c
|
7
|
+
data.tar.gz: c114dca660f79679fdb6a59ac7d6ca866c6a9806cf76492f88aa6a7ff1d307fa88f936272eec3b2f493d5f21e0f675abc346c8828a0aaa8bb64ed9b32d9757f5
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir['./lib/reactive_support/core_ext/array/*.rb'].each {|f| require f }
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# This file adds the +#transform_keys+, +#transform_keys!+,
|
2
|
+
# +#stringify_keys+, +#stringify_keys!+, +#symbolize_keys+, and
|
3
|
+
# +#symbolize_keys! methods to Ruby's core +Hash+ class. These
|
4
|
+
# methods modify the hash's keys according to given parameters,
|
5
|
+
# or create a duplicate with keys modified in this way.
|
6
|
+
|
7
|
+
# Ruby's core Hash class. See documentation for version
|
8
|
+
# 2.1.5[http://ruby-doc.org/core-2.1.5/Hash.html],
|
9
|
+
# 2.0.0[http://ruby-doc.org/core-2.0.0/Hash.html], or
|
10
|
+
# 1.9.3[http://ruby-doc.org/core-1.9.3/Hash.html].
|
11
|
+
|
12
|
+
class Hash
|
13
|
+
|
14
|
+
# The +#assert_valid_keys method validates that all keys in a hash
|
15
|
+
# match +*valid_keys+, raising an ArgumentError if the keys don't
|
16
|
+
# match. Note that, as usual, symbols and strings are treated as
|
17
|
+
# distinct.
|
18
|
+
#
|
19
|
+
# Examples:
|
20
|
+
# {:foo => 'bar'}.assert_valid_keys(:foo) # => true
|
21
|
+
# {:foo => 'bar'}.assert_valid_keys(:foo, :baz) # => true
|
22
|
+
# {:foo => 'bar'}.assert_valid_keys(:baz) # => ArgumentError
|
23
|
+
# {:foo => 'bar'}.assert_valid_keys('foo') # => ArgumentError
|
24
|
+
|
25
|
+
def assert_valid_keys(*valid_keys)
|
26
|
+
valid_keys.flatten!
|
27
|
+
each_key do |key|
|
28
|
+
unless valid_keys.include?(key)
|
29
|
+
raise ArgumentError.new("Unknown key: #{key.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# The +#stringify_keys+ method returns a hash identical to the calling
|
35
|
+
# hash, but with symbol keys turned into strings. It is non-destructive;
|
36
|
+
# the original hash is still available after it is called.
|
37
|
+
#
|
38
|
+
# Although this method was formerly a part of ActiveSupport, it was
|
39
|
+
# already deprected by the time ReactiveSupport was introduced. For
|
40
|
+
# that reason, it is being included as part of ReactiveExtensions.
|
41
|
+
#
|
42
|
+
# Examples:
|
43
|
+
# orig = { :foo => 'bar' }
|
44
|
+
# dup = orig.stringify_keys
|
45
|
+
#
|
46
|
+
# orig #=> { :foo => 'bar' }
|
47
|
+
# dup #=> { 'foo' => 'bar' }
|
48
|
+
|
49
|
+
def stringify_keys
|
50
|
+
transform_keys &:to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
# The +#stringify_keys!+ method converts symbol hash keys into strings.
|
54
|
+
# It is a destructive method; the original hash is changed when this
|
55
|
+
# method is called.
|
56
|
+
#
|
57
|
+
# Although this method was formerly a part of ActiveSupport, it was already
|
58
|
+
# deprecated by the time ReactiveSupport was introduced. For that reason,
|
59
|
+
# it is being included as part of ReactiveExtensions.
|
60
|
+
#
|
61
|
+
# Examples:
|
62
|
+
# orig = { :foo => 'bar' }
|
63
|
+
# orig.symbolize_keys!
|
64
|
+
#
|
65
|
+
# orig #=> { 'foo' => 'bar' }
|
66
|
+
|
67
|
+
def stringify_keys!
|
68
|
+
transform_keys! &:to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
# The +#symbolize_keys+ method returns a hash identical to the calling
|
72
|
+
# hash but with string keys turned into symbols. It is non-destructive;
|
73
|
+
# the original hash is still available after it is called.
|
74
|
+
#
|
75
|
+
# Although this method was formerly a part of ActiveSupport, it was
|
76
|
+
# already deprecated by the time ReactiveSupport was introduced. For
|
77
|
+
# that reason, it is being included as part of ReactiveExtensions.
|
78
|
+
#
|
79
|
+
# Examples:
|
80
|
+
# orig = { 'foo' => 'bar' }
|
81
|
+
# dup = orig.symbolize_keys
|
82
|
+
#
|
83
|
+
# orig #=> { 'foo' => 'bar' }
|
84
|
+
# dup #=> { :foo => 'bar' }
|
85
|
+
|
86
|
+
def symbolize_keys
|
87
|
+
transform_keys {|key| key.to_sym }
|
88
|
+
end
|
89
|
+
|
90
|
+
# The +#symbolize_keys!+ method converts string hash keys into symbols.
|
91
|
+
# It is a destructive method; the original hash is changed when this
|
92
|
+
# method is called.
|
93
|
+
#
|
94
|
+
# Although this method was formerly a part of ActiveSupport, it was already
|
95
|
+
# deprecated by the time ReactiveSupport was introduced. For that reason,
|
96
|
+
# it is being included as part of ReactiveExtensions.
|
97
|
+
#
|
98
|
+
# Examples:
|
99
|
+
# orig = { 'foo' => 'bar' }
|
100
|
+
# orig.symbolize_keys!
|
101
|
+
#
|
102
|
+
# orig #=> { :foo => 'bar' }
|
103
|
+
|
104
|
+
def symbolize_keys!
|
105
|
+
transform_keys! {|key| key.to_sym }
|
106
|
+
end
|
107
|
+
|
108
|
+
# The +#transform_keys+ method returns a new hash with all keys transformed
|
109
|
+
# in accordance with the given +block+. The +#transform_keys+ method is
|
110
|
+
# non-destructive; the original hash will still be available after it is
|
111
|
+
# called.
|
112
|
+
#
|
113
|
+
# If no block is given, the method returns an enumerator.
|
114
|
+
#
|
115
|
+
# Example:
|
116
|
+
# hash = { :foo => 'bar' }
|
117
|
+
# hash.transform_keys {|key| key.to_s.upcase } # => { 'FOO' => 'bar' }
|
118
|
+
# hash.transform_keys # => #<Enumerator: {:foo=>"bar"}:transform_keys>
|
119
|
+
# hash # => { :foo => 'bar' }
|
120
|
+
|
121
|
+
def transform_keys(&block)
|
122
|
+
return enum_for(:transform_keys) unless block_given?
|
123
|
+
dup = self.class.new
|
124
|
+
|
125
|
+
each_key do |key|
|
126
|
+
dup[yield key] = self[key]
|
127
|
+
end
|
128
|
+
|
129
|
+
dup
|
130
|
+
end
|
131
|
+
|
132
|
+
# The +#transform_keys!+ method transforms all of the calling hash's keys
|
133
|
+
# in accordance with the given +block+. The +#transform_keys!+ method is
|
134
|
+
# destructive; the original hash will be changed in place after it is
|
135
|
+
# called.
|
136
|
+
#
|
137
|
+
# If no block is given, the method returns an enumerator.
|
138
|
+
#
|
139
|
+
# Example:
|
140
|
+
# hash = { :foo => 'bar' }
|
141
|
+
# hash.transform_keys! {|key| key.to_s.upcase } # => { 'FOO' => 'bar' }
|
142
|
+
# hash.transform_keys! # => #<Enumerator: {:foo=>"bar"}:transform_keys!>
|
143
|
+
# hash # => { 'FOO' => 'bar' }
|
144
|
+
|
145
|
+
def transform_keys!(&block)
|
146
|
+
return enum_for(:transform_keys) unless block_given?
|
147
|
+
|
148
|
+
keys.each do |key|
|
149
|
+
self[yield key] = delete(key)
|
150
|
+
end
|
151
|
+
|
152
|
+
self
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir['./lib/reactive_support/core_ext/hash/*.rb'].each {|f| require f }
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir['./lib/reactive_support/core_ext/object/*.rb'].each {|f| require f }
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir['./lib/reactive_support/core_ext/**/*.rb'].each {|f| require f }
|
data/lib/reactive_support.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
Dir['./lib/reactive_support
|
2
|
-
Dir['./lib/reactive_support/extensions/**/*.rb'].each {|f| require f }
|
1
|
+
Dir['./lib/reactive_support/*.rb'].each {|f| require f }
|
3
2
|
|
4
3
|
# The ReactiveSupport module implements methods from ActiveSupport. It can be
|
5
4
|
# included in Ruby's +Object+ class by adding +require 'reactive_support'+ to
|
@@ -8,6 +7,7 @@ Dir['./lib/reactive_support/extensions/**/*.rb'].each {|f| require f }
|
|
8
7
|
#
|
9
8
|
# In this example, ReactiveSupport's #try method is called on an array:
|
10
9
|
# require 'reactive_support'
|
10
|
+
# require 'reactive_support/core_ext/array/try'
|
11
11
|
#
|
12
12
|
# arr = %w(foo, bar, baz)
|
13
13
|
# arr.try(:join, '.')
|
data/reactive_support.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
|
9
9
|
s.name = 'reactive_support'
|
10
10
|
s.version = ReactiveSupport.gem_version
|
11
|
-
s.date = '2014-11-
|
11
|
+
s.date = '2014-11-28'
|
12
12
|
|
13
13
|
s.description = "ActiveSupport methods re-implemented independently of the Rails ecosystem"
|
14
14
|
s.summary = "ReactiveSupport provides useful ActiveSupport methods in a gem that is simple, stable, agnostic, and transparent."
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
|
19
19
|
# = MANIFEST =
|
20
20
|
s.files = ReactiveSupport.files
|
21
|
-
s.
|
21
|
+
s.require_paths = ['lib']
|
22
22
|
# = MANIFEST =
|
23
23
|
|
24
24
|
s.test_files = s.files.select {|path| path =~ /^spec\/.*.rb/ }
|
data/spec/hash_spec.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
let(:hash) { { :foo => 'bar', :baz => 'qux' } }
|
5
|
+
|
6
|
+
describe 'assert_valid_keys' do
|
7
|
+
context 'all keys are valid' do
|
8
|
+
it 'returns the hash' do
|
9
|
+
expect(hash.assert_valid_keys(:foo, :baz)).to eql hash
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'doesn\'t raise an error' do
|
13
|
+
expect{ hash.assert_valid_keys(:foo, :baz) }.not_to raise_error
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'keys are a subset of valid keys' do
|
18
|
+
it 'returns the hash' do
|
19
|
+
expect(hash.assert_valid_keys(:foo, :bar, :baz)).to eql hash
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'doesn\'t raise an error' do
|
23
|
+
expect{ hash.assert_valid_keys(:foo, :bar, :baz) }.not_to raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'keys are wrong type' do
|
28
|
+
it 'raises an ArgumentError' do
|
29
|
+
expect{ hash.assert_valid_keys(:foo, 'baz') }.to raise_error(ArgumentError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'invalid keys are present' do
|
34
|
+
it 'raises an ArgumentError' do
|
35
|
+
expect{ hash.assert_valid_keys(:foo, 'baz') }.to raise_error(ArgumentError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'stringify_keys' do
|
41
|
+
it 'turns symbol keys into strings' do
|
42
|
+
expect(hash.stringify_keys).to eql({'foo' => 'bar', 'baz' => 'qux'})
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'maintains the original hash' do
|
46
|
+
expect { hash.stringify_keys }.not_to change(hash, :keys)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'stringify_keys!' do
|
51
|
+
it 'turns symbol keys into strings' do
|
52
|
+
expect(hash.stringify_keys!).to eql({'foo' => 'bar', 'baz' => 'qux'})
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'overwrites the original hash' do
|
56
|
+
expect { hash.stringify_keys! }.to change(hash, :keys)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'symbolize_keys' do
|
61
|
+
let(:hash) { {'foo' => 'bar' } }
|
62
|
+
|
63
|
+
it 'turns string keys into symbols' do
|
64
|
+
expect(hash.symbolize_keys).to eql({:foo => 'bar'})
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'maintains the original hash' do
|
68
|
+
expect { hash.symbolize_keys }.not_to change(hash, :keys)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'symbolize_keys!' do
|
73
|
+
let(:hash) { {'foo' => 'bar' } }
|
74
|
+
|
75
|
+
it 'turns string keys into symbols' do
|
76
|
+
expect(hash.symbolize_keys!).to eql({:foo => 'bar'})
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'overwrites the original hash' do
|
80
|
+
expect{ hash.symbolize_keys! }.to change(hash, :keys)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'transform_keys' do
|
85
|
+
it 'changes keys according to a block' do
|
86
|
+
transformed = hash.transform_keys {|key| key.to_s.upcase }
|
87
|
+
expect(transformed).to eql({'FOO' => 'bar', 'BAZ' => 'qux'})
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'is non-destructive' do
|
91
|
+
expect{ hash.transform_keys {|key| key.to_s.upcase } }.not_to change(hash, :keys)
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'no block given' do
|
95
|
+
it 'returns an enumerator' do
|
96
|
+
expect(hash.transform_keys).to be_an(Enumerator)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'transform_keys!' do
|
102
|
+
it 'changes keys according to a block' do
|
103
|
+
transformed = hash.transform_keys! {|key| key.to_s.upcase }
|
104
|
+
expect(transformed).to eql({'FOO' => 'bar', 'BAZ' => 'qux'})
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'is destructive' do
|
108
|
+
expect{ hash.transform_keys! {|key| key.to_s.upcase } }.to change(hash, :keys)
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'no block given' do
|
112
|
+
it 'returns an enum' do
|
113
|
+
expect(hash.transform_keys!).to be_an(Enumerator)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reactive_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dana Scheider
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -76,7 +76,12 @@ extra_rdoc_files:
|
|
76
76
|
- LICENSE
|
77
77
|
files:
|
78
78
|
- "./lib/reactive_support.rb"
|
79
|
+
- "./lib/reactive_support/core_ext.rb"
|
80
|
+
- "./lib/reactive_support/core_ext/array.rb"
|
79
81
|
- "./lib/reactive_support/core_ext/array/access.rb"
|
82
|
+
- "./lib/reactive_support/core_ext/hash.rb"
|
83
|
+
- "./lib/reactive_support/core_ext/hash/keys.rb"
|
84
|
+
- "./lib/reactive_support/core_ext/object.rb"
|
80
85
|
- "./lib/reactive_support/core_ext/object/blank.rb"
|
81
86
|
- "./lib/reactive_support/core_ext/object/deep_dup.rb"
|
82
87
|
- "./lib/reactive_support/core_ext/object/duplicable.rb"
|
@@ -84,13 +89,8 @@ files:
|
|
84
89
|
- "./lib/reactive_support/core_ext/object/inclusion.rb"
|
85
90
|
- "./lib/reactive_support/core_ext/object/instance_variables.rb"
|
86
91
|
- "./lib/reactive_support/core_ext/object/try.rb"
|
87
|
-
- "./lib/reactive_support/extensions/array_extensions.rb"
|
88
|
-
- "./lib/reactive_support/extensions/hash_extensions.rb"
|
89
|
-
- "./lib/reactive_support/extensions/object_extensions.rb"
|
90
|
-
- "./lib/reactive_support/extensions/proc_extensions.rb"
|
91
|
-
- "./lib/reactive_support/extensions/reactive_extensions.rb"
|
92
92
|
- "./spec/array_spec.rb"
|
93
|
-
- "./spec/
|
93
|
+
- "./spec/hash_spec.rb"
|
94
94
|
- "./spec/reactive_support_spec.rb"
|
95
95
|
- "./spec/spec_helper.rb"
|
96
96
|
- CONTRIBUTING.md
|
@@ -1,51 +0,0 @@
|
|
1
|
-
class Array
|
2
|
-
|
3
|
-
# The +#scope+ method is called on an array of hashes. It returns a sub-array
|
4
|
-
# including only hashes for which the value at a given +key+ is among the given +values+.
|
5
|
-
# The +#scope+ method is non-destructive; the original array will remain intact
|
6
|
-
# after it is called. The +#scope+ method is known to work for string or symbol
|
7
|
-
# keys. It should work for other data type keys as well.
|
8
|
-
#
|
9
|
-
# Example:
|
10
|
-
# array = [
|
11
|
-
# { name: 'Jean-Paul Sartre', nationality: 'French' },
|
12
|
-
# { name: 'Bertrand Russell', nationality: 'English' },
|
13
|
-
# { name: 'Ludwig Wittgenstein', nationality: 'Austrian' },
|
14
|
-
# { name: 'Albert Camus', nationality: 'French' }
|
15
|
-
# ]
|
16
|
-
#
|
17
|
-
# array.scope(:nationality, 'French')
|
18
|
-
# # => [
|
19
|
-
# { name: 'Jean-Paul Sartre', nationality: 'French' },
|
20
|
-
# { name: 'Albert Camus', nationality: 'French' }
|
21
|
-
# ]
|
22
|
-
|
23
|
-
def scope(key, *values)
|
24
|
-
self.select {|hash| hash[key].in?(values) }
|
25
|
-
end
|
26
|
-
|
27
|
-
# The +#where_not+ method is called on an array of hashes. It returns a sub-array
|
28
|
-
# including only hashes for which the value at a given +key+ is not among the
|
29
|
-
# given +values+. It is the inverse of the +#scope+ method. The +#where_not+ method
|
30
|
-
# is non-destructive; the original array will remain intact after it is called. The
|
31
|
-
# +#where_not+ method is known to work for string or symbol keys. It should work for
|
32
|
-
# other data types as well.
|
33
|
-
#
|
34
|
-
# Example:
|
35
|
-
# array = [
|
36
|
-
# { name: 'Jean-Paul Sartre', nationality: 'French' },
|
37
|
-
# { name: 'Bertrand Russell', nationality: 'English' },
|
38
|
-
# { name: 'Ludwig Wittgenstein', nationality: 'Austrian' },
|
39
|
-
# { name: 'Albert Camus', nationality: 'French' }
|
40
|
-
# ]
|
41
|
-
#
|
42
|
-
# array.where_not(:nationality, 'French')
|
43
|
-
# # => [
|
44
|
-
# { name: 'Bertrand Russell', nationality: 'English' },
|
45
|
-
# { name: 'Ludwig Wittgenstein', nationality: 'English' }
|
46
|
-
# ]
|
47
|
-
|
48
|
-
def where_not(key, *values)
|
49
|
-
self.reject {|hash| hash[key].in?(values) }
|
50
|
-
end
|
51
|
-
end
|
@@ -1,135 +0,0 @@
|
|
1
|
-
class Hash
|
2
|
-
|
3
|
-
# The +#clean+ method returns a hash identical to the calling hash but
|
4
|
-
# with the given +*keys+, if present, removed. If all the keys in the
|
5
|
-
# hash are given as arguments, an empty hash is returned. The +#clean+
|
6
|
-
# method is non-destructive; the original hash is still available after
|
7
|
-
# it is called. It does have a destructive form, +#clean!+.
|
8
|
-
#
|
9
|
-
# Examples:
|
10
|
-
# hash = {:foo => 'bar'}
|
11
|
-
# hash.clean(:baz) # => {:foo => 'bar'}
|
12
|
-
# hash.clean(:foo) # => {}
|
13
|
-
# hash # => {:foo => 'bar'}
|
14
|
-
#
|
15
|
-
# Examples with multiple arguments:
|
16
|
-
# hash = { 'foo' => 'bar', 'baz' => 'qux', => :norf => 'raboof' }
|
17
|
-
# hash.clean('foo', :norf) # => {'baz' => 'qux'}
|
18
|
-
# hash # => { 'foo' => 'bar', 'baz' => 'qux', :norf => 'raboof' }
|
19
|
-
|
20
|
-
def clean(*keys)
|
21
|
-
self.reject {|k,v| k.in?(keys) }
|
22
|
-
end
|
23
|
-
|
24
|
-
# The +#clean!+ method returns a hash identical to the calling hash but
|
25
|
-
# with the given +*keys+, if present, removed. If all the keys in the
|
26
|
-
# hash are given as arguments, an empty hash is returned. The +#clean!+
|
27
|
-
# method is non-destructive; the original hash is still available after
|
28
|
-
# it is called. It does have a non-destructive form, +#clean+.
|
29
|
-
#
|
30
|
-
# Examples where hash is not changed:
|
31
|
-
# hash = {:foo => 'bar'}
|
32
|
-
# hash.clean!(:baz) # => {:foo => 'bar'}
|
33
|
-
# hash # => {:foo => 'bar'}
|
34
|
-
#
|
35
|
-
# Examples where hash is changed:
|
36
|
-
# hash = {'foo' => 'bar'}
|
37
|
-
# hash.clean!(:foo) # => {}
|
38
|
-
# hash # => {}
|
39
|
-
#
|
40
|
-
# Examples with multiple arguments:
|
41
|
-
# hash = { 'foo' => 'bar', 'baz' => 'qux', => :norf => 'raboof' }
|
42
|
-
# hash.clean('foo', :norf) # => {'baz' => 'qux'}
|
43
|
-
# hash # => {'baz' => 'qux'}
|
44
|
-
|
45
|
-
def clean!(*keys)
|
46
|
-
self.reject! {|k,v| k.in?(keys) }
|
47
|
-
self
|
48
|
-
end
|
49
|
-
|
50
|
-
# The +#symbolize_keys+ method returns a hash identical to the calling
|
51
|
-
# hash but with string keys turned into symbols. It is non-destructive;
|
52
|
-
# the original hash is still available after it is called.
|
53
|
-
#
|
54
|
-
# Although this method was formerly a part of ActiveSupport, it was
|
55
|
-
# already deprecated by the time ReactiveSupport was introduced. For
|
56
|
-
# that reason, it is being included as part of ReactiveExtensions.
|
57
|
-
#
|
58
|
-
# Examples:
|
59
|
-
# orig = { 'foo' => 'bar' }
|
60
|
-
# dup = orig.symbolize_keys
|
61
|
-
#
|
62
|
-
# orig #=> { 'foo' => 'bar' }
|
63
|
-
# dup #=> { :foo => 'bar' }
|
64
|
-
|
65
|
-
def symbolize_keys
|
66
|
-
dup = {}
|
67
|
-
self.each {|k, v| dup[k.to_sym] = v }
|
68
|
-
dup
|
69
|
-
end
|
70
|
-
|
71
|
-
# The +#symbolize_keys!+ method converts string hash keys into symbols.
|
72
|
-
# It is a destructive method; the original hash is changed when this
|
73
|
-
# method is called.
|
74
|
-
#
|
75
|
-
# Although this method was formerly a part of ActiveSupport, it was already
|
76
|
-
# deprecated by the time ReactiveSupport was introduced. For that reason,
|
77
|
-
# it is being included as part of ReactiveExtensions.
|
78
|
-
#
|
79
|
-
# Examples:
|
80
|
-
# orig = { 'foo' => 'bar' }
|
81
|
-
# orig.symbolize_keys!
|
82
|
-
#
|
83
|
-
# orig #=> { :foo => 'bar' }
|
84
|
-
|
85
|
-
def symbolize_keys!
|
86
|
-
keys.each do |key|
|
87
|
-
self[(key.to_sym rescue key) || key] = delete(key)
|
88
|
-
end
|
89
|
-
|
90
|
-
self
|
91
|
-
end
|
92
|
-
|
93
|
-
# The +#stringify_keys+ method returns a hash identical to the calling
|
94
|
-
# hash, but with symbol keys turned into strings. It is non-destructive;
|
95
|
-
# the original hash is still available after it is called.
|
96
|
-
#
|
97
|
-
# Although this method was formerly a part of ActiveSupport, it was
|
98
|
-
# already deprected by the time ReactiveSupport was introduced. For
|
99
|
-
# that reason, it is being included as part of ReactiveExtensions.
|
100
|
-
#
|
101
|
-
# Examples:
|
102
|
-
# orig = { :foo => 'bar' }
|
103
|
-
# dup = orig.stringify_keys
|
104
|
-
#
|
105
|
-
# orig #=> { :foo => 'bar' }
|
106
|
-
# dup #=> { 'foo' => 'bar' }
|
107
|
-
|
108
|
-
def stringify_keys
|
109
|
-
dup = {}
|
110
|
-
self.each {|k, v| dup[k.to_s] = v }
|
111
|
-
dup
|
112
|
-
end
|
113
|
-
|
114
|
-
# The +#stringify_keys!+ method converts symbol hash keys into strings.
|
115
|
-
# It is a destructive method; the original hash is changed when this
|
116
|
-
# method is called.
|
117
|
-
#
|
118
|
-
# Although this method was formerly a part of ActiveSupport, it was already
|
119
|
-
# deprecated by the time ReactiveSupport was introduced. For that reason,
|
120
|
-
# it is being included as part of ReactiveExtensions.
|
121
|
-
#
|
122
|
-
# Examples:
|
123
|
-
# orig = { :foo => 'bar' }
|
124
|
-
# orig.symbolize_keys!
|
125
|
-
#
|
126
|
-
# orig #=> { 'foo' => 'bar' }
|
127
|
-
|
128
|
-
def stringify_keys!
|
129
|
-
keys.each do |key|
|
130
|
-
self[(key.to_s rescue key) || key] = delete(key)
|
131
|
-
end
|
132
|
-
|
133
|
-
self
|
134
|
-
end
|
135
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
class Object
|
2
|
-
|
3
|
-
# The +#try_rescue+ method extends ReactiveSupport's +#try+ method so it
|
4
|
-
# rescues NoMethodErrors and TypeErrors as well as returning +nil+ when
|
5
|
-
# called on a +nil+ value.
|
6
|
-
#
|
7
|
-
# Like the +#try+ method, +#try_rescue+ takes 1 or more arguments. The first
|
8
|
-
# argument is the method to be called on the calling object, passed as a
|
9
|
-
# symbol. The others are zero or more arguments that will be passed through to
|
10
|
-
# that method, and +&block+ is an optional block that will be similarly passed through.
|
11
|
-
#
|
12
|
-
# Example of usage identical to +#try+:
|
13
|
-
# nil.try(:map) {|a| a.to_s } # => nil
|
14
|
-
# nil.try_rescue(:map) {|a| a.to_s } # => nil
|
15
|
-
#
|
16
|
-
# Example of usage calling a method that is not defined on the calling object:
|
17
|
-
# 10.try(:to_h) # => TypeError
|
18
|
-
# 10.try_rescue(:to_h) # => nil
|
19
|
-
#
|
20
|
-
# Example of usage with invalid arguments:
|
21
|
-
# %w(foo, bar, baz).try(:join, [:hello, :world]) # => TypeError
|
22
|
-
# %w(foo, bar, baz).try_rescue(:join, [:hello, :world]) # => nil
|
23
|
-
|
24
|
-
def try_rescue(*args, &block)
|
25
|
-
self.try(*args, &block) rescue nil
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# The +#try_rescue+ method extends ReactiveSupport's +#try+ method so it rescues
|
30
|
-
# NoMethodErrors and TypeErrors as well as returning +nil+ when called on a +nil+
|
31
|
-
# value.
|
32
|
-
#
|
33
|
-
# Like the +#try+ method, +#try_rescue+ takes 1 or more arguments. The first argument
|
34
|
-
# is the method to be called on the calling object, passed as a symbol. The others
|
35
|
-
# are zero or more arguments that will be passed through to that method, and an
|
36
|
-
# optional block to be likewise passed through.
|
37
|
-
#
|
38
|
-
# When called on NilClass, +#try_rescue+ always returns nil.
|
39
|
-
#
|
40
|
-
# Example:
|
41
|
-
# foo = nil
|
42
|
-
# foo.try_rescue(:has_key?, :bar) # => nil
|
43
|
-
|
44
|
-
class NilClass
|
45
|
-
def try_rescue(*args, &block)
|
46
|
-
nil
|
47
|
-
end
|
48
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# Ruby's core Proc class. See documentation for version
|
2
|
-
# 2.1.5[http://ruby-doc.org/core-2.1.5/Proc.html],
|
3
|
-
# 2.0.0[http://ruby-doc.org/core-2.0.0/Proc.html], or
|
4
|
-
# 1.9.3[http://ruby-doc.org/core-1.9.3/Proc.html].
|
5
|
-
|
6
|
-
class Proc
|
7
|
-
|
8
|
-
# The +#raises_error?+ method checks whether an exception is raised
|
9
|
-
# when the calling Proc is called with the given +*args+.
|
10
|
-
#
|
11
|
-
# The +#raises_error?+ method does not actually create lasting changes
|
12
|
-
# to objects or variables; it only checks whether an exception would be
|
13
|
-
# raised if the Proc were called with the given +*args+.
|
14
|
-
#
|
15
|
-
# Basic examples:
|
16
|
-
# proc = Proc.new {|q| 1.quo(q) }
|
17
|
-
# proc.raises_error?(2) # => false
|
18
|
-
# proc.raises_error?(0) # => true
|
19
|
-
#
|
20
|
-
# Examples with destructive proc:
|
21
|
-
# hash = {:foo => :bar}
|
22
|
-
# proc = Proc.new {|hash| hash.reject! {|k,v| k === :foo } }
|
23
|
-
# proc.raises_error?(hash) # => false
|
24
|
-
# hash # => {:foo => :bar}
|
25
|
-
|
26
|
-
def raises_error?(*args)
|
27
|
-
(!self.call(*args.deep_dup)) rescue true
|
28
|
-
end
|
29
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
|
2
|
-
# The ReactiveExtensions module consists of methods I wish ActiveSupport provided.
|
3
|
-
# These methods do not adhere to the ActiveSupport API. If you wish to include
|
4
|
-
# them in your project, you will need to put this in your main project file:
|
5
|
-
# require 'reactive_support/extensions'
|
6
|
-
#
|
7
|
-
# ReactiveExtensions includes ReactiveSupport, so you will need to remove any
|
8
|
-
# requires for ReactiveSupport as it will raise a SystemStackError.
|
9
|
-
|
10
|
-
module ReactiveExtensions
|
11
|
-
Dir['./lib/reactive_support/extensions/*.rb'].each {|f| require f }
|
12
|
-
end
|
@@ -1,246 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ReactiveExtensions do
|
4
|
-
describe '#try_rescue method' do
|
5
|
-
context 'when self is nil' do
|
6
|
-
it 'returns nil' do
|
7
|
-
expect(nil.try_rescue(:collect) {|i| i + 2 }).to eql nil
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
context 'when the method can be executed successfully' do
|
12
|
-
it 'calls the method' do
|
13
|
-
expect('foo'.try_rescue(:upcase)).to eql 'FOO'
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context 'when a NoMethodError is raised' do
|
18
|
-
it 'returns nil' do
|
19
|
-
expect(('foo').try_rescue(:bar)).to eql nil
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe 'array methods' do
|
25
|
-
let(:sartre) { { 'name' => 'Jean-Paul Sartre', 'nationality' => 'French' } }
|
26
|
-
let(:russell) { { 'name' => 'Bertrand Russell', 'nationality' => 'English' } }
|
27
|
-
let(:wittgenstein) { { 'name' => 'Ludwig Wittgenstein', 'nationality' => 'Austrian' } }
|
28
|
-
let(:camus) { { 'name' => 'Albert Camus', 'nationality' => 'French' } }
|
29
|
-
let(:array) { [sartre, russell, wittgenstein, camus] }
|
30
|
-
|
31
|
-
describe 'array #scope method' do
|
32
|
-
context 'symbol keys' do
|
33
|
-
context 'single value' do
|
34
|
-
it 'returns scoped hashes' do
|
35
|
-
array.each {|hash| hash.symbolize_keys! }
|
36
|
-
expect(array.scope(:nationality, 'French')).to eql([sartre, camus])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'multiple values' do
|
41
|
-
it 'returns scoped hashes' do
|
42
|
-
array.each {|hash| hash.symbolize_keys! }
|
43
|
-
expect(array.scope(:nationality, 'French', 'English')).to eql([sartre, russell, camus])
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'string keys' do
|
49
|
-
context 'single value' do
|
50
|
-
it 'returns scoped hashes' do
|
51
|
-
expect(array.scope('nationality', 'French')).to eql([sartre, camus])
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'multiple values' do
|
56
|
-
it 'returns scoped hashes' do
|
57
|
-
expect(array.scope('nationality', 'French', 'English')).to eql([sartre, russell, camus])
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
describe 'array #where_not method' do
|
64
|
-
context 'symbol keys' do
|
65
|
-
context 'single value' do
|
66
|
-
it 'returns scoped hashes' do
|
67
|
-
array.each {|hash| hash.symbolize_keys! }
|
68
|
-
expect(array.where_not(:nationality, 'French')).to eql([russell, wittgenstein])
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context 'multiple values' do
|
73
|
-
it 'returns scoped hashes' do
|
74
|
-
array.each {|hash| hash.symbolize_keys! }
|
75
|
-
expect(array.where_not(:nationality, 'French', 'English')).to eql([wittgenstein])
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context 'string keys' do
|
81
|
-
context 'single value' do
|
82
|
-
it 'returns scoped hashes' do
|
83
|
-
expect(array.where_not('nationality', 'French')).to eql([russell, wittgenstein])
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
context 'multiple values' do
|
88
|
-
it 'returns scoped hashes' do
|
89
|
-
expect(array.where_not('nationality', 'French', 'English')).to eql([wittgenstein])
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe 'hash methods' do
|
97
|
-
describe 'symbolize_keys' do
|
98
|
-
it 'turns string keys into symbols' do
|
99
|
-
expect({'foo' => 'bar'}.symbolize_keys).to eql({:foo => 'bar'})
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'maintains the original hash' do
|
103
|
-
hash = { 'foo' => 'bar' }
|
104
|
-
expect { hash.symbolize_keys }.not_to change(hash, :keys)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
describe 'symbolize_keys!' do
|
109
|
-
it 'turns string keys into symbols' do
|
110
|
-
expect({'foo' => 'bar'}.symbolize_keys!).to eql({:foo => 'bar'})
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'overwrites the original hash' do
|
114
|
-
hash = { 'foo' => 'bar' }
|
115
|
-
expect { hash.symbolize_keys! }.to change(hash, :keys)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe 'stringify_keys' do
|
120
|
-
it 'turns symbol keys into strings' do
|
121
|
-
expect({foo: 'bar'}.stringify_keys).to eql({'foo' => 'bar'})
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'maintains the original hash' do
|
125
|
-
hash = { foo: 'bar' }
|
126
|
-
expect { hash.stringify_keys }.not_to change(hash, :keys)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
describe 'stringify_keys!' do
|
131
|
-
it 'turns symbol keys into strings' do
|
132
|
-
expect({foo: 'bar'}.stringify_keys!).to eql({'foo' => 'bar'})
|
133
|
-
end
|
134
|
-
|
135
|
-
it 'overwrites the original hash' do
|
136
|
-
hash = { foo: 'bar' }
|
137
|
-
expect { hash.stringify_keys! }.to change(hash, :keys)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
describe 'clean' do
|
142
|
-
context 'when no cleaning is needed' do
|
143
|
-
it 'returns the original hash' do
|
144
|
-
expect({:foo => 'bar'}.clean(:baz)). to eql({:foo => 'bar'})
|
145
|
-
end
|
146
|
-
|
147
|
-
it 'doesn\'t raise an error' do
|
148
|
-
expect{ {:foo => 'bar'}.clean(:baz) }.not_to raise_error
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
context 'when there are some keys to clean' do
|
153
|
-
it 'removes specified keys' do
|
154
|
-
expect({:foo => 'bar', :baz => 'qux'}.clean(:baz)).to eql({:foo => 'bar'})
|
155
|
-
end
|
156
|
-
|
157
|
-
it 'doesn\'t change the original hash' do
|
158
|
-
hash = {:foo => 'bar', :baz => 'qux', 'norf' => 'raboof'}
|
159
|
-
expect{ hash.clean(:baz, 'norf') }.not_to change(hash, :keys)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
context 'when all keys must be cleaned' do
|
164
|
-
it 'returns an empty hash' do
|
165
|
-
expect({:foo => 'bar'}.clean(:foo)).to eql({})
|
166
|
-
end
|
167
|
-
|
168
|
-
it 'doesn\'t change the original hash' do
|
169
|
-
hash = {:foo => 'bar'}
|
170
|
-
expect{ hash.clean(:foo) }.not_to change(hash, :keys)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
describe 'clean!' do
|
176
|
-
context 'when no cleaning is needed' do
|
177
|
-
it 'returns the original hash' do
|
178
|
-
expect({:foo => 'bar'}.clean!(:baz)). to eql({:foo => 'bar'})
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'doesn\'t raise an error' do
|
182
|
-
expect{ {:foo => 'bar'}.clean(:baz) }.not_to raise_error
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
context 'when there are some keys to clean' do
|
187
|
-
it 'removes specified keys' do
|
188
|
-
expect({:foo => 'bar', :baz => 'qux'}.clean!(:baz)).to eql({:foo => 'bar'})
|
189
|
-
end
|
190
|
-
|
191
|
-
it 'changes the original hash' do
|
192
|
-
hash = {:foo => 'bar', :baz => 'qux', 'norf' => 'raboof'}
|
193
|
-
expect{ hash.clean!(:baz, 'norf') }.to change(hash, :keys)
|
194
|
-
end
|
195
|
-
|
196
|
-
it 'returns the hash' do
|
197
|
-
hash = {:foo => 'bar', :baz => 'qux'}
|
198
|
-
expect(hash.clean!(:baz)).to eql hash
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
context 'when all keys must be cleaned' do
|
203
|
-
it 'returns an empty hash' do
|
204
|
-
expect({:foo => 'bar'}.clean!(:foo)).to eql({})
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'changes the original hash' do
|
208
|
-
hash = {:foo => 'bar'}
|
209
|
-
expect{ hash.clean!(:foo) }.to change(hash, :keys)
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'returns the hash' do
|
213
|
-
hash = {:foo => 'bar'}
|
214
|
-
expect(hash.clean!(:foo)).to eql hash
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
describe 'proc methods' do
|
221
|
-
describe 'raises_error?' do
|
222
|
-
let(:proc) { Proc.new {|quotient| 1.quo(quotient) } }
|
223
|
-
|
224
|
-
context 'when an error is raised' do
|
225
|
-
it 'returns true' do
|
226
|
-
expect(proc.raises_error?(0)).to be true
|
227
|
-
end
|
228
|
-
|
229
|
-
it 'handles the exception' do
|
230
|
-
expect{ proc.raises_error?(0) }.not_to raise_error
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
context 'when no error is raised' do
|
235
|
-
it 'returns false' do
|
236
|
-
expect(proc.raises_error?(2)).to be false
|
237
|
-
end
|
238
|
-
|
239
|
-
it 'doesn\'t change objects' do
|
240
|
-
h, p = {:foo => :bar}, Proc.new {|hash| hash.reject! {|k,v| k === :foo } }
|
241
|
-
expect{ p.raises_error?(h) }.not_to change(h, :length)
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|