tfg_support 0.2.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|