footing 0.2.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9704809712f905ca795e12e2ecdc99c63f40f0a9
4
- data.tar.gz: 0ca04637a2af12dfc8d8979ec3538316365b035a
3
+ metadata.gz: 62331199211ec8658359707f77253412878bf094
4
+ data.tar.gz: 5f342a27486320579d36a1dab9b851bdaee79de7
5
5
  SHA512:
6
- metadata.gz: 00259519d93f047459b4179638e4866349449f1c3e50b361c4a0404942bd7b8b2e1a2cd8838c975cae59e0baaecff8c965ae07054c3d0e1e2e3d13334360e810
7
- data.tar.gz: 10aa46ede8bcd8752fdf71f5f76e164e28e862ede5a3966d3aa95105c364e07c3271dae131d6aa29a2ddee12bebb1bd3ce4092cae4b8aad17592800bc359283b
6
+ metadata.gz: c22c8d9868db21ab5528d5a8855b63775243121feb1430b0604c5dd1c73a0115973555d12908a0a96700196682c33f40222ac499b29c84a79530ba7da4fffd77
7
+ data.tar.gz: 09c724182d4234decdca085191b171043059759e45bada2d6b82e56137f01c4e21b2944e558c24550264106e3f72c58d6abfb1e4acf5328a0dc9d16df60a9771
@@ -1,37 +1,80 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- footing (0.2.2)
4
+ footing (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  binding_of_caller (0.7.2)
10
10
  debug_inspector (>= 0.0.1)
11
- coderay (1.0.9)
11
+ byebug (8.2.1)
12
+ coderay (1.1.0)
13
+ coveralls (0.8.10)
14
+ json (~> 1.8)
15
+ rest-client (>= 1.6.8, < 2)
16
+ simplecov (~> 0.11.0)
17
+ term-ansicolor (~> 1.3)
18
+ thor (~> 0.19.1)
19
+ tins (~> 1.6.0)
12
20
  debug_inspector (0.0.2)
21
+ docile (1.1.5)
22
+ domain_name (0.5.25)
23
+ unf (>= 0.0.5, < 1.0.0)
24
+ http-cookie (1.0.2)
25
+ domain_name (~> 0.5)
26
+ interception (0.5)
27
+ json (1.8.3)
13
28
  method_source (0.8.2)
14
- micro_mock (1.1.0)
15
- micro_test (0.4.0)
16
- os
29
+ mime-types (2.99)
30
+ netrc (0.11.0)
17
31
  os (0.9.6)
18
- pry (0.9.12.4)
19
- coderay (~> 1.0)
20
- method_source (~> 0.8)
32
+ pry (0.10.3)
33
+ coderay (~> 1.1.0)
34
+ method_source (~> 0.8.1)
21
35
  slop (~> 3.4)
22
- pry-stack_explorer (0.4.9.1)
36
+ pry-byebug (3.3.0)
37
+ byebug (~> 8.0)
38
+ pry (~> 0.10)
39
+ pry-rescue (1.4.2)
40
+ interception (>= 0.5)
41
+ pry
42
+ pry-stack_explorer (0.4.9.2)
23
43
  binding_of_caller (>= 0.7)
24
44
  pry (>= 0.9.11)
25
- rake (10.1.0)
26
- slop (3.4.6)
45
+ pry-test (0.6.4)
46
+ os
47
+ pry
48
+ pry-byebug
49
+ pry-rescue
50
+ pry-stack_explorer
51
+ rake (10.4.2)
52
+ rest-client (1.8.0)
53
+ http-cookie (>= 1.0.2, < 2.0)
54
+ mime-types (>= 1.16, < 3.0)
55
+ netrc (~> 0.7)
56
+ simplecov (0.11.1)
57
+ docile (~> 1.1.0)
58
+ json (~> 1.8)
59
+ simplecov-html (~> 0.10.0)
60
+ simplecov-html (0.10.0)
61
+ slop (3.6.0)
62
+ term-ansicolor (1.3.2)
63
+ tins (~> 1.0)
64
+ thor (0.19.1)
65
+ tins (1.6.0)
66
+ unf (0.1.4)
67
+ unf_ext
68
+ unf_ext (0.0.7.1)
27
69
 
28
70
  PLATFORMS
29
71
  ruby
30
72
 
31
73
  DEPENDENCIES
74
+ coveralls
32
75
  footing!
33
- micro_mock
34
- micro_test
35
- pry
36
- pry-stack_explorer
76
+ pry-test
37
77
  rake
78
+
79
+ BUNDLED WITH
80
+ 1.10.6
data/README.md CHANGED
@@ -1,71 +1,35 @@
1
+ [![Lines of Code](http://img.shields.io/badge/lines_of_code-87-brightgreen.svg?style=flat)](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
2
+ [![Code Status](http://img.shields.io/codeclimate/github/hopsoft/footing.svg?style=flat)](https://codeclimate.com/github/hopsoft/footing)
3
+ [![Dependency Status](http://img.shields.io/gemnasium/hopsoft/footing.svg?style=flat)](https://gemnasium.com/hopsoft/footing)
4
+ [![Build Status](http://img.shields.io/travis/hopsoft/footing.svg?style=flat)](https://travis-ci.org/hopsoft/footing)
5
+ [![Coverage Status](https://img.shields.io/coveralls/hopsoft/footing.svg?style=flat)](https://coveralls.io/r/hopsoft/footing?branch=master)
6
+ [![Downloads](http://img.shields.io/gem/dt/footing.svg?style=flat)](http://rubygems.org/gems/footing)
7
+
1
8
  # Footing
2
9
 
3
- [![Build Status](https://travis-ci.org/hopsoft/footing.png)](https://travis-ci.org/hopsoft/footing)
4
- [![Dependency Status](https://gemnasium.com/hopsoft/footing.png)](https://gemnasium.com/hopsoft/footing)
5
- [![Code Climate](https://codeclimate.com/github/hopsoft/footing.png)](https://codeclimate.com/github/hopsoft/footing)
10
+ An [ActiveSupport](https://github.com/rails/rails/tree/master/activesupport)
11
+ style utility library that employs [delegation](https://en.wikipedia.org/wiki/Delegation_(programming))
12
+ instead of [monkey patching](https://en.wikipedia.org/wiki/Monkey_patch).
6
13
 
7
- Footing provides some sanity for monkey patching practices.
14
+ __NOTE:__ _The project is structured so that it can support explicit monkey patching if you prefer to use that strategy._
8
15
 
9
- It's also a utility lib that contains additional functionality for core objects that you might find useful.
10
- Think of it as a lightweight version of ActiveSupport that doesn't implicitly change native behavior.
16
+ ## Immutabilty
11
17
 
12
- ## No implicit monkey patching
18
+ Footing employs some principles of [immutability](https://en.wikipedia.org/wiki/Immutable_object) that are common in
19
+ [functional programming](https://en.wikipedia.org/wiki/Functional_programming).
20
+ The integrity of original objects/data is preserved because Footing creates a deep copy by default.
13
21
 
14
- You must explicitly apply monkey patches.
22
+ __NOTE:__ _This behavior can be overridden to improve performance... just be sure you know what you're doing_
15
23
 
16
- ```ruby
17
- Footing.patch! String, Footing::String
18
- Footing.patch! Numeric, Footing::Numeric
19
- ```
24
+ ## Hash
20
25
 
21
- Patches are visible in the classes ancestry.
26
+ ### Filter
22
27
 
23
- ```ruby
24
- String.ancestors
25
- [
26
- String,
27
- Footing::String, # <--
28
- Comparable,
29
- Object,
30
- Kernel,
31
- BasicObject
32
- ]
33
-
34
- Numeric.ancestors
35
- [
36
- Numeric,
37
- Footing::Numeric, # <--
38
- Comparable,
39
- Object,
40
- Kernel,
41
- BasicObject
42
- ]
43
- ```
44
-
45
- ## Instance patching
46
-
47
- If you don't want to corrupt the entire runtime, you can patch an instance.
28
+ Recursively filter out unwanted values based on key.
48
29
 
49
30
  ```ruby
50
- s = "foo"
51
- Footing.patch! s, Footing::String
52
- s.respond_to? :escape # => true
53
- "foo".respond_to? :escape # => false
31
+ data = { name: "Joe", password: "secret" }
32
+ copy = Footing::Hash.new(data)
33
+ copy.filter!(:password)
34
+ copy.inner_object # => {:name=>"Joe", :password=>"[FILTERED]"}
54
35
  ```
55
-
56
- ## Patch free
57
-
58
- Dont like monkey patches? Run patch free by setting up utility methods instead.
59
-
60
- ```ruby
61
- Footing.util! Footing::String
62
- Footing::String.escape "foo", "o" # => "f\\o\\o"
63
- ```
64
-
65
- ## The Library
66
-
67
- The suite of functionality is pretty small right now.
68
- Poke around the [extensions directory](https://github.com/hopsoft/footing/tree/master/lib/footing/extensions) to see what's available.
69
-
70
- Pull requests welcome.
71
-
data/Rakefile CHANGED
@@ -4,6 +4,6 @@ task :default => [:test]
4
4
 
5
5
  desc "Runs the tests."
6
6
  task :test do
7
- exec "bundle exec mt"
7
+ exec "bundle exec pry-test --disable-pry"
8
8
  end
9
9
 
@@ -0,0 +1,20 @@
1
+ require File.join(File.dirname(__FILE__), "lib", "footing", "version")
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "footing"
5
+ spec.license = "MIT"
6
+ spec.version = Footing::VERSION
7
+ spec.homepage = "https://github.com/hopsoft/footing"
8
+ spec.summary = "A utility belt lib with sane monkey patching."
9
+ spec.description = "A utility belt lib with sane monkey patching."
10
+
11
+ spec.authors = ["Nathan Hopkins"]
12
+ spec.email = ["natehop@gmail.com"]
13
+
14
+ spec.files = Dir["lib/**/*.rb", "[A-Z]*"]
15
+ spec.test_files = Dir["lib/**/*.rb"]
16
+
17
+ spec.add_development_dependency "rake"
18
+ spec.add_development_dependency "pry-test"
19
+ spec.add_development_dependency "coveralls"
20
+ end
@@ -1,55 +1,6 @@
1
- require "delegate"
2
- require File.expand_path("../footing/version", __FILE__)
1
+ $:.unshift File.dirname(__FILE__)
2
+ require "footing/version"
3
+ require "footing/object"
4
+ require "footing/hash"
5
+ require "pry"
3
6
 
4
- module Footing
5
- class << self
6
-
7
- # Patches a Module or instance with the given extension.
8
- # @param [Module, Object] obj The Module or instance to patch.
9
- # @param [Module] extension The Module that contains the patches.
10
- def patch!(obj, extension)
11
- context = patch_context(obj)
12
- raise "#{obj.class.name} doesn't support patching!" unless context
13
- context.send :include, extension
14
- end
15
-
16
- # Creates class methods for all instance methods in the module.
17
- # This allows users to invoke utility methods rather than monkey patching if they so desire.
18
- # @param [Module] mod The Module to setup util methods for.
19
- def util!(mod)
20
- proxy = Class.new(SimpleDelegator)
21
- Footing.patch! proxy, mod
22
-
23
- mod.instance_methods(false).each do |method_name|
24
- mod.define_singleton_method(method_name) do |target, *args|
25
- method = proxy.instance_method(method_name)
26
- target = proxy.new(target)
27
- if method.parameters.empty?
28
- method.bind(target).call
29
- else
30
- method.bind(target).call(*args)
31
- end
32
- end
33
- end
34
- end
35
-
36
- private
37
-
38
- def patch_context(obj)
39
- context = obj if obj.is_a? Module
40
- begin
41
- context ||= class << obj
42
- self
43
- end
44
- rescue Exception
45
- end
46
- context
47
- end
48
-
49
- end
50
- end
51
-
52
- Dir[File.expand_path("../**/*.rb", __FILE__)].each do |file|
53
- next if file =~ /(lib\/footing\.rb|version\.rb)\z/
54
- ENV["FOOTING_DEV"] ? load(file) : require(file)
55
- end
@@ -0,0 +1,39 @@
1
+ module Footing
2
+ module HashMethods
3
+
4
+ # Recursively filters the values for the specified keys in place.
5
+ # IMPORTANT: This mutates the Hash.
6
+ #
7
+ # @param keys [Array<Symbol,String,Regexp>] The keys to filter
8
+ # @param replacement [Object] The replacement value to use
9
+ # @return [Footing::Hash] Returns self
10
+ def filter!(keys, replacement: "[FILTERED]")
11
+ should_replace = lambda do |key|
12
+ replace = false
13
+ keys.each do |k|
14
+ break if replace
15
+ replace = k.is_a?(Regexp) ? key.to_s =~ k : key.to_s == k.to_s
16
+ end
17
+ replace
18
+ end
19
+
20
+ Footing::Hash.new(self).inner_object.each do |key, value|
21
+ if value.is_a?(::Hash)
22
+ Footing::Hash.new(value, copy: false).filter!(keys, replacement: replacement)
23
+ elsif value.is_a?(Enumerable)
24
+ value.each do |val|
25
+ if val.is_a?(::Hash)
26
+ Footing::Hash.new(val, copy: false).filter!(keys, replacement: replacement)
27
+ end
28
+ end
29
+ else
30
+ value = replacement if should_replace.call(key)
31
+ self[key] = value
32
+ end
33
+ end
34
+
35
+ self
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ require "footing/concerns/hash_methods"
2
+
3
+ module Footing
4
+ class Hash < Footing::Object
5
+ include HashMethods
6
+ end
7
+ end
@@ -0,0 +1,55 @@
1
+ module Footing
2
+ class Object
3
+ extend Forwardable
4
+
5
+ attr_reader :inner_object
6
+
7
+ class << self
8
+ def target_name
9
+ self.name.gsub(/\AFooting::/, "")
10
+ end
11
+
12
+ def match?(o)
13
+ o.class.ancestors.map(&:name).include?(target_name)
14
+ end
15
+
16
+ def new(o, copy: true)
17
+ return o if o.is_a?(self)
18
+ super o, copy: copy
19
+ end
20
+
21
+ def copy(o)
22
+ Marshal.load Marshal.dump(o)
23
+ end
24
+ end
25
+
26
+ def initialize(o, copy: true)
27
+ raise ArgumentError.new("Types must match") unless self.class.match?(o)
28
+ o = self.class.copy(o) if copy
29
+ @inner_object = o
30
+ end
31
+
32
+ def eigen
33
+ @eigen ||= class << self
34
+ self
35
+ end
36
+ end
37
+
38
+ def method_missing(name, *args)
39
+ if inner_object.respond_to?(name)
40
+ eigen.instance_eval do
41
+ define_method(name) { |*a| inner_object.send name, *a }
42
+ end
43
+ return inner_object.send name, *args
44
+ end
45
+
46
+ super
47
+ end
48
+
49
+ def respond_to?(name)
50
+ return true if inner_object.respond_to?(name)
51
+ super
52
+ end
53
+
54
+ end
55
+ end
@@ -1,3 +1,3 @@
1
1
  module Footing
2
- VERSION = "0.2.3"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: footing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Hopkins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-08 00:00:00.000000000 Z
11
+ date: 2015-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: micro_test
28
+ name: pry-test
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,35 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: micro_mock
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: pry
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: pry-stack_explorer
42
+ name: coveralls
71
43
  requirement: !ruby/object:Gem::Requirement
72
44
  requirements:
73
45
  - - ">="
@@ -92,16 +64,11 @@ files:
92
64
  - LICENSE.txt
93
65
  - README.md
94
66
  - Rakefile
67
+ - footing.gemspec
95
68
  - lib/footing.rb
96
- - lib/footing/extensions/array.rb
97
- - lib/footing/extensions/hash.rb
98
- - lib/footing/extensions/kernel.rb
99
- - lib/footing/extensions/nil_class.rb
100
- - lib/footing/extensions/numeric.rb
101
- - lib/footing/extensions/object.rb
102
- - lib/footing/extensions/postgresql_adapter.rb
103
- - lib/footing/extensions/schema_statements.rb
104
- - lib/footing/extensions/string.rb
69
+ - lib/footing/concerns/hash_methods.rb
70
+ - lib/footing/hash.rb
71
+ - lib/footing/object.rb
105
72
  - lib/footing/version.rb
106
73
  homepage: https://github.com/hopsoft/footing
107
74
  licenses:
@@ -123,19 +90,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
90
  version: '0'
124
91
  requirements: []
125
92
  rubyforge_project:
126
- rubygems_version: 2.2.0
93
+ rubygems_version: 2.4.5
127
94
  signing_key:
128
95
  specification_version: 4
129
96
  summary: A utility belt lib with sane monkey patching.
130
97
  test_files:
131
- - lib/footing/extensions/array.rb
132
- - lib/footing/extensions/hash.rb
133
- - lib/footing/extensions/kernel.rb
134
- - lib/footing/extensions/nil_class.rb
135
- - lib/footing/extensions/numeric.rb
136
- - lib/footing/extensions/object.rb
137
- - lib/footing/extensions/postgresql_adapter.rb
138
- - lib/footing/extensions/schema_statements.rb
139
- - lib/footing/extensions/string.rb
98
+ - lib/footing/concerns/hash_methods.rb
99
+ - lib/footing/hash.rb
100
+ - lib/footing/object.rb
140
101
  - lib/footing/version.rb
141
102
  - lib/footing.rb
103
+ has_rdoc:
@@ -1,18 +0,0 @@
1
- module Footing
2
- module Array
3
-
4
- # Recursively casts all string values in this Array.
5
- # See Footing::String#cast
6
- def cast_values!
7
- each_with_index do |value, index|
8
- if value.respond_to?(:cast_values!)
9
- value.cast_values!
10
- elsif value.respond_to?(:cast)
11
- self[index] = value.cast
12
- end
13
- end
14
- self
15
- end
16
-
17
- end
18
- end
@@ -1,123 +0,0 @@
1
- module Footing
2
- module Hash
3
-
4
- # Rekeys the Hash by invoking a method on the existing keys
5
- # and uses the return value as the new key.
6
- #
7
- # NOTE: Creates and returns a new Hash.
8
- #
9
- # Example:
10
- # h = { [1] => "short", [1,2] => "medium", [1,2,3] => "long" }
11
- # h.rekey(:length) # => { 1 => "short", 2 => "medium", 3 => "long" }
12
- #
13
- # @param [Symbol] name The method name to invoke on the existing keys.
14
- # @return [Hash] A new Hash that has been re-keyed.
15
- def rekey(method_name)
16
- reduce({}) do |new_hash, (key, value)|
17
- new_hash[key.public_send(method_name)] = value
18
- new_hash
19
- end
20
- end
21
-
22
- # Recursively forces all String values to the specified encoding.
23
- # @param [] encoding The encoding to use.
24
- # @yield [value] Yields the value after the encoding has been applied.
25
- def force_encoding!(encoding, &block)
26
- each do |key, value|
27
- if value.respond_to?(:force_encoding!)
28
- value.force_encoding!(encoding, &block)
29
- elsif value.is_a?(Enumerable)
30
- value.each do |val|
31
- next unless val.respond_to?(:force_encoding!)
32
- val.force_encoding!(encoding, &block)
33
- end
34
- elsif value.is_a?(String)
35
- # force encoding then strip all non ascii chars
36
- if block_given?
37
- self[key] = yield(value.force_encoding(encoding))
38
- else
39
- self[key] = value.force_encoding(encoding)
40
- end
41
- end
42
- end
43
- end
44
-
45
- # Recursively adjusts the values of the Hash in place.
46
- #
47
- # @example
48
- # dict = {:a => 1, :b => 2, :c => 3}
49
- # dict.adjust_values! { |v| v.to_s }
50
- # dict # => {:a => "1", :b => "2", :c => "3"}
51
- #
52
- # @yield [value] Yields the current value to the block.
53
- # The result of the block is then assigned to the corresponding key.
54
- def adjust_values!(&block)
55
- each do |key, value|
56
- if value.respond_to?(:adjust_values!)
57
- value.adjust_values!(&block)
58
- elsif value.is_a?(Enumerable)
59
- value.each do |val|
60
- next unless val.respond_to?(:adjust_values!)
61
- val.adjust_values!(&block)
62
- end
63
- else
64
- self[key] = yield(value)
65
- end
66
- end
67
- self
68
- end
69
-
70
- # Recursively casts all string values in this Hash.
71
- # See Footing::String#cast
72
- def cast_values!
73
- each do |key, value|
74
- if value.respond_to?(:cast_values!)
75
- value.cast_values!
76
- elsif value.is_a?(Enumerable)
77
- value.each do |val|
78
- next unless val.respond_to?(:cast_values!)
79
- val.cast_values!
80
- end
81
- elsif value.respond_to?(:cast)
82
- self[key] = value.cast
83
- end
84
- end
85
- self
86
- end
87
-
88
- def filter!(keys, replacement="[FILTERED]")
89
- should_replace = lambda do |key|
90
- replace = false
91
- keys.each do |k|
92
- break if replace
93
- replace = k.is_a?(Regexp) ? key.to_s =~ k : key.to_s == k.to_s
94
- end
95
- replace
96
- end
97
-
98
- each do |key, value|
99
- if value.respond_to?(:filter!)
100
- value.filter!(keys, replacement)
101
- elsif value.is_a?(Enumerable)
102
- value.each do |val|
103
- next unless val.respond_to?(:filter!)
104
- val.filter!(keys, replacement)
105
- end
106
- else
107
- value = replacement if should_replace.call(key)
108
- self[key] = value
109
- end
110
- end
111
- self
112
- end
113
-
114
- def silence!(keys)
115
- filter! keys, nil
116
- end
117
-
118
- def copy
119
- Marshal.load(Marshal.dump(self))
120
- end
121
-
122
- end
123
- end
@@ -1,18 +0,0 @@
1
- module Footing
2
- module Kernel
3
-
4
- # Safely evals text inside of a sandbox.
5
- # @see http://phrogz.net/programmingruby/taint.html Ruby safe level description.
6
- # @param [String] text The text to eval.
7
- # @param [Integer] level The safe level to apply.
8
- # @return [Object]
9
- def safe_eval(text, level=4)
10
- sandbox = lambda do
11
- $SAFE = level
12
- eval(text.to_s)
13
- end
14
- sandbox.call
15
- end
16
-
17
- end
18
- end
@@ -1,17 +0,0 @@
1
- module Footing
2
- module NilClass
3
-
4
- # Calling [] on nil returns nil instead of raising an exception.
5
- # Helpful when looping over nested Hashes.
6
- #
7
- # @example
8
- # dict = {}
9
- # dict[:foo][:bar][:baz] # => nil
10
- #
11
- # @param [Object] key The key to lookup.
12
- def [](key)
13
- nil
14
- end
15
-
16
- end
17
- end
@@ -1,37 +0,0 @@
1
- module Footing
2
- module Numeric
3
-
4
- # Returns a positive representation of the number.
5
- def positive
6
- abs
7
- end
8
-
9
- # Returns a negative representation of the number.
10
- def negative
11
- abs.flip_sign
12
- end
13
-
14
- # Flips the sign on the number making it either either positive or negative.
15
- def flip_sign
16
- self * -1
17
- end
18
-
19
- # Returns the percentage that this number is of the passed number.
20
- # @example
21
- # 8.percent_of(10) # => 80.0
22
- # @param [Numeric] number The number to calculate the percentage with
23
- def percent_of(number)
24
- percent = (self.to_f / number.to_f) * 100 if number > 0
25
- percent ||= 0.0
26
- end
27
-
28
- # Rounds the number to a certain number of decimal places.
29
- # @example
30
- # 1.784329.round_to(1) # => 1.8
31
- # @param [Numeric] decimal_places The number of decimal places to round to
32
- def round_to(decimal_places)
33
- (self * 10**decimal_places).round.to_f / 10**decimal_places
34
- end
35
-
36
- end
37
- end
@@ -1,28 +0,0 @@
1
- module Footing
2
- module Object
3
-
4
- # Returns the eigen class for the object.
5
- def eigen
6
- class << self
7
- self
8
- end
9
- rescue Exception
10
- nil
11
- end
12
-
13
- # Indicates if the object has an eigen class.
14
- def has_eigen?
15
- !eigen.nil?
16
- end
17
-
18
- # Trys to invoke a method on the object.
19
- # Returns nil if the method isn't supported.
20
- def try(name, *args, &block)
21
- if respond_to?(name)
22
- return public_send(name, *args, &block)
23
- end
24
- nil
25
- end
26
-
27
- end
28
- end
@@ -1,20 +0,0 @@
1
- # Extend Rails with this module to add a uuid method in your migrations.
2
- #
3
- # Example:
4
- # # rails_root/config/application.rb
5
- # config.after_initialize do
6
- # Footing.patch! ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::TableDefinition, Footing::PGTableDefinition
7
- # end
8
- #
9
- module Footing
10
- module PGTableDefinition
11
-
12
- # Provides a uuid method when inside a migration's create_table block.
13
- def uuid(*args)
14
- options = args.extract_options!
15
- #column(args[0], 'uuid default uuid_generate_v1()', options)
16
- column(args[0], 'uuid', options)
17
- end
18
-
19
- end
20
- end
@@ -1,75 +0,0 @@
1
- # Extend Rails to support adding timestamp indexes for created_at & updated_at using day granularity.
2
- #
3
- # @example Make these statements available to ActiveRecord::Migration change, up, down methods
4
- # # rails_root/config/application.rb
5
- # config.after_initialize do
6
- # Footing.patch! ActiveRecord::ConnectionAdapters::AbstractAdapter, Footing::PGSchemaStatements
7
- # end
8
- #
9
- module Footing
10
- module PGSchemaStatements
11
-
12
- # Adds indexes to the created_at and updated_at timestamp columns with 'day' granularity.
13
- def add_timestamp_indexes(table_name)
14
- %w(created_at updated_at).each do |column_name|
15
- add_datetime_index(table_name, column_name, :precision => :day)
16
- end
17
- end
18
-
19
- # Removes indexes to the created_at and updated_at timestamp columns with 'day' granularity.
20
- def remove_timestamp_indexes(table_name)
21
- %w(created_at updated_at).each do |column_name|
22
- remove_datetime_index(table_name, column_name, :precision => :day)
23
- end
24
- end
25
-
26
- # Adds an index on a datetime column using the specified precision.
27
- # @param [Symbol,String] table_name The name of the table to migrate.
28
- # @param [Symbol,String] column_name The name of the column to migrate.
29
- # @param [Hash] options
30
- # @option options [Symbol,String] :precision
31
- # - microseconds
32
- # - milliseconds
33
- # - second
34
- # - minute *default
35
- # - hour
36
- # - day
37
- # - week
38
- # - month
39
- # - quarter
40
- # - year
41
- # - decade
42
- # - century
43
- # - millennium
44
- def add_datetime_index(table_name, column_name, options={})
45
- options[:precision] ||= :minute
46
- index_name = "index_#{table_name}_on_#{column_name}_by_#{options[:precision]}"
47
- execute "create index #{index_name} on #{quote_table_name(table_name)} (date_trunc('#{options[:precision]}', #{quote_column_name(column_name)}))"
48
- end
49
-
50
- # Removes an index on a datetime column using the specified precision.
51
- # @param [Symbol,String] table_name The name of the table to migrate.
52
- # @param [Symbol,String] column_name The name of the column to migrate.
53
- # @param [Hash] options
54
- # @option options [Symbol,String] :precision
55
- # - microseconds
56
- # - milliseconds
57
- # - second
58
- # - minute *default
59
- # - hour
60
- # - day
61
- # - week
62
- # - month
63
- # - quarter
64
- # - year
65
- # - decade
66
- # - century
67
- # - millennium
68
- def remove_datetime_index(table_name, column_name, options={})
69
- options[:precision] ||= :minute
70
- index_name = "index_#{table_name}_on_#{column_name}_by_#{options[:precision]}"
71
- execute "drop index if exists #{index_name}"
72
- end
73
-
74
- end
75
- end
@@ -1,74 +0,0 @@
1
- module Footing
2
- module String
3
-
4
- # Generates a random string.
5
- #
6
- # @example
7
- # Footing.util! Footing::String
8
- # Footing::String.random_key(100, :reject => ["1", "I", "l", "0", "O"])
9
- #
10
- # @param [Integer] length The length of the key to generate. Defaults to 12.
11
- # @param [Hash] opts
12
- # @option opts [Array] :reject A list of characters to omit from the key.
13
- # @option opts [Boolean] :upcase Indicates that only use uppercase characters should be used.
14
- # @return [String]
15
- def random(length=12, opts={})
16
- @chars ||= [(0..9).to_a, ('a'..'z').to_a, ('A'..'Z').to_a].flatten.map { |c| c.to_s }
17
- chars = @chars.reject do |c|
18
- c =~ /[a-z]/ if opts[:upcase]
19
- end
20
- opts[:reject] ||= []
21
- opts[:reject] = opts[:reject].map { |c| c.to_s }
22
- (1..length).map{ |i| (chars - opts[:reject]).sample }.join
23
- end
24
-
25
- # Escapes a series of chars.
26
- def escape(*chars)
27
- gsub(/(?<!\\)(#{chars.join("|")})/) do |char|
28
- "\\" + char
29
- end
30
- end
31
-
32
- # Converts a word with underscores into a sentance with a capitalized first word.
33
- def humanize
34
- self.downcase.gsub(/_/, " ").capitalize
35
- end
36
-
37
- # Similar to humanize but it capitalizes each word
38
- def titleize
39
- self.gsub(/\s/, "_").split('_').map(&:capitalize).join(' ')
40
- end
41
- alias :titlecase :titleize
42
-
43
-
44
- def classify
45
- self.gsub(/\s/, "_").titleize.gsub(/\W/, "")
46
- end
47
-
48
- # Indicates if this string represents a number.
49
- def numeric?
50
- !!(self =~ /\A[0-9]+\.*[0-9]*\z/)
51
- end
52
-
53
- # Indicates if this string represents a boolean value.
54
- def boolean?
55
- !!(self =~ /\A(true|false)\z/i)
56
- end
57
-
58
- # Casts this string to another datatype.
59
- # Supported datatypes:
60
- # * Integer
61
- # * Float
62
- # * Boolean
63
- def cast
64
- return to_f if numeric? && index(".")
65
- return to_i if numeric?
66
- if boolean?
67
- return true if self =~ /\Atrue\z/i
68
- return false if self =~ /\Afalse\z/i
69
- end
70
- self
71
- end
72
-
73
- end
74
- end