Permalink
Browse files

Add initial extensions for Hash/Array/String and m method on Object

  • Loading branch information...
1 parent 7193fe8 commit a03ab4ad46280b15de744afc7c1c50c45b2ffcc1 @onsitedev onsitedev committed Oct 27, 2010
View
@@ -0,0 +1,3 @@
+pkg/*
+*.gem
+.bundle
View
@@ -1,4 +1,7 @@
source "http://rubygems.org"
-# Specify your gem's dependencies in libraries.gemspec
gemspec
+
+group :test do
+ gem "rspec"
+end
View
@@ -0,0 +1,26 @@
+PATH
+ remote: .
+ specs:
+ libraries (0.0.1)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ diff-lcs (1.1.2)
+ rspec (2.0.1)
+ rspec-core (~> 2.0.1)
+ rspec-expectations (~> 2.0.1)
+ rspec-mocks (~> 2.0.1)
+ rspec-core (2.0.1)
+ rspec-expectations (2.0.1)
+ diff-lcs (>= 1.1.2)
+ rspec-mocks (2.0.1)
+ rspec-core (~> 2.0.1)
+ rspec-expectations (~> 2.0.1)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ libraries!
+ rspec
View
@@ -1,2 +1,12 @@
require 'bundler'
Bundler::GemHelper.install_tasks
+
+require 'spec/rake/spectask'
+
+task :default => :spec
+
+desc "Run specs"
+Spec::Rake::SpecTask.new do |t|
+ t.spec_files = FileList['spec/**/*_spec.rb']
+ t.spec_opts = %w(-fs --color)
+end
View
@@ -1,3 +1,7 @@
-module Libraries
+require "active_support"
-end
+require "libraries/enumerable"
+require "libraries/array"
+require "libraries/hash"
+require "libraries/string"
+require "libraries/object"
@@ -0,0 +1,42 @@
+module ActiveRecord
+
+ class Base
+ before_save(:_clean_whitespace)
+
+ def _clean_whitespace
+ self.attributes.each_pair do |key, value|
+ if value && value.respond_to?('strip')
+ self[key] = value.strip
+ end
+ end
+ end
+
+ def to_hash(*fields)
+ h = attributes.symbolize_keys
+ fields.present? ? h.slice(*fields.flatten) : h
+ end
+
+ class << self
+ def conditions(*args)
+ scoped :conditions => args
+ end
+
+ def by_date_range(options)
+ scoped :conditions => ["#{options[:date_field]} BETWEEN ? AND ?", options[:start_date].to_s(:db), (options[:end_date] || Date.today).to_s(:db)]
+ end
+
+ def sort_scope(options)
+ scoped :order => "#{options[:attribute]} #{options[:direction]}"
+ end
+
+ def random(_limit=1)
+ scoped :order => "RAND()", :limit => _limit
+ end
+
+ def limit(_limit)
+ scoped :limit => _limit
+ end
+ end
+ end
+
+end
View
@@ -0,0 +1,17 @@
+class Array
+
+ def each_pair
+ self.in_groups_of(2).each { |g| yield g.first, g.last }
+ end
+
+ # delete all passed element and return the array after delete
+ def delete!(*args)
+ self.tap { |a| a.delete_if { |e| args.include? e } }
+ end
+
+ # same as delete! but does not alter self
+ def without(*args)
+ self.dup.tap { |dup| dup.delete!(*args) }
+ end
+
+end
@@ -0,0 +1,15 @@
+module Enumerable
+
+ # Call the given block for each element, creating a new hash
+ # that uses the element as the key and the block's result as the value.
+ def map_into_hash &block
+ # The "reduce(:concat)" does a shallow flatten, so that blocks that
+ # return arrays will do the Right Thing.
+ Hash[*map {|x| [x, block.call(x)]}.inject([], &:concat)]
+ end
+
+ def map_keyvals_into_hash &block
+ Hash[*map(&block).inject([], &:concat)]
+ end
+
+end
View
@@ -0,0 +1,73 @@
+class Hash
+
+ def recursive_symbolize_keys!
+ symbolize_keys!
+ # symbolize each hash in .values
+ values.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash) }
+ # symbolize each hash inside an array in .values
+ values.select{|v| v.is_a?(Array) }.flatten.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash) }
+ self
+ end
+
+ # deep lookup a nested hash without failing on non-existing keys
+ # in which case returns and empty hash
+ # This will only work on NESTED hashes, something like:
+ # h = {:a => {:b => {:c => 3}}}
+ # h.lookup(:a,:b,:c) => 3
+ # h.lookup(:a,:b) => {:c => 3}
+ # h.lookup(:a,:b,:X) => nil
+ # h.lookup(:a,:X,:Y) => nil
+ # h.lookup(:W,:T,:F) => nil
+ def nested_lookup(*keys)
+ keys.inject(self){ |h,k| (h || {}).fetch(k,nil) } rescue nil
+ end
+
+ # Takes a hash argument of old, new pairs
+ # Returns hash with keys renamed
+ def rename_keys!(keys_hash)
+ keys_hash.each do |old, new|
+ self[new] = self.delete(old)
+ end
+ self
+ end
+
+ def rename_keys(keys_hash)
+ self.dup.rename_keys!(keys_hash)
+ end
+
+ # map from a block
+ def map_into_hash(&block)
+ Hash[*map {|x| [x[0], block.call(x)]}.inject([], &:concat)]
+ end
+
+ def parent_to?(*args)
+ return self.slice(*args.first.keys) == args.first if args.size == 1 && args.first.is_a?(Hash)
+ args.each_pair do |key, value|
+ return false unless self[key] == value
+ end
+ true
+ end
+
+ ############################################################
+ # The following methods take as an argument, a list of keys
+ # See the specs for examples
+
+ def all_keys?(*keys)
+ keys.all? {|k| has_key? k}
+ end
+
+ def any_key?(*keys)
+ keys.any? {|k| has_key? k}
+ end
+
+ def all_values?(*keys)
+ keys.all?{|k| self[k].present?}
+ end
+
+ def any_value?(*keys)
+ keys.any?{|k| self[k].present?}
+ end
+
+ ############################################################
+
+end
View
@@ -0,0 +1,9 @@
+class Object
+
+ def m regexp=nil
+ m = (self.methods - Object.methods).sort
+ return m.grep(/#{regexp}/) if regexp
+ m
+ end
+
+end
View
@@ -0,0 +1,32 @@
+class String
+
+ def strip_with_arg_support!(char=nil)
+ if char.present?
+ m = char.each_char.inject('') {|r,c| r+=(c =~ /[\*\.\[\]\^\$\?\\\|\=\+\:\/\(\)]/ ? "\\" : "") + c}
+ self.gsub!(/^[#{m}]*(.*?)[#{m}]*$/,'\1')
+ else
+ strip_without_arg_support!
+ end
+ end
+ alias_method_chain :strip!, :arg_support
+
+ def strip_with_arg_support(char=nil)
+ char.present? ? self.dup.strip!(char) : strip_without_arg_support
+ end
+ alias_method_chain :strip, :arg_support
+
+ # In the sense of normal characters only, it also downcases the string
+ # Can be used, for example, in file names and css classes
+ def normalize!
+ return if normalize.blank?
+ self.gsub!(/[^A-Z0-9]/i, '_')
+ self.squeeze!("_")
+ self.strip!("_")
+ self.downcase!
+ end
+
+ def normalize
+ self.gsub(/[^A-Z0-9]/i, '_').squeeze("_").strip("_").downcase
+ end
+
+end
View
@@ -0,0 +1,2 @@
+require "libraries"
+require "libraries/active_record" if defined?(ActiveRecord)
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+describe Array do
+
+ describe "#each_pair" do
+ it "yeilds pairs" do
+ out = ''
+ [1,2,3,4].each_pair { |a1,a2| out << "*#{a1}#{a2}*" }
+ out.should == "*12**34*"
+ end
+ end
+
+ describe "#delete!" do
+ it "accepts one argument and returns the array after delete" do
+ [1,:a,3.14,"x"].delete!(1).should == [:a,3.14,"x"]
+ end
+ it "accepts a list of arguments and returns the array after delete" do
+ [1,:a,3.14,"x"].delete!(1, "x").should == [:a,3.14]
+ end
+ it "modifies receiver" do
+ a = [1,2,3]
+ a.delete!(2,3)
+ a.should == [1]
+ end
+ end
+
+ describe "#without" do
+ it "does not modify receiver" do
+ a = [1,2,3]
+ a.without(2,3).should == [1]
+ a.should == [1,2,3]
+ end
+ end
+
+end
Oops, something went wrong.

0 comments on commit a03ab4a

Please sign in to comment.