footing 0.2.3 → 1.0.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.
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