hoodie 0.4.6 → 0.4.7

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: 62365f7e782e882ae3769a0f11495a15662baffd
4
- data.tar.gz: 5c174acce11e7d7e22ebbe43533b52f2bc91a6c6
3
+ metadata.gz: 1cc89e655be60fd07041f5142b3ce00d8998abea
4
+ data.tar.gz: 43d8d7c519bd16d6d7bc8872979f7187b30315b3
5
5
  SHA512:
6
- metadata.gz: 89700fd2bed82cc9abfd889db31551694ac271b49eb3ae5554c1ab3def161948218cd6062ccde5cbd5202634a569458d96ebb51744a68a321f3b74af404c6393
7
- data.tar.gz: b18ae1e33e1f0b9abaaa2cab448e76411a71c8804c2524d0f2aada6319addd65aa0bd749c6ebd17b3a5b4e906757ab426ecf1b28c78694e4d55878a62ba1b8b9
6
+ metadata.gz: aff45c5e404ef4944924ab67f1b1dd8e8b1f9cbd782023d2214411501122dd8b1241bc25cd10cdbfeadeeab1c289a45ea429736f09b0246434e153ee9e2e20f7
7
+ data.tar.gz: 368898a15a8a4dbcf40f4f1274009ecd4feddacc2b3934d98ddb4b2e5dc6a7fcf8980e720cf70b60fe6c8954d5622e504100020f580c0b6fe0a421d02532f34c
data/hoodie.gemspec CHANGED
@@ -22,10 +22,10 @@ Gem::Specification.new do |s|
22
22
  # s.add_runtime_dependency 'anemone', '>= 0.7.2'
23
23
  s.add_runtime_dependency 'hitimes'
24
24
 
25
- s.add_development_dependency 'rubocop', '>= 0.26.0'
26
- s.add_development_dependency 'rake', '>= 10.3.2'
27
- s.add_development_dependency 'coveralls', '>= 0.7.1'
28
- s.add_development_dependency 'rspec', '>= 3.1.0'
29
- s.add_development_dependency 'fuubar', '>= 2.0.0'
30
- s.add_development_dependency 'timecop', '>= 0.7.1'
25
+ s.add_development_dependency 'rubocop'
26
+ s.add_development_dependency 'rake'
27
+ s.add_development_dependency 'yard'
28
+ s.add_development_dependency 'yard-redcarpet-ext'
29
+ s.add_development_dependency 'redcarpet'
30
+ s.add_development_dependency 'github-markup'
31
31
  end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hoodie
4
+
5
+ # A Configuration instance
6
+ class Configuration
7
+
8
+ # Access the logging setting for this instance
9
+ attr_accessor :logging
10
+
11
+ # Access to the logging level for this instance
12
+ attr_accessor :level
13
+
14
+ # Initialized a configuration instance
15
+ #
16
+ # @return [undefined]
17
+ #
18
+ # @api private
19
+ def initialize(options={})
20
+ @logging = options.fetch(:logging, false)
21
+ @level = options.fetch(:level, :info)
22
+
23
+ yield self if block_given?
24
+ end
25
+
26
+ # @api private
27
+ def to_h
28
+ { logging: logging,
29
+ level: level
30
+ }.freeze
31
+ end
32
+ end
33
+ end
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ class Hash
43
43
  # @return [Hash]
44
44
  #
45
45
  def transform_keys
46
- return enum_for(:transform_keys) unless block_given?
46
+ enum_for(:transform_keys) unless block_given?
47
47
  result = self.class.new
48
48
  each_key do |key|
49
49
  result[yield(key)] = self[key]
@@ -91,7 +91,7 @@ class Hash
91
91
  # @return [Hash]
92
92
  #
93
93
  def recursively_symbolize_keys
94
- recursively_transform_keys { |key| key.downcase.to_sym rescue key }
94
+ recursively_transform_keys { |key| key.to_sym rescue key }
95
95
  end
96
96
 
97
97
  # Returns a new hash with all keys converted to strings.
@@ -110,8 +110,52 @@ class Hash
110
110
  recursively_transform_keys { |key| key.to_s rescue key }
111
111
  end
112
112
 
