Module: Doodle::Utils

Included in:
XML
Defined in:
lib/doodle.rb,
lib/doodle.rb

Overview

A factory function is a function that has the same name as a class which acts just like class.new. For example:

Cat(:name => 'Ren')

is the same as:

Cat.new(:name => 'Ren')

As the notion of a factory function is somewhat contentious [xref ruby-talk], you need to explicitly ask for them by including Factory in your base class:

class Animal < Doodle
  include Factory
end
class Dog < Animal
end
stimpy = Dog(:name => 'Stimpy')

etc.

Class Method Summary collapse

Class Method Details

.const_lookup(const, context = self) ⇒ Object

lookup a constant along the module nesting path

Raises:

  • (NameError)


1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
# File 'lib/doodle.rb', line 1115

def const_lookup(const, context = self)
  #p [:const_lookup, const, context]
  const = Utils.normalize_const(const)
  result = nil
  if !context.kind_of?(Module)
    context = context.class
  end
  klasses = context.to_s.split(/::/)
  #p klasses

  path = []
  0.upto(klasses.size - 1) do |i|
    path << Doodle::Utils.const_resolve(klasses[0..i].join('::'))
  end
  path = (path.reverse + context.ancestors).flatten
  #p [:const, context, path]
  path.each do |ctx|
    #p [:checking, ctx]
    if ctx.const_defined?(const)
      result = ctx.const_get(const)
      break
    end
  end
  raise NameError, "Uninitialized constant #{const} in context #{context}" if result.nil?
  result
end

.const_resolve(constant) ⇒ Object

resolve a constant of the form Some::Class::Or::Module - doesn’t work with constants defined in anonymous classes/modules



115
116
117
# File 'lib/doodle.rb', line 115

def const_resolve(constant)
  constant.to_s.split(/::/).reject{|x| x.empty?}.inject(Object) { |prev, this| prev.const_get(this) }
end

.deep_copy(obj) ⇒ Object

deep copy of object (unlike shallow copy dup or clone)



119
120
121
# File 'lib/doodle.rb', line 119

def deep_copy(obj)
  Marshal.load(Marshal.dump(obj))
end

.doodle_callerObject

caller



188
189
190
191
192
193
194
# File 'lib/doodle.rb', line 188

def doodle_caller
  if $DEBUG
    caller
  else
    [caller[-1]]
  end
end

.flatten_first_level(enum) ⇒ Object

Unnest arrays by one level of nesting, e.g. [1, [[2], 3]] => [1, [2], 3].



94
95
96
97
98
99
100
101
102
# File 'lib/doodle.rb', line 94

def flatten_first_level(enum)
  enum.inject([]) {|arr, i|
    if i.kind_of?(Array)
      arr.push(*i)
    else
      arr.push(i)
    end
  }
end

.normalize_const(const) ⇒ Object

normalize a name to contain only legal characters for a Ruby constant



1110
1111
1112
# File 'lib/doodle.rb', line 1110

def self.normalize_const(const)
  const.to_s.gsub(/[^A-Za-z_0-9]/, '')
end

.normalize_keys(hash, recursive = false, method = :to_sym) ⇒ Object

normalize hash keys using method (e.g. :to_sym, :to_s)

  • returns copy of hash

  • optionally recurse into child hashes



145
146
147
148
149
150
151
152
# File 'lib/doodle.rb', line 145

def normalize_keys(hash, recursive = false, method = :to_sym)
  if recursive
    h = deep_copy(hash)
  else
    h = hash.dup
  end
  normalize_keys!(h, recursive, method)
end

.normalize_keys!(hash, recursive = false, method = :to_sym) ⇒ Object

normalize hash keys using method (e.g. :to_sym, :to_s)

  • updates target hash

  • optionally recurse into child hashes



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/doodle.rb', line 125

def normalize_keys!(hash, recursive = false, method = :to_sym)
  if hash.kind_of?(Hash)
    hash.keys.each do |key|
      normalized_key = key.respond_to?(method) ? key.send(method) : key
      v = hash.delete(key)
      if recursive
        if v.kind_of?(Hash)
          v = normalize_keys!(v, recursive, method)
        elsif v.kind_of?(Array)
          v = v.map{ |x| normalize_keys!(x, recursive, method) }
        end
      end
      hash[normalized_key] = v
    end
  end
  hash
end

.pluralize(string) ⇒ Object

simple (!) pluralization - if you want fancier, override this method



178
179
180
181
182
183
184
185
# File 'lib/doodle.rb', line 178

def pluralize(string)
  s = string.to_s
  if s =~ /s$/
    s + 'es'
  else
    s + 's'
  end
end

.snake_case(camel_cased_word) ⇒ Object

from facets/string/case.rb, line 80



104
105
106
107
108
109
110
111
# File 'lib/doodle.rb', line 104

def snake_case(camel_cased_word)
  # if all caps, just downcase it
  if camel_cased_word =~ /^[A-Z]+$/
    camel_cased_word.downcase
  else
    camel_cased_word.to_s.gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
  end
end

.stringify_keys(hash, recursive = false) ⇒ Object

convert keys to strings

  • returns copy of hash

  • optionally recurse into child hashes



174
175
176
# File 'lib/doodle.rb', line 174

def stringify_keys(hash, recursive = false)
  normalize_keys(hash, recursive, :to_s)
end

.stringify_keys!(hash, recursive = false) ⇒ Object

convert keys to strings

  • updates target hash in place

  • optionally recurse into child hashes



168
169
170
# File 'lib/doodle.rb', line 168

def stringify_keys!(hash, recursive = false)
  normalize_keys!(hash, recursive, :to_s)
end

.symbolize_keys(hash, recursive = false) ⇒ Object

convert keys to symbols

  • returns copy of hash

  • optionally recurse into child hashes



162
163
164
# File 'lib/doodle.rb', line 162

def symbolize_keys(hash, recursive = false)
  normalize_keys(hash, recursive, :to_sym)
end

.symbolize_keys!(hash, recursive = false) ⇒ Object

convert keys to symbols

  • updates target hash in place

  • optionally recurse into child hashes



156
157
158
# File 'lib/doodle.rb', line 156

def symbolize_keys!(hash, recursive = false)
  normalize_keys!(hash, recursive, :to_sym)
end