tfg_support 0.2.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +17 -32
- data/Rakefile +1 -1
- data/lib/tfg/support/core_ext/hash/deep.rb +30 -0
- data/lib/tfg/support/core_ext/hash/map_values.rb +32 -0
- data/lib/tfg/support/core_ext/hash/with_indifferent_equality.rb +27 -0
- data/lib/tfg/support/core_ext/hash.rb +3 -0
- data/lib/tfg/support/core_ext/object/as.rb +37 -0
- data/lib/tfg/support/core_ext/object.rb +3 -0
- data/lib/tfg/support/core_ext/string/to_boolean.rb +21 -0
- data/lib/tfg/support/core_ext/string.rb +3 -0
- data/lib/tfg/support/deep_hash_accessor.rb +34 -0
- data/lib/tfg/support/hash_with_indifferent_equality.rb +31 -0
- data/lib/tfg/support/sequence.rb +22 -0
- data/lib/tfg/support/version.rb +5 -0
- data/lib/tfg_support.rb +14 -6
- data/spec/spec_helper.rb +2 -1
- data/spec/tfg/support/core_ext/hash/deep_spec.rb +12 -0
- data/spec/tfg/support/core_ext/hash/map_values_spec.rb +23 -0
- data/spec/tfg/support/core_ext/hash/with_indifferent_equality_spec.rb +59 -0
- data/spec/tfg/support/core_ext/object/as_spec.rb +24 -0
- data/spec/tfg/support/core_ext/string/to_boolean_spec.rb +32 -0
- data/spec/tfg/support/deep_hash_accessor_spec.rb +63 -0
- data/spec/tfg/support/hash_with_indifferent_equality_spec.rb +23 -0
- data/spec/tfg/support/sequence_spec.rb +25 -0
- data/tfg_support.gemspec +9 -5
- metadata +120 -25
- checksums.yaml +0 -7
- data/lib/tfg_support/deep_hash_accessor.rb +0 -35
- data/lib/tfg_support/hash.rb +0 -5
- data/lib/tfg_support/sequence.rb +0 -16
- data/lib/tfg_support/string.rb +0 -8
- data/lib/tfg_support/version.rb +0 -3
- data/spec/hash_spec.rb +0 -76
- data/spec/string_spec.rb +0 -31
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--debugger
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
thefrontiergroup-support
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-1.9.3-p392
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,48 +1,33 @@
|
|
1
|
-
#
|
1
|
+
# TFG::Support
|
2
|
+
|
3
|
+
A collection of handy helpers and extentions to the Ruby core library.
|
4
|
+
Should only contain application-nonspecific code that is of general use.
|
2
5
|
|
3
6
|
## Installation
|
4
7
|
|
5
8
|
Add this line to your application's Gemfile:
|
6
9
|
|
7
|
-
|
10
|
+
```ruby
|
11
|
+
gem "tfg_support"
|
12
|
+
```
|
8
13
|
|
9
14
|
And then execute:
|
10
15
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Provides some useful extentions to ruby classes.
|
16
|
-
|
17
|
-
### [Hash] (http://ruby-doc.org/core-2.0/Hash.html)
|
18
|
-
|
19
|
-
#### #deep
|
20
|
-
|
21
|
-
Allows access to hashes nested with in other hashes.
|
22
|
-
|
23
|
-
Replace
|
24
|
-
|
25
|
-
value = some_hash[:foo][:bar][:baz] if some_hash[:foo] && some_hash[:foo][:bar]
|
26
|
-
|
27
|
-
with
|
28
|
-
|
29
|
-
value = hash.deep[:foo, :bar, :baz]
|
16
|
+
```sh
|
17
|
+
$ bundle
|
18
|
+
```
|
30
19
|
|
31
|
-
|
20
|
+
This gem does not depend on `active_support`, however, if you with to use `Hash#with_indifferent_equality` you must ensure that `active_support` is loaded before `tfg_support`.
|
32
21
|
|
33
|
-
|
34
|
-
hash.deep[:foo, :bar, :baz] = :frob
|
35
|
-
hash.deep[:foo, :missing_key, :baz] = :frob
|
22
|
+
## Documentation
|
36
23
|
|
37
|
-
|
38
|
-
=> {:foo=>{:bar=>{:baz=>:frob}, :missing_key=>{:baz=>:frob}}}
|
24
|
+
The codebase is documented using `yard`.
|
39
25
|
|
40
|
-
|
26
|
+
Documentation can be viewed in the source tree or at [RubyDoc](http://rubydoc.info/github/thefrontiergroup/thefrontiergroup-tfg_support/master/frames).
|
41
27
|
|
42
|
-
|
28
|
+
## Versioning
|
43
29
|
|
44
|
-
|
45
|
-
and `'false' 'f' 'no' 'n' '0'` to `false`
|
30
|
+
This project uses [Semantic Versioning](http://semver.org).
|
46
31
|
|
47
32
|
## Contributing
|
48
33
|
|
@@ -50,4 +35,4 @@ and `'false' 'f' 'no' 'n' '0'` to `false`
|
|
50
35
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
51
36
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
52
37
|
4. Push to the branch (`git push origin my-new-feature`)
|
53
|
-
5. Create
|
38
|
+
5. Create a Pull Request
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "tfg/support/deep_hash_accessor"
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
# Allows chaining of keys through nested hashes.
|
5
|
+
#
|
6
|
+
# ```ruby
|
7
|
+
# hash = {foo: true, bar: {baz: {qux: false}}}
|
8
|
+
#
|
9
|
+
# hash.deep[:foo] #=> true
|
10
|
+
# hash.deep[:bar, :baz, :qux] #=> false
|
11
|
+
# ```
|
12
|
+
#
|
13
|
+
# When the chain of keys is incomplete `nil` will be returned.
|
14
|
+
#
|
15
|
+
# ```ruby
|
16
|
+
# hash[:bar, :qux] #=> nil
|
17
|
+
# ```
|
18
|
+
#
|
19
|
+
# Assignment is also possible, and the key chain will be created
|
20
|
+
# if needed.
|
21
|
+
#
|
22
|
+
# ```ruby
|
23
|
+
# hash = {}
|
24
|
+
# hash[:foo, :bar] = true
|
25
|
+
# hash #=> {foo: {bar: true}}
|
26
|
+
# ```
|
27
|
+
def deep
|
28
|
+
TFG::Support::DeepHashAccessor.new(self)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Hash
|
2
|
+
# Allows you to map the values of a hash. The original
|
3
|
+
# keys will be retained.
|
4
|
+
#
|
5
|
+
# ```ruby
|
6
|
+
# {foo: 1, bar: 2}.map_values {|value| value * 2 } #=> {foo: 2, bar: 4}
|
7
|
+
# ```
|
8
|
+
#
|
9
|
+
# The original hash is not mutated.
|
10
|
+
def map_values
|
11
|
+
Hash.new.tap do |result|
|
12
|
+
self.each do |key, value|
|
13
|
+
result[key] = yield(value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# The same as {Hash#map_values}, except mutates and returns the original hash.
|
19
|
+
#
|
20
|
+
# ```ruby
|
21
|
+
# hash = {foo: 1, bar: 2}
|
22
|
+
# hash.map_values {|value| value * 2 }
|
23
|
+
# hash #=> {foo: 2, bar: 4}
|
24
|
+
# ```
|
25
|
+
def map_values!
|
26
|
+
self.tap do |hash|
|
27
|
+
hash.each do |key, value|
|
28
|
+
hash[key] = yield(value)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
if defined? ActiveSupport
|
2
|
+
class Hash
|
3
|
+
# Will return a new hash that does not differentiate
|
4
|
+
# between string and symbol keys for equality.
|
5
|
+
#
|
6
|
+
# ```ruby
|
7
|
+
# {a: 1} == {"a" => 1}.with_indifferent_equality #=> true
|
8
|
+
# ```
|
9
|
+
def with_indifferent_equality
|
10
|
+
TFG::Support::HashWithIndifferentEquality.new(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Aliased to original {Hash#==}.
|
14
|
+
alias_method :old_double_equals, :==
|
15
|
+
|
16
|
+
# Check equality of hashes, considering if difference
|
17
|
+
# between string and symbol keys should be observed.
|
18
|
+
# See {Hash#with_indifferent_equality}.
|
19
|
+
def ==(other)
|
20
|
+
if other.is_a?(TFG::Support::HashWithIndifferentEquality)
|
21
|
+
other == self
|
22
|
+
else
|
23
|
+
old_double_equals(other)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Object
|
2
|
+
# The method #as allows you to take an object and use it in a block. If
|
3
|
+
# you return a non-nil value, #as will return that value, otherwise the
|
4
|
+
# original object is returned.
|
5
|
+
#
|
6
|
+
# This is particularly useful with super.
|
7
|
+
#
|
8
|
+
# ```ruby
|
9
|
+
# def overridden_method
|
10
|
+
# super.as |value|
|
11
|
+
# if value.is_a? String
|
12
|
+
# Array.wrap(value)
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
# ```
|
17
|
+
#
|
18
|
+
# Is equivalent to:
|
19
|
+
#
|
20
|
+
# ```ruby
|
21
|
+
# def overridden_method
|
22
|
+
# _overridden_method = super
|
23
|
+
#
|
24
|
+
# if _overridden_method.is_a? String
|
25
|
+
# Array.wrap(_overridden_method)
|
26
|
+
# else
|
27
|
+
# _overridden_method
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
# ```
|
31
|
+
def _as
|
32
|
+
result = yield(self)
|
33
|
+
result.nil? ? self : result
|
34
|
+
end
|
35
|
+
|
36
|
+
alias_method :as, :_as
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class String
|
2
|
+
# Attempts to cast the string to `true` or `false`. This is done
|
3
|
+
# by comparison with known truthy and falsey values.
|
4
|
+
#
|
5
|
+
# ```ruby
|
6
|
+
# "Yes".to_boolean #=> true
|
7
|
+
# "1".to_boolean #=> true
|
8
|
+
#
|
9
|
+
# "NO".to_boolean #=> false
|
10
|
+
# "FaLsE".to_boolean #=> false
|
11
|
+
# ```
|
12
|
+
#
|
13
|
+
# @raise ArgumentError when the string does not match either a
|
14
|
+
# truthey or falsey value.
|
15
|
+
def to_boolean
|
16
|
+
return true if self =~ (/\A(true|t|yes|y|1)\Z/i)
|
17
|
+
return false if self =~ (/\A(false|f|no|n|0)\Z/i)
|
18
|
+
|
19
|
+
raise ArgumentError.new("String \"#{self}\" cannot be cast to boolean.")
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module TFG
|
2
|
+
module Support
|
3
|
+
class DeepHashAccessor
|
4
|
+
def initialize(hash)
|
5
|
+
self.hash = hash
|
6
|
+
end
|
7
|
+
|
8
|
+
def [](*keys)
|
9
|
+
head, *tail = keys
|
10
|
+
|
11
|
+
if tail.empty?
|
12
|
+
hash[head]
|
13
|
+
else
|
14
|
+
hash[head].deep[*tail] if hash[head]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(*keys, value)
|
19
|
+
head, *tail = keys
|
20
|
+
|
21
|
+
if tail.empty?
|
22
|
+
hash[head] = value
|
23
|
+
else
|
24
|
+
hash[head] ||= Hash.new
|
25
|
+
hash[head].deep[*tail] = value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_accessor :hash
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module TFG
|
2
|
+
module Support
|
3
|
+
class HashWithIndifferentEquality < BasicObject
|
4
|
+
def initialize(hash)
|
5
|
+
@hash = hash
|
6
|
+
end
|
7
|
+
|
8
|
+
def is_a?(klass)
|
9
|
+
if klass == ::TFG::Support::HashWithIndifferentEquality
|
10
|
+
return true
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def ==(other)
|
17
|
+
if other.is_a?(::Hash)
|
18
|
+
@hash.with_indifferent_access == other.with_indifferent_access
|
19
|
+
else
|
20
|
+
@hash == other
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def method_missing(name, *args, &block)
|
27
|
+
@hash.public_send(name, *args, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module TFG
|
2
|
+
module Support
|
3
|
+
class Sequence
|
4
|
+
def initialize(first, generator)
|
5
|
+
self.first = first
|
6
|
+
self.generator = generator
|
7
|
+
end
|
8
|
+
|
9
|
+
def next
|
10
|
+
if previous
|
11
|
+
self.previous = generator.call(previous)
|
12
|
+
else
|
13
|
+
self.previous = first
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_accessor :first, :previous, :generator
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/tfg_support.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
|
-
require "
|
1
|
+
require "tfg/support/version"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
autoload :Sequence, "tfg_support/sequence"
|
3
|
+
if defined? ActiveSupport
|
4
|
+
require "active_support/core_ext/hash/indifferent_access"
|
6
5
|
end
|
7
6
|
|
8
|
-
|
9
|
-
|
7
|
+
module TFG
|
8
|
+
module Support
|
9
|
+
autoload :DeepHashAccessor, "tfg/support/deep_hash_accessor"
|
10
|
+
autoload :Sequence, "tfg/support/sequence"
|
11
|
+
autoload :HashWithIndifferentEquality, "tfg/support/hash_with_indifferent_equality"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Dir[File.expand_path("../tfg/support/core_ext/**/*.rb", __FILE__)].each do |file|
|
16
|
+
require file
|
17
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
require "
|
1
|
+
require "active_support"
|
2
|
+
require "tfg_support"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
subject(:hash) { Hash.new }
|
5
|
+
|
6
|
+
describe "#deep" do
|
7
|
+
subject(:deep) { hash.deep }
|
8
|
+
|
9
|
+
specify { expect(deep).to be_a TFG::Support::DeepHashAccessor }
|
10
|
+
specify { expect(deep.send(:hash)).to eq hash }
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
let(:hash) { {foo: 1, bar: 2, baz: 3, qux: 4} }
|
5
|
+
|
6
|
+
describe "#map_values" do
|
7
|
+
subject(:map_values) { hash.map_values {|arg| arg * 2 } }
|
8
|
+
|
9
|
+
specify { expect(map_values).to eq({foo: 2, bar: 4, baz: 6, qux: 8}) }
|
10
|
+
specify { expect{|block| hash.map_values(&block) }.to yield_successive_args(1, 2, 3, 4) }
|
11
|
+
|
12
|
+
specify { expect{ map_values }.to_not change{ hash } }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#map_values!" do
|
16
|
+
subject(:map_values!) { hash.map_values! {|arg| arg * 2 } }
|
17
|
+
|
18
|
+
specify { expect(map_values!).to eq({foo: 2, bar: 4, baz: 6, qux: 8}) }
|
19
|
+
specify { expect{|block| hash.map_values!(&block) }.to yield_successive_args(1, 2, 3, 4) }
|
20
|
+
|
21
|
+
specify { expect{ map_values! }.to change{ hash } }
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
subject(:hash) { {a: 1, b: 2} }
|
5
|
+
|
6
|
+
describe "#with_indifferent_equality" do
|
7
|
+
subject(:with_indifferent_equality) { hash.with_indifferent_equality }
|
8
|
+
|
9
|
+
specify { expect(with_indifferent_equality).to_not equal hash }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#==" do
|
13
|
+
subject(:call) { hash == other }
|
14
|
+
|
15
|
+
context "with normal hashes" do
|
16
|
+
context "with different keys" do
|
17
|
+
let(:other) { {"a" => 1, "b" => 2} }
|
18
|
+
|
19
|
+
specify { expect(call).to be_false }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with the same keys" do
|
23
|
+
let(:other) { hash.dup }
|
24
|
+
|
25
|
+
specify { expect(call).to be_true }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with two indifferent hashes" do
|
30
|
+
let(:hash) { {a: 1, b: 2}.with_indifferent_equality }
|
31
|
+
|
32
|
+
context "with different keys" do
|
33
|
+
let(:other) { {"a" => 1, "b" => 2}.with_indifferent_equality }
|
34
|
+
|
35
|
+
specify { expect(call).to be_true }
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with the same keys" do
|
39
|
+
let(:other) { {a: 1, b: 2}.with_indifferent_equality }
|
40
|
+
|
41
|
+
specify { expect(call).to be_true }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "with one indifferent hash" do
|
46
|
+
context "with different keys" do
|
47
|
+
let(:other) { {"a" => 1, "b" => 2}.with_indifferent_equality }
|
48
|
+
|
49
|
+
specify { expect(call).to be_true }
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with the same keys" do
|
53
|
+
let(:other) { {a: 1, b: 2}.with_indifferent_equality }
|
54
|
+
|
55
|
+
specify { expect(call).to be_true }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Object do
|
4
|
+
subject(:object) { Object.new }
|
5
|
+
|
6
|
+
describe "#as" do
|
7
|
+
let(:as) { object.as(&block) }
|
8
|
+
|
9
|
+
specify { expect{|block| object.as(&block) }.to yield_with_args(object) }
|
10
|
+
|
11
|
+
context "when the block returns nil" do
|
12
|
+
let(:block) { Proc.new {|arg| nil } }
|
13
|
+
|
14
|
+
specify { expect(as).to eq object }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when the block does not return nil" do
|
18
|
+
let(:block_return) { Object.new }
|
19
|
+
let(:block) { Proc.new {|arg| block_return } }
|
20
|
+
|
21
|
+
specify { expect(as).to eq block_return }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe String do
|
4
|
+
describe "#to_boolean" do
|
5
|
+
subject(:to_boolean) { string.to_boolean }
|
6
|
+
|
7
|
+
true_cases = %w(true TRUE True t T yes YES Yes y Y 1)
|
8
|
+
false_cases = %w(false FALSE False f F no NO No n N 0)
|
9
|
+
|
10
|
+
true_cases.each do |string|
|
11
|
+
context "for #{string}" do
|
12
|
+
let(:string) { string }
|
13
|
+
|
14
|
+
specify { expect(to_boolean).to be_true }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
false_cases.each do |string|
|
19
|
+
context "for #{string}" do
|
20
|
+
let(:string) { string }
|
21
|
+
|
22
|
+
specify { expect(to_boolean).to be_false }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "for other values" do
|
27
|
+
let(:string) { "bob" }
|
28
|
+
|
29
|
+
specify { expect{to_boolean}.to raise_error(ArgumentError) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe TFG::Support::DeepHashAccessor do
|
4
|
+
let(:hash) { Hash.new }
|
5
|
+
|
6
|
+
subject(:accessor) { TFG::Support::DeepHashAccessor.new(hash) }
|
7
|
+
|
8
|
+
describe "#[]" do
|
9
|
+
context "with a single argument" do
|
10
|
+
subject(:call) { accessor[:foo] }
|
11
|
+
|
12
|
+
context "when the key is present" do
|
13
|
+
let(:hash) { {foo: :bar} }
|
14
|
+
|
15
|
+
specify { expect(call).to eq :bar }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when the key is not present" do
|
19
|
+
specify { expect(call).to be_nil }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "with multiple arguments" do
|
24
|
+
subject(:call) { accessor[:foo, :bar, :baz] }
|
25
|
+
|
26
|
+
context "when key chain is present" do
|
27
|
+
let(:hash) { {foo: {bar: {baz: :qux}}} }
|
28
|
+
|
29
|
+
specify { expect(call).to eq :qux }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when key chain is not present" do
|
33
|
+
let(:hash) { {foo: {baz: {bar: :qux}}} }
|
34
|
+
|
35
|
+
specify { expect(call).to be_nil }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#[]=" do
|
41
|
+
context "with a single argument" do
|
42
|
+
subject(:call) { accessor[:foo] = :bar }
|
43
|
+
|
44
|
+
context "when the key is present" do
|
45
|
+
specify { call; expect(hash[:foo]).to eq :bar }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with multiple arguments" do
|
50
|
+
subject(:call) { accessor[:foo, :bar, :baz] = :qux }
|
51
|
+
|
52
|
+
context "when key chain is present" do
|
53
|
+
let(:hash) { {foo: {bar: {}}} }
|
54
|
+
|
55
|
+
specify { call; expect(hash[:foo][:bar][:baz]).to eq :qux }
|
56
|
+
end
|
57
|
+
|
58
|
+
context "when key chain is not present" do
|
59
|
+
specify { call; expect(hash[:foo][:bar][:baz]).to eq :qux }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe TFG::Support::HashWithIndifferentEquality do
|
4
|
+
let(:hash) { Hash.new }
|
5
|
+
|
6
|
+
subject(:hash_with_indifferent_equality) { TFG::Support::HashWithIndifferentEquality.new(hash) }
|
7
|
+
|
8
|
+
describe "#is_a?" do
|
9
|
+
subject(:is_a?) { hash_with_indifferent_equality.is_a?(klass) }
|
10
|
+
|
11
|
+
context "with TFG::Support::HashWithIndifferentEquality" do
|
12
|
+
let(:klass) { TFG::Support::HashWithIndifferentEquality }
|
13
|
+
|
14
|
+
specify { expect(is_a?).to be_true }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "with Hash" do
|
18
|
+
let(:klass) { TFG::Support::HashWithIndifferentEquality }
|
19
|
+
|
20
|
+
specify { expect(is_a?).to be_true }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe TFG::Support::Sequence do
|
4
|
+
subject(:sequence) { TFG::Support::Sequence.new(first, generator) }
|
5
|
+
|
6
|
+
describe "#next" do
|
7
|
+
let(:first) { Object.new }
|
8
|
+
let(:second) { Object.new }
|
9
|
+
let(:generator) { double("generator", call: second) }
|
10
|
+
|
11
|
+
subject(:call) { sequence.next }
|
12
|
+
|
13
|
+
context "on the first call" do
|
14
|
+
specify { expect(call).to eq first }
|
15
|
+
specify { call; expect(generator).to_not have_received(:call) }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "on susequent calls" do
|
19
|
+
before { sequence.next }
|
20
|
+
|
21
|
+
specify { expect(call).to eq second }
|
22
|
+
specify { call; expect(generator).to have_received(:call).with(first) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/tfg_support.gemspec
CHANGED
@@ -1,24 +1,28 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require '
|
4
|
+
require 'tfg/support/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "tfg_support"
|
8
|
-
spec.version =
|
8
|
+
spec.version = TFG::Support::VERSION
|
9
9
|
spec.authors = ["Courtney de Lautour"]
|
10
10
|
spec.email = ["clautour@thefrontiergroup.com.au"]
|
11
11
|
spec.description = %q{A collection of helper methods / extensions for Ruby}
|
12
12
|
spec.summary = %q{A collection of helper methods / extensions for Ruby}
|
13
|
-
spec.homepage = "https://github.com/
|
13
|
+
spec.homepage = "https://github.com/thefrontiergroup/thefrontiergroup-support"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^
|
18
|
+
spec.test_files = spec.files.grep(%r{^spec/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "bundler"
|
21
|
+
spec.add_development_dependency "bundler"
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "yard"
|
25
|
+
spec.add_development_dependency "redcarpet"
|
26
|
+
spec.add_development_dependency "debugger"
|
27
|
+
spec.add_development_dependency "active_support"
|
24
28
|
end
|
metadata
CHANGED
@@ -1,55 +1,126 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tfg_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Courtney de Lautour
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-
|
12
|
+
date: 2013-07-26 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
|
-
- -
|
19
|
+
- - ! '>='
|
18
20
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
21
|
+
version: '0'
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
|
-
- -
|
27
|
+
- - ! '>='
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
29
|
+
version: '0'
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: rake
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
|
-
- - '>='
|
35
|
+
- - ! '>='
|
32
36
|
- !ruby/object:Gem::Version
|
33
37
|
version: '0'
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
|
-
- - '>='
|
43
|
+
- - ! '>='
|
39
44
|
- !ruby/object:Gem::Version
|
40
45
|
version: '0'
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: rspec
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: yard
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: redcarpet
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: debugger
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: active_support
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
44
114
|
requirements:
|
45
|
-
- - '>='
|
115
|
+
- - ! '>='
|
46
116
|
- !ruby/object:Gem::Version
|
47
117
|
version: '0'
|
48
118
|
type: :development
|
49
119
|
prerelease: false
|
50
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
51
122
|
requirements:
|
52
|
-
- - '>='
|
123
|
+
- - ! '>='
|
53
124
|
- !ruby/object:Gem::Version
|
54
125
|
version: '0'
|
55
126
|
description: A collection of helper methods / extensions for Ruby
|
@@ -60,45 +131,69 @@ extensions: []
|
|
60
131
|
extra_rdoc_files: []
|
61
132
|
files:
|
62
133
|
- .gitignore
|
134
|
+
- .rspec
|
135
|
+
- .ruby-gemset
|
136
|
+
- .ruby-version
|
137
|
+
- .yardopts
|
63
138
|
- Gemfile
|
64
139
|
- LICENSE.txt
|
65
140
|
- README.md
|
66
141
|
- Rakefile
|
142
|
+
- lib/tfg/support/core_ext/hash.rb
|
143
|
+
- lib/tfg/support/core_ext/hash/deep.rb
|
144
|
+
- lib/tfg/support/core_ext/hash/map_values.rb
|
145
|
+
- lib/tfg/support/core_ext/hash/with_indifferent_equality.rb
|
146
|
+
- lib/tfg/support/core_ext/object.rb
|
147
|
+
- lib/tfg/support/core_ext/object/as.rb
|
148
|
+
- lib/tfg/support/core_ext/string.rb
|
149
|
+
- lib/tfg/support/core_ext/string/to_boolean.rb
|
150
|
+
- lib/tfg/support/deep_hash_accessor.rb
|
151
|
+
- lib/tfg/support/hash_with_indifferent_equality.rb
|
152
|
+
- lib/tfg/support/sequence.rb
|
153
|
+
- lib/tfg/support/version.rb
|
67
154
|
- lib/tfg_support.rb
|
68
|
-
- lib/tfg_support/deep_hash_accessor.rb
|
69
|
-
- lib/tfg_support/hash.rb
|
70
|
-
- lib/tfg_support/sequence.rb
|
71
|
-
- lib/tfg_support/string.rb
|
72
|
-
- lib/tfg_support/version.rb
|
73
|
-
- spec/hash_spec.rb
|
74
155
|
- spec/spec_helper.rb
|
75
|
-
- spec/
|
156
|
+
- spec/tfg/support/core_ext/hash/deep_spec.rb
|
157
|
+
- spec/tfg/support/core_ext/hash/map_values_spec.rb
|
158
|
+
- spec/tfg/support/core_ext/hash/with_indifferent_equality_spec.rb
|
159
|
+
- spec/tfg/support/core_ext/object/as_spec.rb
|
160
|
+
- spec/tfg/support/core_ext/string/to_boolean_spec.rb
|
161
|
+
- spec/tfg/support/deep_hash_accessor_spec.rb
|
162
|
+
- spec/tfg/support/hash_with_indifferent_equality_spec.rb
|
163
|
+
- spec/tfg/support/sequence_spec.rb
|
76
164
|
- tfg_support.gemspec
|
77
|
-
homepage: https://github.com/
|
165
|
+
homepage: https://github.com/thefrontiergroup/thefrontiergroup-support
|
78
166
|
licenses:
|
79
167
|
- MIT
|
80
|
-
metadata: {}
|
81
168
|
post_install_message:
|
82
169
|
rdoc_options: []
|
83
170
|
require_paths:
|
84
171
|
- lib
|
85
172
|
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
+
none: false
|
86
174
|
requirements:
|
87
|
-
- - '>='
|
175
|
+
- - ! '>='
|
88
176
|
- !ruby/object:Gem::Version
|
89
177
|
version: '0'
|
90
178
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
|
+
none: false
|
91
180
|
requirements:
|
92
|
-
- - '>='
|
181
|
+
- - ! '>='
|
93
182
|
- !ruby/object:Gem::Version
|
94
183
|
version: '0'
|
95
184
|
requirements: []
|
96
185
|
rubyforge_project:
|
97
|
-
rubygems_version:
|
186
|
+
rubygems_version: 1.8.25
|
98
187
|
signing_key:
|
99
|
-
specification_version:
|
188
|
+
specification_version: 3
|
100
189
|
summary: A collection of helper methods / extensions for Ruby
|
101
190
|
test_files:
|
102
|
-
- spec/hash_spec.rb
|
103
191
|
- spec/spec_helper.rb
|
104
|
-
- spec/
|
192
|
+
- spec/tfg/support/core_ext/hash/deep_spec.rb
|
193
|
+
- spec/tfg/support/core_ext/hash/map_values_spec.rb
|
194
|
+
- spec/tfg/support/core_ext/hash/with_indifferent_equality_spec.rb
|
195
|
+
- spec/tfg/support/core_ext/object/as_spec.rb
|
196
|
+
- spec/tfg/support/core_ext/string/to_boolean_spec.rb
|
197
|
+
- spec/tfg/support/deep_hash_accessor_spec.rb
|
198
|
+
- spec/tfg/support/hash_with_indifferent_equality_spec.rb
|
199
|
+
- spec/tfg/support/sequence_spec.rb
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 1fd20eeadffb493510c56f4399e5b3f907cd62dc
|
4
|
-
data.tar.gz: e44d25eeaea0df82581593ae50e46d08a7bfc797
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 726f4e9f18a233b327753eca18db1ecdfbe47559b8a1405cf79b458c85d94b9aa1ab3732d4e4e008b6ffc0490e44ff72c909ad66166b2d0add984744841fcbac
|
7
|
-
data.tar.gz: 0408bb9d52d278d78dae9948cd3adc5bb212614b84e6723ac73015d7e32c229d4135ba444bc1d20259eddc8a98544886df7ec74a93289f21350afac412e93904
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module TfgSupport
|
2
|
-
class DeepHashAccessor
|
3
|
-
|
4
|
-
def initialize(hash)
|
5
|
-
@hash = hash
|
6
|
-
end
|
7
|
-
|
8
|
-
def [](*keys)
|
9
|
-
target = @hash
|
10
|
-
|
11
|
-
keys.each do |key|
|
12
|
-
return nil unless target.respond_to?(:[])
|
13
|
-
target = target[key]
|
14
|
-
end
|
15
|
-
target
|
16
|
-
end
|
17
|
-
|
18
|
-
def []=(*keys)
|
19
|
-
value = keys.pop()
|
20
|
-
set_key = keys.pop()
|
21
|
-
|
22
|
-
target = @hash
|
23
|
-
keys.each do |key|
|
24
|
-
hash = target[key]
|
25
|
-
if hash.nil?
|
26
|
-
hash = {}
|
27
|
-
target[key] = hash
|
28
|
-
end
|
29
|
-
target = hash
|
30
|
-
end
|
31
|
-
|
32
|
-
target[set_key] = value
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
data/lib/tfg_support/hash.rb
DELETED
data/lib/tfg_support/sequence.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module TfgSupport
|
2
|
-
class Sequence
|
3
|
-
|
4
|
-
def initialize(args, &block)
|
5
|
-
@current_value, @generator = args, block
|
6
|
-
end
|
7
|
-
|
8
|
-
# return the next element in the sequence
|
9
|
-
|
10
|
-
def next
|
11
|
-
@current_value = @generator.call(@current_value) if @called
|
12
|
-
@called = true
|
13
|
-
@current_value
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/lib/tfg_support/string.rb
DELETED
data/lib/tfg_support/version.rb
DELETED
data/spec/hash_spec.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Hash do
|
4
|
-
|
5
|
-
subject(:hash) do
|
6
|
-
{
|
7
|
-
shallow_key: :single_value,
|
8
|
-
deep_key:
|
9
|
-
{
|
10
|
-
nested_key: :nested_value
|
11
|
-
}
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "#deep[]" do
|
16
|
-
describe "with single argument" do
|
17
|
-
|
18
|
-
subject(:index) { hash.deep[:shallow_key] }
|
19
|
-
|
20
|
-
it "returns the value of the key" do
|
21
|
-
should eq :single_value
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "with multiple arguments" do
|
26
|
-
|
27
|
-
subject(:index) { hash.deep[:deep_key, :nested_key] }
|
28
|
-
|
29
|
-
it "returns the value of the key for the nested hash" do
|
30
|
-
should eq :nested_value
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "when a key is not present" do
|
35
|
-
|
36
|
-
subject(:index) { hash.deep[:deep_key, :missing_key, :nested_key] }
|
37
|
-
|
38
|
-
it "returns nil" do
|
39
|
-
should be nil
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe "#deep[]=" do
|
45
|
-
before :each do
|
46
|
-
deep_set
|
47
|
-
end
|
48
|
-
|
49
|
-
describe "with single argument" do
|
50
|
-
subject(:deep_set) { hash.deep[:shallow_key]= :new_value }
|
51
|
-
|
52
|
-
it "sets the key of the original hash" do
|
53
|
-
hash[:shallow_key].should eq :new_value
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "with multiple arguments" do
|
58
|
-
|
59
|
-
subject(:deep_set) { hash.deep[:deep_key, :nested_key]= :new_value }
|
60
|
-
|
61
|
-
it "sets the key of the nested hash" do
|
62
|
-
hash[:deep_key][:nested_key].should eq :new_value
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
describe "when a key is not present" do
|
67
|
-
|
68
|
-
subject(:deep_set) { hash.deep[:deep_key, :missing_key, :nested_key]= :new_value }
|
69
|
-
|
70
|
-
it "creates a new hash for the missing key" do
|
71
|
-
hash[:deep_key][:missing_key][:nested_key].should eq :new_value
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
data/spec/string_spec.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe String do
|
4
|
-
|
5
|
-
describe "#to_boolean" do
|
6
|
-
subject(:to_boolean) { str.to_boolean }
|
7
|
-
|
8
|
-
true_cases = %w(true trUe t yes y 1)
|
9
|
-
false_cases = %w(false faLse f no n 0)
|
10
|
-
|
11
|
-
true_cases.each do |str|
|
12
|
-
context "when #{str}" do
|
13
|
-
let(:str) { str }
|
14
|
-
it("returns true") { should eq true }
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
false_cases.each do |str|
|
19
|
-
context "when #{str}" do
|
20
|
-
let(:str) { str }
|
21
|
-
it("returns false") { should eq false }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
context "when something else" do
|
26
|
-
let(:str) { "bob" }
|
27
|
-
it("raises an argument error") { expect { to_boolean }.to raise_error(ArgumentError) }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|