113
+ # Returns a new hash with all keys converted to strings and the
114
+ # first letter capitalized.
115
+ #
116
+ # @return [Hash]
117
+ #
118
+ def capitalize_keys
119
+ transform_keys { |key| key.to_s.capitalize rescue key }
120
+ end
121
+
122
+ # Returns a new Hash, recursively converting all keys to strings
123
+ # and the first letter capitalized.
124
+ #
125
+ # @return [Hash]
126
+ #
127
+ def recursively_capitalize_key
128
+ recursively_transform_keys { |key| key.to_s.capitalize rescue key }
129
+ end
130
+
131
+ class UndefinedPathError < StandardError; end
132
+ # Recursively searchs a nested datastructure for a key and returns
133
+ # the value. If a block is provided its value will be returned if
134
+ # the key does not exist
135
+ #
136
+ # @example
137
+ # options = { server: { location: { row: { rack: 34 } } } }
138
+ # options.recursive_fetch :server, :location, :row, :rack
139
+ # # => 34
140
+ # options.recursive_fetch(:non_existent_key) { 'default' }
141
+ # # => "default"
142
+ #
143
+ # @return [Hash, Array, String] value for key
144
+ #
145
+ def recursive_fetch(*args, &block)
146
+ args.reduce(self) do |obj, arg|
147
+ begin
148
+ arg = Integer(arg) if obj.is_a? Array
149
+ obj.fetch(arg)
150
+ rescue ArgumentError, IndexError, NoMethodError => e
151
+ break block.call(arg) if block
152
+ raise UndefinedPathError, "Could not fetch path (#{args.join(' > ')}) at #{arg}", e.backtrace
153
+ end
154
+ end
155
+ end
156
+
113
157
  def recursive_merge(other)
114
- hash = dup
158
+ hash = self.dup
115
159
  other.each do |key, value|
116
160
  myval = self[key]
117
161
  if value.is_a?(Hash) && myval.is_a?(Hash)
