buff-extensions 0.1.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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p429
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ script: "bundle exec thor spec"
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - jruby-19mode
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,24 @@
1
+ # Contributing
2
+
3
+ ## Running tests
4
+
5
+ ### Install prerequisites
6
+
7
+ Install the latest version of [Bundler](http://gembundler.com)
8
+
9
+ $ gem install bundler
10
+
11
+ Clone the project
12
+
13
+ $ git clone git://github.com/RiotGames/buff-extensions.git
14
+
15
+ and run:
16
+
17
+ $ cd buff-extensions
18
+ $ bundle install
19
+
20
+ Bundler will install all gems and their dependencies required for testing and developing.
21
+
22
+ ### Running unit (RSpec) tests
23
+
24
+ $ bundle exec guard start
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,15 @@
1
+ notification :off
2
+
3
+ guard "spork" do
4
+ watch('Gemfile')
5
+ watch('spec/spec_helper.rb') { :rspec }
6
+ watch(%r{^spec/support/.+\.rb$}) { :rspec }
7
+ end
8
+
9
+ guard "rspec", cli: "--color --drb --format Fuubar", all_on_start: false, all_after_pass: false do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+
12
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
13
+ watch('spec/spec_helper.rb') { "spec" }
14
+ watch(%r{^spec/support/.+\.rb$}) { "spec" }
15
+ end
data/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Copyright 2012-2013 Riot Games
2
+
3
+ Jamie Winsor (<reset@riotgames.com>)
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # Buff::Extensions
2
+ [![Gem Version](https://badge.fury.io/rb/buff-extensions.png)](http://badge.fury.io/rb/buff-extensions)
3
+ [![Build Status](https://travis-ci.org/RiotGames/buff-extensions.png?branch=master)](https://travis-ci.org/RiotGames/buff-extensions)
4
+
5
+ Extensions to Core Ruby classes
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'buff-extensions'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install buff-extensions
20
+
21
+ ## Usage
22
+
23
+ Using it as a mixin
24
+
25
+ require 'buff/extensions'
26
+
27
+ class PowerHash
28
+ include Buff::Extensions::DottedPaths
29
+ end
30
+
31
+ # Authors and Contributors
32
+
33
+ * Jamie Winsor (<reset@riotgames.com>)
34
+
35
+ Thank you to all of our [Contributors](https://github.com/RiotGames/buff-extensions/graphs/contributors), testers, and users.
data/Thorfile ADDED
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ require 'bundler'
5
+ require 'bundler/setup'
6
+ require 'buff/ruby_engine'
7
+ require 'buff/extensions/version'
8
+
9
+ class Default < Thor
10
+ extend Buff::RubyEngine
11
+
12
+ unless jruby?
13
+ require 'thor/rake_compat'
14
+
15
+ include Thor::RakeCompat
16
+ Bundler::GemHelper.install_tasks
17
+
18
+ desc "build", "Build buff-extensions-#{Buff::Extensions::VERSION}.gem into the pkg directory"
19
+ def build
20
+ Rake::Task["build"].execute
21
+ end
22
+
23
+ desc "install", "Build and install buff-extensions-#{Buff::Extensions::VERSION}.gem into system gems"
24
+ def install
25
+ Rake::Task["install"].execute
26
+ end
27
+
28
+ desc "release", "Create tag v#{Buff::Extensions::VERSION} and build and push buff-extensions-#{Buff::Extensions::VERSION}.gem to Rubygems"
29
+ def release
30
+ Rake::Task["release"].execute
31
+ end
32
+ end
33
+
34
+ class Spec < Thor
35
+ namespace :spec
36
+ default_task :unit
37
+
38
+ desc "unit", "run the project's unit tests"
39
+ def unit
40
+ exec "rspec --color --format=documentation spec"
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'buff/extensions/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "buff-extensions"
8
+ spec.version = Buff::Extensions::VERSION
9
+ spec.authors = ["Jamie Winsor"]
10
+ spec.email = ["reset@riotgames.com"]
11
+ spec.description = %q{Extensions to Core Ruby classes}
12
+ spec.summary = spec.description
13
+ spec.homepage = "https://github.com/RiotGames/buff-extensions"
14
+ spec.license = "Apache 2.0"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^spec/})
19
+ spec.require_paths = ["lib"]
20
+ spec.required_ruby_version = ">= 1.9.2"
21
+
22
+ spec.add_development_dependency "buff-ruby_engine", "~> 0.1"
23
+ spec.add_development_dependency "thor", "~> 0.18.0"
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "fuubar"
28
+ spec.add_development_dependency "guard"
29
+ spec.add_development_dependency "guard-rspec"
30
+ spec.add_development_dependency "guard-spork"
31
+ spec.add_development_dependency "spork"
32
+ end
@@ -0,0 +1,9 @@
1
+ module Boolean; end
2
+
3
+ class TrueClass
4
+ include Boolean
5
+ end
6
+
7
+ class FalseClass
8
+ include Boolean
9
+ end
@@ -0,0 +1,124 @@
1
+ require 'buff/extensions/object'
2
+
3
+ module Buff
4
+ module Extensions
5
+ module DottedPaths
6
+ class << self
7
+ def included(base)
8
+ base.send(:extend, ClassMethods)
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ # Create a new Hash containing other nested Hashes from a string containing
14
+ # a dotted path. A Hash will be created and assigned to a key of another Hash
15
+ # for each entry in the dotted path.
16
+ #
17
+ # If a value is provided for the optional seed argument then the value of the
18
+ # deepest nested key will be set to the given value. If no value is provided
19
+ # the value of the key will be nil.
20
+ #
21
+ # @example creating a nested hash from a dotted path
22
+ #
23
+ # Hash.from_dotted_path("deep.nested.hash") =>
24
+ # {
25
+ # "deep" => {
26
+ # "nested" => {
27
+ # "hash" => nil
28
+ # }
29
+ # }
30
+ # }
31
+ #
32
+ #
33
+ # @example specifying a seed value
34
+ #
35
+ # Hash.from_dotted_path("deep.nested.hash", :seed_value) =>
36
+ # {
37
+ # "deep" => {
38
+ # "nested" => {
39
+ # "hash" => :seed_value
40
+ # }
41
+ # }
42
+ # }
43
+ #
44
+ # @param [String, Symbol, Array] dotpath
45
+ # @param [Object] seed (nil)
46
+ # @param [Hash] target (self.new)
47
+ #
48
+ # @return [Hash]
49
+ def from_dotted_path(dotpath, seed = nil, target = self.new)
50
+ case dotpath
51
+ when String, Symbol
52
+ from_dotted_path(dotpath.to_s.split("."), seed)
53
+ when Array
54
+ if dotpath.empty?
55
+ return target
56
+ end
57
+
58
+ key = dotpath.pop
59
+
60
+ if target.empty?
61
+ target[key] = seed
62
+ from_dotted_path(dotpath, seed, target)
63
+ else
64
+ new_target = self.new
65
+ new_target[key] = target
66
+ from_dotted_path(dotpath, seed, new_target)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ # Return the value of the nested hash key from the given dotted path
73
+ #
74
+ # @example
75
+ #
76
+ # nested_hash = {
77
+ # "deep" => {
78
+ # "nested" => {
79
+ # "hash" => :seed_value
80
+ # }
81
+ # }
82
+ # }
83
+ #
84
+ # nested_hash.dig('deep.nested.hash') => :seed_value
85
+ #
86
+ # @param [String] path
87
+ #
88
+ # @return [Object, nil]
89
+ def dig(path)
90
+ return nil unless path.present?
91
+
92
+ parts = path.split('.', 2)
93
+ match = self[parts[0].to_s].nil? ? self[parts[0].to_sym] : self[parts[0].to_s]
94
+ if !parts[1] or match.nil?
95
+ match
96
+ else
97
+ match.dig(parts[1])
98
+ end
99
+ end
100
+
101
+ # Returns an array of dotted paths from the keys, values of this Hash. Values which are
102
+ # nested Hashes will also recurred into and their paths will be added properly.
103
+ #
104
+ # @param [Hash] source
105
+ # @param [Array] acc
106
+ # @param [Array] namespace
107
+ #
108
+ # @return [Array<String>]
109
+ def dotted_paths(source = self, acc = Array.new, namespace = Array.new)
110
+ if source.is_a?(Hash) && !source.empty?
111
+ source.each do |key, value|
112
+ branch = namespace.dup
113
+ branch << key
114
+ dotted_paths(value, acc, branch)
115
+ end
116
+ else
117
+ acc << namespace.join('.')
118
+ end
119
+
120
+ acc
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,144 @@
1
+ module Buff
2
+ module Extensions
3
+ # Borrowd and modified from
4
+ # {https://raw.github.com/rails/rails/master/activesupport/lib/active_support/core_ext/hash/keys.rb}
5
+ module KeyTransforms
6
+ # Return a new hash with all keys converted using the block operation.
7
+ #
8
+ # hash = { name: 'Rob', age: '28' }
9
+ #
10
+ # hash.transform_keys{ |key| key.to_s.upcase }
11
+ # # => { "NAME" => "Rob", "AGE" => "28" }
12
+ def transform_keys
13
+ result = {}
14
+ each_key do |key|
15
+ result[yield(key)] = self[key]
16
+ end
17
+ result
18
+ end
19
+
20
+ # Destructively convert all keys using the block operations.
21
+ # Same as transform_keys but modifies +self+.
22
+ def transform_keys!
23
+ keys.each do |key|
24
+ self[yield(key)] = delete(key)
25
+ end
26
+ self
27
+ end
28
+
29
+ # Return a new hash with all keys converted to strings.
30
+ #
31
+ # hash = { name: 'Rob', age: '28' }
32
+ #
33
+ # hash.stringify_keys
34
+ # #=> { "name" => "Rob", "age" => "28" }
35
+ def stringify_keys
36
+ transform_keys { |key| key.to_s }
37
+ end
38
+
39
+ # Destructively convert all keys to strings. Same as
40
+ # +stringify_keys+, but modifies +self+.
41
+ def stringify_keys!
42
+ transform_keys! { |key| key.to_s }
43
+ end
44
+
45
+ # Return a new hash with all keys converted to symbols, as long as
46
+ # they respond to +to_sym+.
47
+ #
48
+ # hash = { 'name' => 'Rob', 'age' => '28' }
49
+ #
50
+ # hash.symbolize_keys
51
+ # #=> { name: "Rob", age: "28" }
52
+ def symbolize_keys
53
+ transform_keys { |key| key.to_sym rescue key }
54
+ end
55
+ alias_method :to_options, :symbolize_keys
56
+
57
+ # Destructively convert all keys to symbols, as long as they respond
58
+ # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
59
+ def symbolize_keys!
60
+ transform_keys! { |key| key.to_sym rescue key }
61
+ end
62
+ alias_method :to_options!, :symbolize_keys!
63
+
64
+ # Validate all keys in a hash match <tt>*valid_keys</tt>, raising ArgumentError
65
+ # on a mismatch. Note that keys are NOT treated indifferently, meaning if you
66
+ # use strings for keys but assert symbols as keys, this will fail.
67
+ #
68
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"
69
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: name"
70
+ # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
71
+ def assert_valid_keys(*valid_keys)
72
+ valid_keys.flatten!
73
+ each_key do |k|
74
+ raise ArgumentError.new("Unknown key: #{k}") unless valid_keys.include?(k)
75
+ end
76
+ end
77
+
78
+ # Return a new hash with all keys converted by the block operation.
79
+ # This includes the keys from the root hash and from all
80
+ # nested hashes.
81
+ #
82
+ # hash = { person: { name: 'Rob', age: '28' } }
83
+ #
84
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
85
+ # # => { "PERSON" => { "NAME" => "Rob", "AGE" => "28" } }
86
+ def deep_transform_keys(&block)
87
+ result = {}
88
+ each do |key, value|
89
+ result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
90
+ end
91
+ result
92
+ end
93
+
94
+ # Destructively convert all keys by using the block operation.
95
+ # This includes the keys from the root hash and from all
96
+ # nested hashes.
97
+ def deep_transform_keys!(&block)
98
+ keys.each do |key|
99
+ value = delete(key)
100
+ self[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys!(&block) : value
101
+ end
102
+ self
103
+ end
104
+
105
+ # Return a new hash with all keys converted to strings.
106
+ # This includes the keys from the root hash and from all
107
+ # nested hashes.
108
+ #
109
+ # hash = { person: { name: 'Rob', age: '28' } }
110
+ #
111
+ # hash.deep_stringify_keys
112
+ # # => { "person" => { "name" => "Rob", "age" => "28" } }
113
+ def deep_stringify_keys
114
+ deep_transform_keys { |key| key.to_s }
115
+ end
116
+
117
+ # Destructively convert all keys to strings.
118
+ # This includes the keys from the root hash and from all
119
+ # nested hashes.
120
+ def deep_stringify_keys!
121
+ deep_transform_keys! { |key| key.to_s }
122
+ end
123
+
124
+ # Return a new hash with all keys converted to symbols, as long as
125
+ # they respond to +to_sym+. This includes the keys from the root hash
126
+ # and from all nested hashes.
127
+ #
128
+ # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
129
+ #
130
+ # hash.deep_symbolize_keys
131
+ # # => { person: { name: "Rob", age: "28" } }
132
+ def deep_symbolize_keys
133
+ deep_transform_keys { |key| key.to_sym rescue key }
134
+ end
135
+
136
+ # Destructively convert all keys to symbols, as long as they respond
137
+ # to +to_sym+. This includes the keys from the root hash and from all
138
+ # nested hashes.
139
+ def deep_symbolize_keys!
140
+ deep_transform_keys! { |key| key.to_sym rescue key }
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,19 @@
1
+ module Buff
2
+ module Extensions
3
+ module ReverseMerge
4
+ # @param [Hash] other
5
+ #
6
+ # @return [Hash]
7
+ def reverse_merge(other)
8
+ other.merge(self)
9
+ end
10
+
11
+ # @param [Hash] other
12
+ #
13
+ # @return [Hash]
14
+ def reverse_merge!(other)
15
+ merge!(other) { |key, old, new| old }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'hash/dotted_paths'
2
+ require_relative 'hash/key_transforms'
3
+ require_relative 'hash/reverse_merge'
4
+
5
+ class Hash
6
+ include Buff::Extensions::DottedPaths
7
+ include Buff::Extensions::KeyTransforms
8
+ include Buff::Extensions::ReverseMerge
9
+ end
@@ -0,0 +1,106 @@
1
+ # Borrowed and modified from
2
+ # {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/blank.rb}
3
+
4
+ class Object
5
+ # An object is blank if it's false, empty, or a whitespace string.
6
+ # For example, '', ' ', +nil+, [], and {} are all blank.
7
+ #
8
+ # This simplifies:
9
+ #
10
+ # if address.nil? || address.empty?
11
+ #
12
+ # ...to:
13
+ #
14
+ # if address.blank?
15
+ def blank?
16
+ respond_to?(:empty?) ? empty? : !self
17
+ end
18
+
19
+ # An object is present if it's not <tt>blank?</tt>.
20
+ def present?
21
+ !blank?
22
+ end
23
+
24
+ # Returns object if it's <tt>present?</tt> otherwise returns +nil+.
25
+ # <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
26
+ #
27
+ # This is handy for any representation of objects where blank is the same
28
+ # as not present at all. For example, this simplifies a common check for
29
+ # HTTP POST/query parameters:
30
+ #
31
+ # state = params[:state] if params[:state].present?
32
+ # country = params[:country] if params[:country].present?
33
+ # region = state || country || 'US'
34
+ #
35
+ # ...becomes:
36
+ #
37
+ # region = params[:state].presence || params[:country].presence || 'US'
38
+ def presence
39
+ self if present?
40
+ end
41
+ end
42
+
43
+ class NilClass
44
+ # +nil+ is blank:
45
+ #
46
+ # nil.blank? # => true
47
+ def blank?
48
+ true
49
+ end
50
+ end
51
+
52
+ class FalseClass
53
+ # +false+ is blank:
54
+ #
55
+ # false.blank? # => true
56
+ def blank?
57
+ true
58
+ end
59
+ end
60
+
61
+ class TrueClass
62
+ # +true+ is not blank:
63
+ #
64
+ # true.blank? # => false
65
+ def blank?
66
+ false
67
+ end
68
+ end
69
+
70
+ class Array
71
+ # An array is blank if it's empty:
72
+ #
73
+ # [].blank? # => true
74
+ # [1,2,3].blank? # => false
75
+ alias_method :blank?, :empty?
76
+ end
77
+
78
+ class Hash
79
+ # A hash is blank if it's empty:
80
+ #
81
+ # {}.blank? # => true
82
+ # { key: 'value' }.blank? # => false
83
+ alias_method :blank?, :empty?
84
+ end
85
+
86
+ class String
87
+ # A string is blank if it's empty or contains whitespaces only:
88
+ #
89
+ # ''.blank? # => true
90
+ # ' '.blank? # => true
91
+ # ' '.blank? # => true
92
+ # ' something here '.blank? # => false
93
+ def blank?
94
+ self !~ /[^[:space:]]/
95
+ end
96
+ end
97
+
98
+ class Numeric #:nodoc:
99
+ # No number is blank:
100
+ #
101
+ # 1.blank? # => false
102
+ # 0.blank? # => false
103
+ def blank?
104
+ false
105
+ end
106
+ end
@@ -0,0 +1 @@
1
+ require_relative 'object/blank'
@@ -0,0 +1,5 @@
1
+ module Buff
2
+ module Extensions
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ module Buff
2
+ module Extensions
3
+ require_relative 'extensions/version'
4
+ end
5
+ end
6
+
7
+ require_relative 'extensions/boolean'
8
+ require_relative 'extensions/hash'
9
+ require_relative 'extensions/object'
@@ -0,0 +1 @@
1
+ require_relative 'buff/extensions'
@@ -0,0 +1,151 @@
1
+ require 'spec_helper'
2
+
3
+ describe Buff::Extensions::DottedPaths do
4
+ describe "ClassMethods" do
5
+ subject { Hash }
6
+
7
+ describe "::from_dotted_path" do
8
+ it "returns a new Hash" do
9
+ expect(subject.from_dotted_path("deep.nested.item")).to be_a(Hash)
10
+ end
11
+
12
+ it "returns a hash containing the nested keys" do
13
+ obj = subject.from_dotted_path("deep.nested.item")
14
+
15
+ expect(obj).to have_key("deep")
16
+ expect(obj["deep"]).to have_key("nested")
17
+ expect(obj["deep"]["nested"]).to have_key("item")
18
+ end
19
+
20
+ it "sets a nil value for the deepest nested item" do
21
+ obj = subject.from_dotted_path("deep.nested.item")
22
+
23
+ expect(obj["deep"]["nested"]["item"]).to be_nil
24
+ end
25
+
26
+ it "handles a symbol as the dotted path" do
27
+ obj = subject.from_dotted_path(:"a.b.c", "value")
28
+
29
+ expect(obj["a"]["b"]["c"]).to eql("value")
30
+ end
31
+
32
+ context "when given a seed value" do
33
+ it "sets the value of the deepest nested item to the seed" do
34
+ obj = subject.from_dotted_path("deep.nested.item", "seeded_value")
35
+
36
+ expect(obj["deep"]["nested"]["item"]).to eql("seeded_value")
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ subject { Hash.new }
43
+
44
+ describe "#dig" do
45
+ context "when the Hash contains the nested path" do
46
+ subject do
47
+ {
48
+ "we" => {
49
+ "found" => {
50
+ "something" => true
51
+ }
52
+ }
53
+ }
54
+ end
55
+
56
+ it "returns the value at the dotted path" do
57
+ expect(subject.dig("we.found.something")).to eql(true)
58
+ end
59
+ end
60
+
61
+ context "when the Hash does not contain the nested path" do
62
+ it "returns a nil value" do
63
+ expect(subject.dig("nothing.is.here")).to be_nil
64
+ end
65
+ end
66
+
67
+ context "when the Hash contains symbols for keys" do
68
+ subject do
69
+ {
70
+ we: {
71
+ found: {
72
+ something: :symbol_value
73
+ }
74
+ }
75
+ }
76
+ end
77
+
78
+ it "returns the value at the dotted path" do
79
+ expect(subject.dig("we.found.something")).to eql(:symbol_value)
80
+ end
81
+ end
82
+
83
+ it "returns nil if given a blank string" do
84
+ expect(subject.dig("")).to be_nil
85
+ end
86
+
87
+ it "returns 'false' nested values as 'false' and not 'nil'" do
88
+ hash = {
89
+ "ssl" => {
90
+ "verify" => false
91
+ }
92
+ }
93
+
94
+ expect(hash.dig('ssl.verify')).to eql(false)
95
+ end
96
+ end
97
+
98
+ describe "#dotted_paths" do
99
+ it "returns an array" do
100
+ expect(subject.dotted_paths).to be_a(Array)
101
+ end
102
+
103
+ context "given a hash with only top level keys" do
104
+ subject do
105
+ {
106
+ "one" => "val",
107
+ "two" => "val"
108
+ }
109
+ end
110
+
111
+ it "returns an array of the top level keys as strings" do
112
+ expect(subject.dotted_paths).to eql(["one", "two"])
113
+ end
114
+ end
115
+
116
+ context "given a hash with empty hashes as values" do
117
+ subject do
118
+ {
119
+ "one" => Hash.new,
120
+ "two" => Hash.new
121
+ }
122
+ end
123
+
124
+ it "returns an array of the top level keys as strings" do
125
+ expect(subject.dotted_paths).to eql(["one", "two"])
126
+ end
127
+ end
128
+
129
+ context "given a hash with nested keys" do
130
+ subject do
131
+ {
132
+ "one" => {
133
+ "nested" => {
134
+ "attribute" => "hello"
135
+ }
136
+ },
137
+ "two" => {
138
+ "nested" => {
139
+ "attribute" => "other_hello",
140
+ "other_attr" => "world"
141
+ }
142
+ }
143
+ }
144
+ end
145
+
146
+ it "returns an array of dotted paths including the nested Hash keys" do
147
+ expect(subject.dotted_paths).to eql(["one.nested.attribute", "two.nested.attribute", "two.nested.other_attr"])
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,27 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rspec'
4
+ require 'buff/ruby_engine'
5
+
6
+ def setup_rspec
7
+ RSpec.configure do |config|
8
+ config.expect_with :rspec do |c|
9
+ c.syntax = :expect
10
+ end
11
+
12
+ config.mock_with :rspec
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.filter_run focus: true
15
+ config.run_all_when_everything_filtered = true
16
+ end
17
+ end
18
+
19
+ if Buff::RubyEngine.jruby?
20
+ require 'buff/extensions'
21
+ setup_rspec
22
+ else
23
+ require 'spork'
24
+
25
+ Spork.prefork { setup_rspec }
26
+ Spork.each_run { require 'buff/extensions' }
27
+ end
metadata ADDED
@@ -0,0 +1,233 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: buff-extensions
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jamie Winsor
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: buff-ruby_engine
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.1'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.1'
30
+ - !ruby/object:Gem::Dependency
31
+ name: thor
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.18.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.18.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: bundler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.3'
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: '1.3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
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: rspec
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: fuubar
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: guard
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: guard-rspec
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: guard-spork
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: spork
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ description: Extensions to Core Ruby classes
175
+ email:
176
+ - reset@riotgames.com
177
+ executables: []
178
+ extensions: []
179
+ extra_rdoc_files: []
180
+ files:
181
+ - .gitignore
182
+ - .ruby-version
183
+ - .travis.yml
184
+ - CONTRIBUTING.md
185
+ - Gemfile
186
+ - Guardfile
187
+ - LICENSE
188
+ - README.md
189
+ - Thorfile
190
+ - buff-extensions.gemspec
191
+ - lib/buff-extensions.rb
192
+ - lib/buff/extensions.rb
193
+ - lib/buff/extensions/boolean.rb
194
+ - lib/buff/extensions/hash.rb
195
+ - lib/buff/extensions/hash/dotted_paths.rb
196
+ - lib/buff/extensions/hash/key_transforms.rb
197
+ - lib/buff/extensions/hash/reverse_merge.rb
198
+ - lib/buff/extensions/object.rb
199
+ - lib/buff/extensions/object/blank.rb
200
+ - lib/buff/extensions/version.rb
201
+ - spec/buff/extensions/hash/dotted_paths_spec.rb
202
+ - spec/spec_helper.rb
203
+ homepage: https://github.com/RiotGames/buff-extensions
204
+ licenses:
205
+ - Apache 2.0
206
+ post_install_message:
207
+ rdoc_options: []
208
+ require_paths:
209
+ - lib
210
+ required_ruby_version: !ruby/object:Gem::Requirement
211
+ none: false
212
+ requirements:
213
+ - - ! '>='
214
+ - !ruby/object:Gem::Version
215
+ version: 1.9.2
216
+ required_rubygems_version: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ segments:
223
+ - 0
224
+ hash: -4518863559578760213
225
+ requirements: []
226
+ rubyforge_project:
227
+ rubygems_version: 1.8.23
228
+ signing_key:
229
+ specification_version: 3
230
+ summary: Extensions to Core Ruby classes
231
+ test_files:
232
+ - spec/buff/extensions/hash/dotted_paths_spec.rb
233
+ - spec/spec_helper.rb