buff-extensions-1.0.0/0000755000175000017500000000000012365021511014151 5ustar miguelmiguelbuff-extensions-1.0.0/spec/0000755000175000017500000000000012365021511015103 5ustar miguelmiguelbuff-extensions-1.0.0/spec/buff/0000755000175000017500000000000012365021511016025 5ustar miguelmiguelbuff-extensions-1.0.0/spec/buff/extensions/0000755000175000017500000000000012365021511020224 5ustar miguelmiguelbuff-extensions-1.0.0/spec/buff/extensions/hash/0000755000175000017500000000000012365021511021147 5ustar miguelmiguelbuff-extensions-1.0.0/spec/buff/extensions/hash/dotted_paths_spec.rb0000644000175000017500000000723112365021511025173 0ustar miguelmiguelrequire 'spec_helper' describe Buff::Extensions::Hash::DottedPaths do describe "ClassMethods" do subject { Hash } describe "::from_dotted_path" do it "returns a new Hash" do expect(subject.from_dotted_path("deep.nested.item")).to be_a(Hash) end it "returns a hash containing the nested keys" do obj = subject.from_dotted_path("deep.nested.item") expect(obj).to have_key("deep") expect(obj["deep"]).to have_key("nested") expect(obj["deep"]["nested"]).to have_key("item") end it "sets a nil value for the deepest nested item" do obj = subject.from_dotted_path("deep.nested.item") expect(obj["deep"]["nested"]["item"]).to be_nil end it "handles a symbol as the dotted path" do obj = subject.from_dotted_path(:"a.b.c", "value") expect(obj["a"]["b"]["c"]).to eql("value") end context "when given a seed value" do it "sets the value of the deepest nested item to the seed" do obj = subject.from_dotted_path("deep.nested.item", "seeded_value") expect(obj["deep"]["nested"]["item"]).to eql("seeded_value") end end end end subject { Hash.new } describe "#dig" do context "when the Hash contains the nested path" do subject do { "we" => { "found" => { "something" => true } } } end it "returns the value at the dotted path" do expect(subject.dig("we.found.something")).to eql(true) end end context "when the Hash does not contain the nested path" do it "returns a nil value" do expect(subject.dig("nothing.is.here")).to be_nil end end context "when the Hash contains symbols for keys" do subject do { we: { found: { something: :symbol_value } } } end it "returns the value at the dotted path" do expect(subject.dig("we.found.something")).to eql(:symbol_value) end end it "returns nil if given a blank string" do expect(subject.dig("")).to be_nil end it "returns 'false' nested values as 'false' and not 'nil'" do hash = { "ssl" => { "verify" => false } } expect(hash.dig('ssl.verify')).to eql(false) end end describe "#dotted_paths" do it "returns an array" do expect(subject.dotted_paths).to be_a(Array) end context "given a hash with only top level keys" do subject do { "one" => "val", "two" => "val" } end it "returns an array of the top level keys as strings" do expect(subject.dotted_paths).to eql(["one", "two"]) end end context "given a hash with empty hashes as values" do subject do { "one" => Hash.new, "two" => Hash.new } end it "returns an array of the top level keys as strings" do expect(subject.dotted_paths).to eql(["one", "two"]) end end context "given a hash with nested keys" do subject do { "one" => { "nested" => { "attribute" => "hello" } }, "two" => { "nested" => { "attribute" => "other_hello", "other_attr" => "world" } } } end it "returns an array of dotted paths including the nested Hash keys" do expect(subject.dotted_paths).to eql(["one.nested.attribute", "two.nested.attribute", "two.nested.other_attr"]) end end end end buff-extensions-1.0.0/spec/spec_helper.rb0000644000175000017500000000111312365021511017715 0ustar miguelmiguel$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) require 'rspec' require 'buff/ruby_engine' def setup_rspec RSpec.configure do |config| config.expect_with :rspec do |c| c.syntax = :expect end config.mock_with :rspec config.treat_symbols_as_metadata_keys_with_true_values = true config.filter_run focus: true config.run_all_when_everything_filtered = true end end if Buff::RubyEngine.jruby? require 'buff/extensions' setup_rspec else require 'spork' Spork.prefork { setup_rspec } Spork.each_run { require 'buff/extensions' } end buff-extensions-1.0.0/.gitignore0000644000175000017500000000023212365021511016136 0ustar miguelmiguel*.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp buff-extensions-1.0.0/buff-extensions.gemspec0000644000175000017500000000242112365021511020634 0ustar miguelmiguel# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'buff/extensions/version' Gem::Specification.new do |spec| spec.name = "buff-extensions" spec.version = Buff::Extensions::VERSION spec.authors = ["Jamie Winsor"] spec.email = ["jamie@vialstudios.com"] spec.description = %q{Extensions to Core Ruby classes} spec.summary = spec.description spec.homepage = "https://github.com/RiotGames/buff-extensions" spec.license = "Apache 2.0" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^spec/}) spec.require_paths = ["lib"] spec.required_ruby_version = ">= 1.9.2" spec.add_development_dependency "buff-ruby_engine", "~> 0.1" spec.add_development_dependency "thor", "~> 0.18.0" spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" spec.add_development_dependency "rspec" spec.add_development_dependency "fuubar" spec.add_development_dependency "guard" spec.add_development_dependency "guard-rspec" spec.add_development_dependency "guard-spork" spec.add_development_dependency "spork" end buff-extensions-1.0.0/CONTRIBUTING.md0000644000175000017500000000067512365021511016412 0ustar miguelmiguel# Contributing ## Running tests ### Install prerequisites Install the latest version of [Bundler](http://gembundler.com) $ gem install bundler Clone the project $ git clone git://github.com/RiotGames/buff-extensions.git and run: $ cd buff-extensions $ bundle install Bundler will install all gems and their dependencies required for testing and developing. ### Running unit (RSpec) tests $ bundle exec guard start buff-extensions-1.0.0/.ruby-version0000644000175000017500000000001412365021511016611 0ustar miguelmiguel2.0.0-p353 buff-extensions-1.0.0/LICENSE0000644000175000017500000000113012365021511015151 0ustar miguelmiguelCopyright 2012-2013 Riot Games Jamie Winsor () Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. buff-extensions-1.0.0/.travis.yml0000644000175000017500000000013112365021511016255 0ustar miguelmiguelscript: "bundle exec thor spec" language: ruby rvm: - 1.9.3 - 2.0.0 - jruby-19mode buff-extensions-1.0.0/README.md0000644000175000017500000000145012365021511015430 0ustar miguelmiguel# Buff::Extensions [![Gem Version](https://badge.fury.io/rb/buff-extensions.png)](http://badge.fury.io/rb/buff-extensions) [![Build Status](https://travis-ci.org/RiotGames/buff-extensions.png?branch=master)](https://travis-ci.org/RiotGames/buff-extensions) Extensions to Core Ruby classes ## Installation Add this line to your application's Gemfile: gem 'buff-extensions' And then execute: $ bundle Or install it yourself as: $ gem install buff-extensions ## Usage Using it as a mixin require 'buff/extensions' class PowerHash include Buff::Extensions::DottedPaths end # Authors and Contributors * Jamie Winsor () Thank you to all of our [Contributors](https://github.com/RiotGames/buff-extensions/graphs/contributors), testers, and users. buff-extensions-1.0.0/Gemfile0000644000175000017500000000004712365021511015445 0ustar miguelmiguelsource 'https://rubygems.org' gemspec buff-extensions-1.0.0/checksums.yaml.gz0000444000175000017500000000041412365021511017436 0ustar miguelmiguelRe;R0=^`egg +g+OoV;-n >_׏G=޿ ʒlBsNe텭tP#ZCY*9, Ac>\?_ [0tcUU ,HD6Vf̅$C4[D:IG̹Z#{/Z2{5M -IãrL\(r#XjMkxϓɩ 1i>j-M<Ύo|3buff-extensions-1.0.0/Thorfile0000644000175000017500000000204512365021511015651 0ustar miguelmiguel# encoding: utf-8 $:.push File.expand_path("../lib", __FILE__) require 'bundler' require 'bundler/setup' require 'buff/ruby_engine' require 'buff/extensions/version' class Default < Thor extend Buff::RubyEngine unless jruby? require 'thor/rake_compat' include Thor::RakeCompat Bundler::GemHelper.install_tasks desc "build", "Build buff-extensions-#{Buff::Extensions::VERSION}.gem into the pkg directory" def build Rake::Task["build"].execute end desc "install", "Build and install buff-extensions-#{Buff::Extensions::VERSION}.gem into system gems" def install Rake::Task["install"].execute end desc "release", "Create tag v#{Buff::Extensions::VERSION} and build and push buff-extensions-#{Buff::Extensions::VERSION}.gem to Rubygems" def release Rake::Task["release"].execute end end class Spec < Thor namespace :spec default_task :unit desc "unit", "run the project's unit tests" def unit exec "rspec --color --format=documentation spec" end end end buff-extensions-1.0.0/lib/0000755000175000017500000000000012365021511014717 5ustar miguelmiguelbuff-extensions-1.0.0/lib/buff/0000755000175000017500000000000012365021511015641 5ustar miguelmiguelbuff-extensions-1.0.0/lib/buff/extensions.rb0000644000175000017500000000041512365021511020365 0ustar miguelmiguelmodule Buff module Extensions require_relative 'extensions/version' end end require_relative 'extensions/boolean' require_relative 'extensions/hash' require_relative 'extensions/kernel' require_relative 'extensions/object' require_relative 'extensions/string' buff-extensions-1.0.0/lib/buff/extensions/0000755000175000017500000000000012365021511020040 5ustar miguelmiguelbuff-extensions-1.0.0/lib/buff/extensions/version.rb0000644000175000017500000000010012365021511022041 0ustar miguelmiguelmodule Buff module Extensions VERSION = "1.0.0" end end buff-extensions-1.0.0/lib/buff/extensions/hash/0000755000175000017500000000000012365021511020763 5ustar miguelmiguelbuff-extensions-1.0.0/lib/buff/extensions/hash/except.rb0000644000175000017500000000127212365021511022602 0ustar miguelmiguelmodule Buff module Extensions::Hash # Borrowd and modified from # {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/except.rb} module Except # Return a hash that includes everything but the given keys. This is useful for # limiting a set of parameters to everything but a few known toggles: # # @person.update(params[:person].except(:admin)) def except(*keys) dup.except!(*keys) end # Replaces the hash without the given keys. def except!(*keys) keys.each { |key| delete(key) } self end end end end class Hash include Buff::Extensions::Hash::Except end buff-extensions-1.0.0/lib/buff/extensions/hash/reverse_merge.rb0000644000175000017500000000064112365021511024143 0ustar miguelmiguelmodule Buff module Extensions::Hash module ReverseMerge # @param [Hash] other # # @return [Hash] def reverse_merge(other) other.merge(self) end # @param [Hash] other # # @return [Hash] def reverse_merge!(other) merge!(other) { |key, old, new| old } end end end end class Hash include Buff::Extensions::Hash::ReverseMerge end buff-extensions-1.0.0/lib/buff/extensions/hash/dotted_paths.rb0000644000175000017500000000666712365021511024011 0ustar miguelmiguelmodule Buff module Extensions::Hash module DottedPaths class << self def included(base) base.send(:extend, ClassMethods) end end module ClassMethods # Create a new Hash containing other nested Hashes from a string containing # a dotted path. A Hash will be created and assigned to a key of another Hash # for each entry in the dotted path. # # If a value is provided for the optional seed argument then the value of the # deepest nested key will be set to the given value. If no value is provided # the value of the key will be nil. # # @example creating a nested hash from a dotted path # # Hash.from_dotted_path("deep.nested.hash") => # { # "deep" => { # "nested" => { # "hash" => nil # } # } # } # # # @example specifying a seed value # # Hash.from_dotted_path("deep.nested.hash", :seed_value) => # { # "deep" => { # "nested" => { # "hash" => :seed_value # } # } # } # # @param [String, Symbol, Array] dotpath # @param [Object] seed (nil) # @param [Hash] target (self.new) # # @return [Hash] def from_dotted_path(dotpath, seed = nil, target = self.new) case dotpath when String, Symbol from_dotted_path(dotpath.to_s.split("."), seed) when Array if dotpath.empty? return target end key = dotpath.pop if target.empty? target[key] = seed from_dotted_path(dotpath, seed, target) else new_target = self.new new_target[key] = target from_dotted_path(dotpath, seed, new_target) end end end end # Return the value of the nested hash key from the given dotted path # # @example # # nested_hash = { # "deep" => { # "nested" => { # "hash" => :seed_value # } # } # } # # nested_hash.dig('deep.nested.hash') => :seed_value # # @param [String] path # # @return [Object, nil] def dig(path) return nil unless path.present? parts = path.split('.', 2) match = self[parts[0].to_s].nil? ? self[parts[0].to_sym] : self[parts[0].to_s] if !parts[1] or match.nil? match else match.dig(parts[1]) end end # Returns an array of dotted paths from the keys, values of this Hash. Values which are # nested Hashes will also recurred into and their paths will be added properly. # # @param [Hash] source # @param [Array] acc # @param [Array] namespace # # @return [Array] def dotted_paths(source = self, acc = Array.new, namespace = Array.new) if source.is_a?(Hash) && !source.empty? source.each do |key, value| branch = namespace.dup branch << key dotted_paths(value, acc, branch) end else acc << namespace.join('.') end acc end end end end class Hash include Buff::Extensions::Hash::DottedPaths end buff-extensions-1.0.0/lib/buff/extensions/hash/slice.rb0000644000175000017500000000337512365021511022417 0ustar miguelmiguelmodule Buff module Extensions::Hash # Borrowd and modified from # {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/slice.rb} module Slice # Slice a hash to include only the given keys. This is useful for # limiting an options hash to valid keys before passing to a method: # # def search(criteria = {}) # criteria.assert_valid_keys(:mass, :velocity, :time) # end # # search(options.slice(:mass, :velocity, :time)) # # If you have an array of keys you want to limit to, you should splat them: # # valid_keys = [:mass, :velocity, :time] # search(options.slice(*valid_keys)) def slice(*keys) keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true) keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) } end # Replaces the hash with only the given keys. # Returns a hash containing the removed key/value pairs. # # { a: 1, b: 2, c: 3, d: 4 }.slice!(:a, :b) # # => {:c=>3, :d=>4} def slice!(*keys) keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true) omit = slice(*self.keys - keys) hash = slice(*keys) replace(hash) omit end # Removes and returns the key/value pairs matching the given keys. # # { a: 1, b: 2, c: 3, d: 4 }.extract!(:a, :b) # => {:a=>1, :b=>2} # { a: 1, b: 2 }.extract!(:a, :x) # => {:a=>1} def extract!(*keys) keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) } end end end end class Hash include Buff::Extensions::Hash::Slice end buff-extensions-1.0.0/lib/buff/extensions/hash/key_transforms.rb0000644000175000017500000001205512365021511024361 0ustar miguelmiguelmodule Buff module Extensions::Hash # Borrowd and modified from # {https://raw.github.com/rails/rails/master/activesupport/lib/active_support/core_ext/hash/keys.rb} module KeyTransforms # Return a new hash with all keys converted using the block operation. # # hash = { name: 'Rob', age: '28' } # # hash.transform_keys{ |key| key.to_s.upcase } # # => { "NAME" => "Rob", "AGE" => "28" } def transform_keys result = {} each_key do |key| result[yield(key)] = self[key] end result end # Destructively convert all keys using the block operations. # Same as transform_keys but modifies +self+. def transform_keys! keys.each do |key| self[yield(key)] = delete(key) end self end # Return a new hash with all keys converted to strings. # # hash = { name: 'Rob', age: '28' } # # hash.stringify_keys # #=> { "name" => "Rob", "age" => "28" } def stringify_keys transform_keys { |key| key.to_s } end # Destructively convert all keys to strings. Same as # +stringify_keys+, but modifies +self+. def stringify_keys! transform_keys! { |key| key.to_s } end # Return a new hash with all keys converted to symbols, as long as # they respond to +to_sym+. # # hash = { 'name' => 'Rob', 'age' => '28' } # # hash.symbolize_keys # #=> { name: "Rob", age: "28" } def symbolize_keys transform_keys { |key| key.to_sym rescue key } end alias_method :to_options, :symbolize_keys # Destructively convert all keys to symbols, as long as they respond # to +to_sym+. Same as +symbolize_keys+, but modifies +self+. def symbolize_keys! transform_keys! { |key| key.to_sym rescue key } end alias_method :to_options!, :symbolize_keys! # Validate all keys in a hash match *valid_keys, raising ArgumentError # on a mismatch. Note that keys are NOT treated indifferently, meaning if you # use strings for keys but assert symbols as keys, this will fail. # # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years" # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: name" # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing def assert_valid_keys(*valid_keys) valid_keys.flatten! each_key do |k| raise ArgumentError.new("Unknown key: #{k}") unless valid_keys.include?(k) end end # Return a new hash with all keys converted by the block operation. # This includes the keys from the root hash and from all # nested hashes. # # hash = { person: { name: 'Rob', age: '28' } } # # hash.deep_transform_keys{ |key| key.to_s.upcase } # # => { "PERSON" => { "NAME" => "Rob", "AGE" => "28" } } def deep_transform_keys(&block) result = {} each do |key, value| result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value end result end # Destructively convert all keys by using the block operation. # This includes the keys from the root hash and from all # nested hashes. def deep_transform_keys!(&block) keys.each do |key| value = delete(key) self[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys!(&block) : value end self end # Return a new hash with all keys converted to strings. # This includes the keys from the root hash and from all # nested hashes. # # hash = { person: { name: 'Rob', age: '28' } } # # hash.deep_stringify_keys # # => { "person" => { "name" => "Rob", "age" => "28" } } def deep_stringify_keys deep_transform_keys { |key| key.to_s } end # Destructively convert all keys to strings. # This includes the keys from the root hash and from all # nested hashes. def deep_stringify_keys! deep_transform_keys! { |key| key.to_s } end # Return a new hash with all keys converted to symbols, as long as # they respond to +to_sym+. This includes the keys from the root hash # and from all nested hashes. # # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } } # # hash.deep_symbolize_keys # # => { person: { name: "Rob", age: "28" } } def deep_symbolize_keys deep_transform_keys { |key| key.to_sym rescue key } end # Destructively convert all keys to symbols, as long as they respond # to +to_sym+. This includes the keys from the root hash and from all # nested hashes. def deep_symbolize_keys! deep_transform_keys! { |key| key.to_sym rescue key } end end end end class Hash include Buff::Extensions::Hash::KeyTransforms end buff-extensions-1.0.0/lib/buff/extensions/hash.rb0000644000175000017500000000025712365021511021314 0ustar miguelmiguelrequire_relative 'hash/dotted_paths' require_relative 'hash/except' require_relative 'hash/key_transforms' require_relative 'hash/reverse_merge' require_relative 'hash/slice' buff-extensions-1.0.0/lib/buff/extensions/object.rb0000644000175000017500000000007612365021511021636 0ustar miguelmiguelrequire_relative 'object/blank' require_relative 'object/try' buff-extensions-1.0.0/lib/buff/extensions/kernel/0000755000175000017500000000000012365021511021320 5ustar miguelmiguelbuff-extensions-1.0.0/lib/buff/extensions/kernel/reporting.rb0000644000175000017500000000635212365021511023664 0ustar miguelmiguelrequire 'rbconfig' require 'tempfile' module Buff module Extensions::Kernel # Borrowd and modified from # {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/kernel/reporting.rb} module Reporting # Sets $VERBOSE to nil for the duration of the block and back to its original # value afterwards. # # silence_warnings do # value = noisy_call # no warning voiced # end # # noisy_call # warning voiced def silence_warnings with_warnings(nil) { yield } end # Sets $VERBOSE to +true+ for the duration of the block and back to its # original value afterwards. def enable_warnings with_warnings(true) { yield } end # Sets $VERBOSE for the duration of the block and back to its original # value afterwards. def with_warnings(flag) old_verbose, $VERBOSE = $VERBOSE, flag yield ensure $VERBOSE = old_verbose end # For compatibility def silence_stderr #:nodoc: silence_stream(STDERR) { yield } end # Silences any stream for the duration of the block. # # silence_stream(STDOUT) do # puts 'This will never be seen' # end # # puts 'But this will' def silence_stream(stream) old_stream = stream.dup stream.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null') stream.sync = true yield ensure stream.reopen(old_stream) end # Blocks and ignores any exception passed as argument if raised within the block. # # suppress(ZeroDivisionError) do # 1/0 # puts 'This code is NOT reached' # end # # puts 'This code gets executed and nothing related to ZeroDivisionError was seen' def suppress(*exception_classes) yield rescue Exception => e raise unless exception_classes.any? { |cls| e.kind_of?(cls) } end # Captures the given stream and returns it: # # stream = capture(:stdout) { puts 'notice' } # stream # => "notice\n" # # stream = capture(:stderr) { warn 'error' } # stream # => "error\n" # # even for subprocesses: # # stream = capture(:stdout) { system('echo notice') } # stream # => "notice\n" # # stream = capture(:stderr) { system('echo error 1>&2') } # stream # => "error\n" def capture(stream) stream = stream.to_s captured_stream = Tempfile.new(stream) stream_io = eval("$#{stream}") origin_stream = stream_io.dup stream_io.reopen(captured_stream) yield stream_io.rewind return captured_stream.read ensure captured_stream.unlink stream_io.reopen(origin_stream) end alias :silence :capture # Silences both STDOUT and STDERR, even for subprocesses. # # quietly { system 'bundle install' } def quietly silence_stream(STDOUT) do silence_stream(STDERR) do yield end end end end end end module Kernel include Buff::Extensions::Kernel::Reporting end buff-extensions-1.0.0/lib/buff/extensions/object/0000755000175000017500000000000012365021511021306 5ustar miguelmiguelbuff-extensions-1.0.0/lib/buff/extensions/object/try.rb0000644000175000017500000000435112365021511022454 0ustar miguelmiguel# Borrowed and modified from # {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/try.rb} class Object # Invokes the public method whose name goes as first argument just like # +public_send+ does, except that if the receiver does not respond to it the # call returns +nil+ rather than raising an exception. # # This method is defined to be able to write # # @person.try(:name) # # instead of # # @person ? @person.name : nil # # +try+ returns +nil+ when called on +nil+ regardless of whether it responds # to the method: # # nil.try(:to_i) # => nil, rather than 0 # # Arguments and blocks are forwarded to the method if invoked: # # @posts.try(:each_slice, 2) do |a, b| # ... # end # # The number of arguments in the signature must match. If the object responds # to the method the call is attempted and +ArgumentError+ is still raised # otherwise. # # If +try+ is called without arguments it yields the receiver to a given # block unless it is +nil+: # # @person.try do |p| # ... # end # # Please also note that +try+ is defined on +Object+, therefore it won't work # with instances of classes that do not have +Object+ among their ancestors, # like direct subclasses of +BasicObject+. For example, using +try+ with # +SimpleDelegator+ will delegate +try+ to the target instead of calling it on # delegator itself. def try(*a, &b) if a.empty? && block_given? yield self else public_send(*a, &b) if respond_to?(a.first) end end # Same as #try, but will raise a NoMethodError exception if the receiving is not nil and # does not implemented the tried method. def try!(*a, &b) if a.empty? && block_given? yield self else public_send(*a, &b) end end end class NilClass # Calling +try+ on +nil+ always returns +nil+. # It becomes specially helpful when navigating through associations that may return +nil+. # # nil.try(:name) # => nil # # Without +try+ # @person && !@person.children.blank? && @person.children.first.name # # With +try+ # @person.try(:children).try(:first).try(:name) def try(*args) nil end def try!(*args) nil end end buff-extensions-1.0.0/lib/buff/extensions/object/blank.rb0000644000175000017500000000434112365021511022724 0ustar miguelmiguel# Borrowed and modified from # {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/blank.rb} class Object # An object is blank if it's false, empty, or a whitespace string. # For example, '', ' ', +nil+, [], and {} are all blank. # # This simplifies: # # if address.nil? || address.empty? # # ...to: # # if address.blank? def blank? respond_to?(:empty?) ? empty? : !self end # An object is present if it's not blank?. def present? !blank? end # Returns object if it's present? otherwise returns +nil+. # object.presence is equivalent to object.present? ? object : nil. # # This is handy for any representation of objects where blank is the same # as not present at all. For example, this simplifies a common check for # HTTP POST/query parameters: # # state = params[:state] if params[:state].present? # country = params[:country] if params[:country].present? # region = state || country || 'US' # # ...becomes: # # region = params[:state].presence || params[:country].presence || 'US' def presence self if present? end end class NilClass # +nil+ is blank: # # nil.blank? # => true def blank? true end end class FalseClass # +false+ is blank: # # false.blank? # => true def blank? true end end class TrueClass # +true+ is not blank: # # true.blank? # => false def blank? false end end class Array # An array is blank if it's empty: # # [].blank? # => true # [1,2,3].blank? # => false alias_method :blank?, :empty? end class Hash # A hash is blank if it's empty: # # {}.blank? # => true # { key: 'value' }.blank? # => false alias_method :blank?, :empty? end class String # A string is blank if it's empty or contains whitespaces only: # # ''.blank? # => true # ' '.blank? # => true # ' '.blank? # => true # ' something here '.blank? # => false def blank? self !~ /[^[:space:]]/ end end class Numeric #:nodoc: # No number is blank: # # 1.blank? # => false # 0.blank? # => false def blank? false end end buff-extensions-1.0.0/lib/buff/extensions/string/0000755000175000017500000000000012365021511021346 5ustar miguelmiguelbuff-extensions-1.0.0/lib/buff/extensions/string/inflections.rb0000644000175000017500000000075712365021511024221 0ustar miguelmiguelmodule Buff module Extensions::String module Inflections def underscore word = self.dup word.gsub!('::', '/') word.gsub!(/(?:([A-Za-z\d])|^)((?=a)b)(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" } word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2') word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') word.tr!("-", "_") word.downcase! word end end end end class String include Buff::Extensions::String::Inflections end buff-extensions-1.0.0/lib/buff/extensions/string.rb0000644000175000017500000000004612365021511021673 0ustar miguelmiguelrequire_relative 'string/inflections' buff-extensions-1.0.0/lib/buff/extensions/kernel.rb0000644000175000017500000000017212365021511021645 0ustar miguelmiguelrequire_relative 'kernel/reporting' class Object # Re-include since the Kernel module was altered include Kernel end buff-extensions-1.0.0/lib/buff/extensions/boolean.rb0000644000175000017500000000020112365021511021775 0ustar miguelmiguelmodule Buff module Boolean; end end class TrueClass include Buff::Boolean end class FalseClass include Buff::Boolean end buff-extensions-1.0.0/lib/buff-extensions.rb0000644000175000017500000000004312365021511020360 0ustar miguelmiguelrequire_relative 'buff/extensions' buff-extensions-1.0.0/metadata.yml0000644000175000017500000001247612365021511016466 0ustar miguelmiguel--- !ruby/object:Gem::Specification name: buff-extensions version: !ruby/object:Gem::Version version: 1.0.0 platform: ruby authors: - Jamie Winsor autorequire: bindir: bin cert_chain: [] date: 2014-02-06 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: buff-ruby_engine requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '0.1' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '0.1' - !ruby/object:Gem::Dependency name: thor requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: 0.18.0 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: 0.18.0 - !ruby/object:Gem::Dependency name: bundler requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '1.3' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '1.3' - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rspec requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: fuubar requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: guard requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: guard-rspec requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: guard-spork requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: spork requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' description: Extensions to Core Ruby classes email: - jamie@vialstudios.com executables: [] extensions: [] extra_rdoc_files: [] files: - .gitignore - .ruby-version - .travis.yml - CONTRIBUTING.md - Gemfile - Guardfile - LICENSE - README.md - Thorfile - buff-extensions.gemspec - lib/buff-extensions.rb - lib/buff/extensions.rb - lib/buff/extensions/boolean.rb - lib/buff/extensions/hash.rb - lib/buff/extensions/hash/dotted_paths.rb - lib/buff/extensions/hash/except.rb - lib/buff/extensions/hash/key_transforms.rb - lib/buff/extensions/hash/reverse_merge.rb - lib/buff/extensions/hash/slice.rb - lib/buff/extensions/kernel.rb - lib/buff/extensions/kernel/reporting.rb - lib/buff/extensions/object.rb - lib/buff/extensions/object/blank.rb - lib/buff/extensions/object/try.rb - lib/buff/extensions/string.rb - lib/buff/extensions/string/inflections.rb - lib/buff/extensions/version.rb - spec/buff/extensions/hash/dotted_paths_spec.rb - spec/spec_helper.rb homepage: https://github.com/RiotGames/buff-extensions licenses: - Apache 2.0 metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 1.9.2 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.0.14 signing_key: specification_version: 4 summary: Extensions to Core Ruby classes test_files: - spec/buff/extensions/hash/dotted_paths_spec.rb - spec/spec_helper.rb buff-extensions-1.0.0/Guardfile0000644000175000017500000000070412365021511015777 0ustar miguelmiguelnotification :off guard "spork" do watch('Gemfile') watch('spec/spec_helper.rb') { :rspec } watch(%r{^spec/support/.+\.rb$}) { :rspec } end guard "rspec", cli: "--color --drb --format Fuubar", all_on_start: false, all_after_pass: false do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } watch('spec/spec_helper.rb') { "spec" } watch(%r{^spec/support/.+\.rb$}) { "spec" } end