@@ -0,0 +1,54 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ #
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ class String
21
+ def clear; colorize(self, "\e[0m"); end
22
+ def erase_line; colorize(self, "\e[K"); end
23
+ def erase_char; colorize(self, "\e[P"); end
24
+ def bold; colorize(self, "\e[1m"); end
25
+ def dark; colorize(self, "\e[2m"); end
26
+ def underline; colorize(self, "\e[4m"); end
27
+ def blink; colorize(self, "\e[5m"); end
28
+ def reverse; colorize(self, "\e[7m"); end
29
+ def concealed; colorize(self, "\e[8m"); end
30
+ def black; colorize(self, "\e[0;30m"); end
31
+ def gray; colorize(self, "\e[1;30m"); end
32
+ def red; colorize(self, "\e[0;31m"); end
33
+ def magenta; colorize(self, "\e[1;31m"); end
34
+ def green; colorize(self, "\e[0;32m"); end
35
+ def olive; colorize(self, "\e[1;32m"); end
36
+ def yellow; colorize(self, "\e[0;33m"); end
37
+ def cream; colorize(self, "\e[1;33m"); end
38
+ def blue; colorize(self, "\e[0;34m"); end
39
+ def purple; colorize(self, "\e[1;34m"); end
40
+ def orange; colorize(self, "\e[0;35m"); end
41
+ def mustard; colorize(self, "\e[1;35m"); end
42
+ def cyan; colorize(self, "\e[0;36m"); end
43
+ def cyan2; colorize(self, "\e[1;36m"); end
44
+ def white; colorize(self, "\e[0;97m"); end
45
+ def on_black; colorize(self, "\e[40m"); end
46
+ def on_red; colorize(self, "\e[41m"); end
47
+ def on_green; colorize(self, "\e[42m"); end
48
+ def on_yellow; colorize(self, "\e[43m"); end
49
+ def on_blue; colorize(self, "\e[44m"); end
50
+ def on_magenta; colorize(self, "\e[45m"); end
51
+ def on_cyan; colorize(self, "\e[46m"); end
52
+ def on_white; colorize(self, "\e[47m"); end
53
+ def colorize(text, color_code) "#{color_code}#{text}\e[0m" end
54
+ end
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -0,0 +1,62 @@
1
+ # encoding: UTF-8
2
+
3
+ Inflections.inflections do |inflect|
4
+ inflect.plural(/$/, 's')
5
+ inflect.plural(/s$/i, 's')
6
+ inflect.plural(/^(ax|test)is$/i, '\1es')
7
+ inflect.plural(/(octop|vir)us$/i, '\1i')
8
+ inflect.plural(/(octop|vir)i$/i, '\1i')
9
+ inflect.plural(/(alias|status)$/i, '\1es')
10
+ inflect.plural(/(bu)s$/i, '\1ses')
11
+ inflect.plural(/(buffal|tomat)o$/i, '\1oes')
12
+ inflect.plural(/([ti])um$/i, '\1a')
13
+ inflect.plural(/([ti])a$/i, '\1a')
14
+ inflect.plural(/sis$/i, 'ses')
15
+ inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
16
+ inflect.plural(/(hive)$/i, '\1s')
17
+ inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
18
+ inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
19
+ inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
20
+ inflect.plural(/^(m|l)ouse$/i, '\1ice')
21
+ inflect.plural(/^(m|l)ice$/i, '\1ice')
22
+ inflect.plural(/^(ox)$/i, '\1en')
23
+ inflect.plural(/^(oxen)$/i, '\1')
24
+ inflect.plural(/(quiz)$/i, '\1zes')
25
+
26
+ inflect.singular(/s$/i, '')
27
+ inflect.singular(/(ss)$/i, '\1')
28
+ inflect.singular(/(n)ews$/i, '\1ews')
29
+ inflect.singular(/([ti])a$/i, '\1um')
30
+ inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '\1sis')
31
+ inflect.singular(/(^analy)(sis|ses)$/i, '\1sis')
32
+ inflect.singular(/([^f])ves$/i, '\1fe')
33
+ inflect.singular(/(hive)s$/i, '\1')
34
+ inflect.singular(/(tive)s$/i, '\1')
35
+ inflect.singular(/([lr])ves$/i, '\1f')
36
+ inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y')
37
+ inflect.singular(/(s)eries$/i, '\1eries')
38
+ inflect.singular(/(m)ovies$/i, '\1ovie')
39
+ inflect.singular(/(x|ch|ss|sh)es$/i, '\1')
40
+ inflect.singular(/^(m|l)ice$/i, '\1ouse')
41
+ inflect.singular(/(bus)(es)?$/i, '\1')
42
+ inflect.singular(/(o)es$/i, '\1')
43
+ inflect.singular(/(shoe)s$/i, '\1')
44
+ inflect.singular(/(cris|test)(is|es)$/i, '\1is')
45
+ inflect.singular(/^(a)x[ie]s$/i, '\1xis')
46
+ inflect.singular(/(octop|vir)(us|i)$/i, '\1us')
47
+ inflect.singular(/(alias|status)(es)?$/i, '\1')
48
+ inflect.singular(/^(ox)en/i, '\1')
49
+ inflect.singular(/(vert|ind)ices$/i, '\1ex')
50
+ inflect.singular(/(matr)ices$/i, '\1ix')
51
+ inflect.singular(/(quiz)zes$/i, '\1')
52
+ inflect.singular(/(database)s$/i, '\1')
53
+
54
+ inflect.irregular('person', 'people')
55
+ inflect.irregular('man', 'men')
56
+ inflect.irregular('child', 'children')
57
+ inflect.irregular('sex', 'sexes')
58
+ inflect.irregular('move', 'moves')
59
+ inflect.irregular('zombie', 'zombies')
60
+
61
+ inflect.uncountable(%w(hovercraft moose milk rain Swiss grass equipment information rice money species series fish sheep jeans))
62
+ end
@@ -0,0 +1,161 @@
1
+ # encoding: UTF-8
2
+
3
+ module Inflections
4
+ # A singleton instance of this class is yielded by Inflections.inflections,
5
+ # which can then be used to specify additional inflection rules. Examples:
6
+ #
7
+ # Inflections.inflections do |inflect|
8
+ # inflect.plural /^(ox)$/i, '\1\2en'
9
+ # inflect.singular /^(ox)en/i, '\1'
10
+ #
11
+ # inflect.irregular 'octopus', 'octopi'
12
+ #
13
+ # inflect.uncountable "equipment"
14
+ # end
15
+ #
16
+ # New rules are added at the top. So in the example above, the irregular rule
17
+ # for octopus will now be the first of the pluralization and singularization
18
+ # rules that is runs. This guarantees that your rules run before any of the
19
+ # rules that may already have been loaded.
20
+ #
21
+ class Inflections
22
+
23
+ # Return instance
24
+ #
25
+ # @return [Inflections]
26
+ # @api private
27
+ def self.instance
28
+ @__instance__ ||= new
29
+ end
30
+
31
+ # @return [Array] plurals
32
+ # @api private
33
+ attr_reader :plurals
34
+
35
+ # @return [Array] singulars
36
+ # @api private
37
+ attr_reader :singulars
38
+
39
+ # @return [Array] uncountables
40
+ # @api private
41
+ attr_reader :uncountables
42
+
43
+ # @return [Array] humans
44
+ # @api private
45
+ attr_reader :humans
46
+
47
+ # Initialize object
48
+ #
49
+ # @return [undefined]
50
+ # @api private
51
+ def initialize
52
+ @plurals = RulesCollection.new
53
+ @singulars = RulesCollection.new
54
+ @humans = RulesCollection.new
55
+ @uncountables = Set[]
56
+ end
57
+
58
+ # Specifies a new pluralization rule and its replacement. The rule can
59
+ # either be a string or a regular expression. The replacement should always
60
+ # be a string that may include references to the matched data from the rule.
61
+ #
62
+ # @param [String, Regexp] rule
63
+ # @param [String, Regexp] replacement
64
+ # @return [self]
65
+ # @api private
66
+ def plural(rule, replacement)
67
+ rule(rule, replacement, @plurals)
68
+ self
69
+ end
70
+
71
+ # Specifies a new singularization rule and its replacement. The rule can
72
+ # either be a string or a regular expression. The replacement should always
73
+ # be a string that may include references to the matched data from the rule.
74
+ #
75
+ # @param [String, Regexp] rule
76
+ # @param [String, Regexp] replacement
77
+ # @return [self]
78
+ # @api private
79
+ def singular(rule, replacement)
80
+ rule(rule, replacement, @singulars)
81
+ self
82
+ end
83
+
84
+ # Specifies a new irregular that applies to both pluralization and
85
+ # singularization at the same time. This can only be used for strings, not
86
+ # regular expressions. You simply pass the irregular in singular and plural
87
+ # form.
88
+ #
89
+ # @param [String] singular
90
+ # @param [String] plural
91
+ # @return [self]
92
+ # @api private
93
+ def irregular(singular, plural)
94
+ @uncountables.delete(singular)
95
+ @uncountables.delete(plural)
96
+ add_irregular(singular, plural, @plurals)
97
+ add_irregular(plural, singular, @singulars)
98
+ self
99
+ end
100
+
101
+ # Uncountable will not be inflected
102
+ #
103
+ # @param [Enumerable<String>] words
104
+ # @return [self]
105
+ # @api private
106
+ def uncountable(*words)
107
+ @uncountables.merge(words.flatten)
108
+ self
109
+ end
110
+
111
+ # Specifies a humanized form of a string by a regular expression rule or by
112
+ # a string mapping. When using a regular expression based replacement, the
113
+ # normal humanize formatting is called after the replacement. When a string
114
+ # is used, the human form should be specified as desired (example: 'The
115
+ # name', not 'the_name')
116
+ #
117
+ # @param [String, Regexp] rule
118
+ # @param [String, Regexp] replacement
119
+ # @return [self]
120
+ # @api private
121
+ def human(rule, replacement)
122
+ @humans.insert(0, [rule, replacement])
123
+ self
124
+ end
125
+
126
+ # Clear all inflection rules
127
+ #
128
+ # @return [self]
129
+ # @api private
130
+ def clear
131
+ initialize
132
+ self
133
+ end
134
+
135
+ private
136
+
137
+ # Add irregular inflection
138
+ #
139
+ # @param [String] rule
140
+ # @param [String] replacement
141
+ # @return [undefined]
142
+ # @api private
143
+ def add_irregular(rule, replacement, target)
144
+ head, *tail = rule.chars.to_a
145
+ rule(/(#{head})#{tail.join}\z/i, '\1' + replacement[1..-1], target)
146
+ end
147
+
148
+ # Add a new rule
149
+ #
150
+ # @param [String, Regexp] rule
151
+ # @param [String, Regexp] replacement
152
+ # @param [Array] target
153
+ # @return [undefined]
154
+ # @api private
155
+ def rule(rule, replacement, target)
156
+ @uncountables.delete(rule)
157
+ @uncountables.delete(replacement)
158
+ target.insert(0, [rule, replacement])
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+
3
+ module Inflections
4
+ # Wraps inflections array
5
+ #
6
+ class RulesCollection < Array
7
+ # Applies first found rule to given word
8
+ #
9
+ # @param [String] word
10
+ # @return [String] modified word
11
+ # @api private
12
+ def apply_to(word)
13
+ result = word.dup
14
+ each { |rule, replacement| break if result.gsub!(rule, replacement) }
15
+ result
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,172 @@
1
+
2
+ require 'set'
3
+
4
+ # The Inflections transforms words from singular to plural, class names to table
5
+ # names, modularized class names to ones without, and class names to foreign
6
+ # keys. The default inflections for pluralization, singularization, and
7
+ # uncountable words are kept in inflections.rb.
8
+ #
9
+ module Inflections
10
+
11
+ # Convert input to UpperCamelCase. Will also convert '/' to '::' which is
12
+ # useful for converting paths to namespaces.
13
+ #
14
+ # @param [String] input
15
+ # @return [String]
16
+ def self.camelize(input)
17
+ input.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:\A|_)(.)/) { $1.upcase }
18
+ end
19
+
20
+ # Convert input to underscored, lowercase string. Changes '::' to '/' to
21
+ # convert namespaces to paths.
22
+ #
23
+ # @param [String] input
24
+ # @return [String]
25
+ def self.underscore(input)
26
+ word = input.gsub(/::/, '/')
27
+ underscorize(word)
28
+ end
29
+
30
+ # Convert input underscores to dashes.
31
+ #
32
+ # @param [String] input
33
+ # @return [String]
34
+ def self.dasherize(input)
35
+ input.tr('_', '-')
36
+ end
37
+
38
+ # Return unscoped constant name.
39
+ #
40
+ # @param [String] input
41
+ # @return [String]
42
+ def self.demodulize(input)
43
+ input.split('::').last
44
+ end
45
+
46
+ # Creates a foreign key name
47
+ #
48
+ # @param [String] input
49
+ # @return [String]
50
+ def self.foreign_key(input)
51
+ "#{underscorize(demodulize(input))}_id"
52
+ end
53
+
54
+ # Find a constant with the name specified in the argument string. The name is
55
+ # assumed to be the one of a top-level constant, constant scope of caller is
56
+ # igored.
57
+ #
58
+ # @param [String] input
59
+ # @return [Class, Module]
60
+ def self.constantize(input)
61
+ names = input.split('::')
62
+ names.shift if names.first.empty?
63
+
64
+ names.inject(Object) do |constant, name|
65
+ if constant.const_defined?(name)
66
+ constant.const_get(name)
67
+ else
68
+ constant.const_missing(name)
69
+ end
70
+ end
71
+ end
72
+
73
+ ORDINALIZE_TH = (4..16).to_set.freeze
74
+
75
+ # Convert a number into an ordinal string.
76
+ #
77
+ # @param [Fixnum] number
78
+ # @return [String]
79
+ def self.ordinalize(number)
80
+ abs_value = number.abs
81
+
82
+ if ORDINALIZE_TH.include?(abs_value % 100)
83
+ "#{number}th"
84
+ else
85
+ case abs_value % 10
86
+ when 1; "#{number}st"
87
+ when 2; "#{number}nd"
88
+ when 3; "#{number}rd"
89
+ end
90
+ end
91
+ end
92
+
93
+ # Convert input word string to plural
94
+ #
95
+ # @param [String] word
96
+ # @return [String]
97
+ def self.pluralize(word)
98
+ return word if uncountable?(word)
99
+ inflections.plurals.apply_to(word)
100
+ end
101
+
102
+ # Convert word to singular
103
+ #
104
+ # @param [String] word
105
+ # @return [String]
106
+ def self.singularize(word)
107
+ return word if uncountable?(word)
108
+ inflections.singulars.apply_to(word)
109
+ end
110
+
111
+ # Humanize string.
112
+ #
113
+ # @param [String] input
114
+ # @return [String]
115
+ def self.humanize(input)
116
+ result = inflections.humans.apply_to(input)
117
+ result.gsub!(/_id\z/, "")
118
+ result.tr!('_', " ")
119
+ result.capitalize!
120
+ result
121
+ end
122
+
123
+ # Tabelize input string.
124
+ #
125
+ # @param [String] input
126
+ # @return [String]
127
+ def self.tableize(input)
128
+ pluralize(underscore(input).gsub('/', '_'))
129
+ end
130
+
131
+ # Create a class name from a plural table name like Rails does for table
132
+ # names to models.
133
+ #
134
+ # @param [String] input
135
+ # @return [String]
136
+ def self.classify(table_name)
137
+ camelize(singularize(table_name.sub(/.*\./, '')))
138
+ end
139
+
140
+ # Test if word is uncountable.
141
+ #
142
+ # @param [String] word
143
+ # @return [Boolean] true, if word is uncountable
144
+ def self.uncountable?(word)
145
+ word.empty? || inflections.uncountables.include?(word.downcase)
146
+ end
147
+
148
+ # Convert input to underscored, lowercase string
149
+ #
150
+ # @param [String] input
151
+ # @return [String]
152
+ def self.underscorize(word)
153
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
154
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
155
+ word.tr!('-', '_')
156
+ word.downcase!
157
+ word
158
+ end
159
+ private_class_method :underscorize
160
+
161
+ # Yields a singleton instance of Inflecto::Inflections.
162
+ #
163
+ # @return [Inflections::Inflections]
164
+ def self.inflections
165
+ instance = Inflections.instance
166
+ block_given? ? yield(instance) : instance
167
+ end
168
+ end
169
+
170
+ require 'hoodie/inflections/rules_collection'
171
+ require 'hoodie/inflections/inflections'
172
+ require 'hoodie/inflections/defaults'
@@ -1,9 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Author: Tom Santos <santos.tom@gmail.com>
4
3
  # Author: Stefano Harding <riddopic@gmail.com>
5
4
  #
6
- # Copyright (C) 2012-2014 Tom Santos, Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
7
6
  #
8
7
  # Licensed under the Apache License, Version 2.0 (the "License");
9
8
  # you may not use this file except in compliance with the License.
@@ -22,53 +21,66 @@ require 'logger'
22
21
  require 'time'
23
22
 
24
23
  module Hoodie
25
- module Logging
24
+ module Log
25
+ @loggers ||= {}
26
+
27
+ def demodulize(class_name_in_module)
28
+ class_name_in_module.to_s.sub(/^.*::/, '')
29
+ end
30
+
26
31
  class << self
27
32
 
28
- # The Zero Log for Class
29
33
  class NoLogger < Logger
30
- def initialize(*args); end
31
- def add(*args, &block); end
34
+ def initialize(*args)
35
+ end
36
+
37
+ def add(*args, &block)
38
+ end
32
39
  end
33
40
 
34
- def no_logger
35
- @log ||= NoLogger.new
41
+ def demodulize(class_name_in_module)
42
+ class_name_in_module.to_s.sub(/^.*::/, '')
36
43
  end
37
44
 
38
- def log(log_prefix)
39
- @log ||= Logger.new($stdout).tap do |log|
40
- log.progname = self.class == Class ? self.to_s : self.class.to_s
41
- log.formatter = Hoodie::Formatter.new
42
- log.formatter.datetime_format = '%F %T'
43
- log.level = Logger::DEBUG
44
- end
45
+ def log(prefix)
46
+ @loggers[prefix] ||= logger_for(prefix)
47
+ end
48
+
49
+ def logger_for(prefix)
50
+
51
+ log = logger
52
+ log.progname = prefix
53
+ log.formatter = Hoodie::Formatter.new
54
+ log.formatter.datetime_format = '%F %T'
55
+ log.level = self.send(log_level)
56
+ log
45
57
  end
46
58
 
47
59
  def log=(log)
48
60
  @log = log
49
61
  end
50
62
 
51
- def log_prefix
52
- self.class == Class ? self.to_s : self.class.to_s
63
+ def logger
64
+ Hoodie.configuration.logging ? Logger.new($stdout) : NoLogger.new
53
65
  end
54
66
 
55
- def level
56
- "Logger::#{@level.to_s.upcase}"
67
+ def log_level
68
+ "Logger::#{Hoodie.configuration.level.to_s.upcase}"
57
69
  end
58
70
  end
59
71
 
60
72
  def self.included(base)
61
73
  class << base
62
74
  def log
63
- log_prefix = self.class == Class ? self.to_s : self.class.to_s
64
- Hoodie::Logging.log log_prefix
75
+ prefix = self.class == Class ? self.to_s : self.class.to_s
76
+ Hoodie::Logging.log(demodulize(prefix))
65
77
  end
66
78
  end
67
79
  end
68
80
 
69
81
  def log
70
- log_prefix = self.class == Class ? self.to_s : self.class.to_s
71
- Hoodie::Logging.log log_prefix
82
+ prefix = self.class == Class ? self.to_s : self.class.to_s
83
+ Hoodie::Logging.log(demodulize(prefix))
72
84
  end
73
85
  end
74
86
 
@@ -82,18 +94,16 @@ module Hoodie
82
94
 
83
95
  def call(severity, time, progname, msg)
84
96
  format % [
85
- format_datetime(time).BLUE,
86
- progname.CYAN,
87
- $$,
88
- severity.GREEN,
89
- msg2str(msg).strip.ORANGE
97
+ format_datetime(time).blue,
98
+ severity.green,
99
+ msg2str(msg).strip.orange
90
100
  ]
91
101
  end
92
102
 
93
103
  private # P R O P R I E T À P R I V A T A Vietato L'accesso
94
104
 
95
105
  def format
96
- "%s [%s#%d] %5s: %s\n"
106
+ "[%s] %5s: %s\n"
97
107
  end
98
108
 
99
109
  def format_datetime(time)
@@ -105,52 +115,3 @@ module Hoodie
105
115
  end
106
116
  end
107
117
  end
108
-
109
- class String
110
- def clear; colorize(self, "\e[0m"); end
111
- # Erase the current line of terminal output.
112
- def erase_line; colorize(self, "\e[K"); end
113
- # Erase the character under the cursor.
114
- def erase_char; colorize(self, "\e[P"); end
115
- # The start of an ANSI bold sequence.
116
- def bold; colorize(self, "\e[1m"); end
117
- # The start of an ANSI dark sequence.
118
- def dark; colorize(self, "\e[2m"); end
119
- # The start of an ANSI underline sequence.
120
- def underline; colorize(self, "\e[4m"); end
121
- # The start of an ANSI blink sequence.
122
- def blink; colorize(self, "\e[5m"); end
123
- # The start of an ANSI reverse sequence.
124
- def reverse; colorize(self, "\e[7m"); end
125
- # The start of an ANSI concealed sequence.
126
- def concealed; colorize(self, "\e[8m"); end
127
-
128
- # Set the terminal's foreground ANSI color to
129
- def BLACK; colorize(self, "\e[0;30m"); end
130
- def GRAY; colorize(self, "\e[1;30m"); end
131
- def RED; colorize(self, "\e[0;31m"); end
132
- def MAGENTA; colorize(self, "\e[1;31m"); end
133
- def GREEN; colorize(self, "\e[0;32m"); end
134
- def OLIVE; colorize(self, "\e[1;32m"); end
135
- def YELLOW; colorize(self, "\e[0;33m"); end
136
- def CREAM; colorize(self, "\e[1;33m"); end
137
- def BLUE; colorize(self, "\e[0;34m"); end
138
- def PURPLE; colorize(self, "\e[1;34m"); end
139
- def ORANGE; colorize(self, "\e[0;35m"); end
140
- def MUSTARD; colorize(self, "\e[1;35m"); end
141
- def CYAN; colorize(self, "\e[0;36m"); end
142
- def CYAN2; colorize(self, "\e[1;36m"); end
143
- def WHITE; colorize(self, "\e[0;97m"); end
144
-
145
- # Set the terminal's background ANSI color to
146
- def on_black; colorize(self, "\e[40m"); end
147
- def on_red; colorize(self, "\e[41m"); end
148
- def on_green; colorize(self, "\e[42m"); end
149
- def on_yellow; colorize(self, "\e[43m"); end
150
- def on_blue; colorize(self, "\e[44m"); end
151
- def on_magenta; colorize(self, "\e[45m"); end
152
- def on_cyan; colorize(self, "\e[46m"); end
153
- def on_white; colorize(self, "\e[47m"); end
154
-
155
- def colorize(text, color_code) "#{color_code}#{text}\e[0m" end
156
- end
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
data/lib/hoodie/os.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
data/lib/hoodie/rash.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
data/lib/hoodie/utils.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -18,5 +18,5 @@
18
18
  #
19
19
 
20
20
  module Hoodie
21
- VERSION = '0.4.6'
21
+ VERSION = '0.4.7'
22
22
  end
data/lib/hoodie.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author: Stefano Harding <riddopic@gmail.com>
4
4
  #
5
- # Copyright (C) 2014 Stefano Harding
5
+ # Copyright (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -17,9 +17,66 @@
17
17
  # limitations under the License.
18
18
  #
19
19
 
20
+ require 'hoodie/configuration'
21
+
22
+ module Hoodie
23
+
24
+ # Raised when errors occur during configuration.
25
+ ConfigurationError = Class.new(StandardError)
26
+
27
+ # Raised when an object's methods are called when it has not been
28
+ # properly initialized.
29
+ InitializationError = Class.new(StandardError)
30
+
31
+ # Raised when an operation times out.
32
+ TimeoutError = Class.new(StandardError)
33
+
34
+ class << self
35
+ # @param [TrueClass, FalseClass] sets the global logging configuration.
36
+ # @return [Hoodie]
37
+ # @api public
38
+ def logging=(value)
39
+ configuration.logging = value
40
+ self
41
+ end
42
+
43
+ # @return [TrueClass, FalseClass] the global logging setting.
44
+ # @api public
45
+ def logging
46
+ configuration.logging
47
+ end
48
+
49
+ # Provides access to the global configuration.
50
+ #
51
+ # @example
52
+ # Hoodie.config do |config|
53
+ # config.logging = true
54
+ # end
55
+ #
56
+ # @return [Configuration]
57
+ #
58
+ # @api public
59
+ def config(&block)
60
+ yield configuration if block_given?
61
+ configuration
62
+ end
63
+
64
+ # @return [Configuration] global configuration instance.
65
+ # @api private
66
+ def configuration
67
+ @configuration ||= Configuration.new
68
+ end
69
+ end
70
+ end
71
+
72
+ require 'hoodie/core_ext/string'
73
+ require 'hoodie/core_ext/blank'
74
+ require 'hoodie/core_ext/hash'
75
+
20
76
  require 'hoodie/stash/mem_store'
21
77
  require 'hoodie/stash/disk_store'
22
78
  require 'hoodie/identity_map'
79
+ require 'hoodie/inflections'
23
80
  require 'hoodie/memoizable'
24
81
  require 'hoodie/obfuscate'
25
82
  require 'hoodie/logging'
@@ -27,6 +84,4 @@ require 'hoodie/version'
27
84
  require 'hoodie/timers'
28
85
  require 'hoodie/utils'
29
86
  require 'hoodie/stash'
30
- require 'hoodie/blank'
31
- require 'hoodie/hash'
32
87
  require 'hoodie/os'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hoodie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.6
4
+ version: 0.4.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefano Harding
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-28 00:00:00.000000000 Z
11
+ date: 2015-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hitimes
@@ -30,84 +30,84 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.26.0
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.26.0
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 10.3.2
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 10.3.2
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: coveralls
56
+ name: yard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 0.7.1
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 0.7.1
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rspec
70
+ name: yard-redcarpet-ext
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: 3.1.0
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 3.1.0
82
+ version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: fuubar
84
+ name: redcarpet
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: 2.0.0
89
+ version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: 2.0.0
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: timecop
98
+ name: github-markup
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: 0.7.1
103
+ version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: 0.7.1
110
+ version: '0'
111
111
  description: A collection of hipster methods and hoodie tools to make even the nerdy
112
112
  rubyist look cool
113
113
  email: riddopic@gmail.com
@@ -123,9 +123,15 @@ files:
123
123
  - Rakefile
124
124
  - hoodie.gemspec
125
125
  - lib/hoodie.rb
126
- - lib/hoodie/blank.rb
127
- - lib/hoodie/hash.rb
126
+ - lib/hoodie/configuration.rb
127
+ - lib/hoodie/core_ext/blank.rb
128
+ - lib/hoodie/core_ext/hash.rb
129
+ - lib/hoodie/core_ext/string.rb
128
130
  - lib/hoodie/identity_map.rb
131
+ - lib/hoodie/inflections.rb
132
+ - lib/hoodie/inflections/defaults.rb
133
+ - lib/hoodie/inflections/inflections.rb
134
+ - lib/hoodie/inflections/rules_collection.rb
129
135
  - lib/hoodie/logging.rb
130
136
  - lib/hoodie/memoizable.rb
131
137
  - lib/hoodie/obfuscate.rb