Module: Smash::CloudPowers::Helper

Instance Method Summary collapse

Instance Method Details

#attr_map!(keys) ⇒ Object

Sets an Array of instance variables, individually to a value that a user given block returns.

Parameters

  • keys Array

    • each object will be used as the name for the instance variable that your block returns block (optional)
    • this block is called for each object in the Array and is used as the value for the instance variable that is being named and created for each key Returns Array
    • each object will either be the result of #instance_variable_set(key, value) or instance_variable_get(key) Example keys = ['foo', 'bar', 'yo']

    attr_map!(keys) { |key| sleep 1; "#key:#Time.now.to_i" }

    => ['foo:1475434058', 'bar:1475434059', 'yo:1475434060']

    puts @bar

    => 'bar:1475434059'



34
35
36
37
38
39
40
# File 'lib/cloud_powers/helper.rb', line 34

def attr_map!(keys)
  keys.map do |key|
    new_i_var = to_i_var(key)
    value = yield key if block_given?
    instance_variable_set(new_i_var, value) unless instance_variable_get(new_i_var)
  end
end

#available_resources ⇒ Object

This is a way to find out if you are trying to work with a resource available to CloudPowers

Returns Use .constants to find all the modules and classes available.

Notes

  • TODO: make this smartly pick up all the objects, within reason and considering need, that we have access to


51
52
53
# File 'lib/cloud_powers/helper.rb', line 51

def available_resources
  [:Task].concat(Smash::CloudPowers.constants)
end

#called_from ⇒ Object

Does its best job at guessing where this method was called from, in terms of where it is located on the file system. It helps track down where a project root is etc.

Returns String

Notes

  • Uses $0 to figure out what the current file is


64
65
66
# File 'lib/cloud_powers/helper.rb', line 64

def called_from
  File.expand_path(File.dirname($0))
end

#create_logger(log_to = STDOUT) ⇒ Object

creates a default logger

Parameters

  • log_to String (optional) - location to send logging information to; default is STDOUT

Returns Logger

Notes

  • TODO: at least make this have overridable defaults


78
79
80
81
82
# File 'lib/cloud_powers/helper.rb', line 78

def create_logger(log_to = STDOUT)
  logger = Logger.new(log_to)
  logger.datetime_format = '%Y-%m-%d %H:%M:%S'
  logger
end

#deep_modify_keys_with(params) ⇒ Object

Allows you to modify all keys, including nested, with a block that you pass. If no block is passed, a copy is returned.

Parameters

  • params +Hash+|+Array+ - hash to be modified
  • block (optional) - a block to be used to modify each key should modify the key and return that value so it can be used in the copy

Returns +Hash+|+Array+ - a copy of the given Array or Hash, with all Hash keys modified

Example hash = { 'foo' => 'v1', 'bar' => { fleep: { 'florp' => 'yo' } } } modify_keys_with(hash) { |key| key.to_sym }

=> { foo: 'v1', bar: { fleep: { florp: 'yo' } } }

Notes

  • see #modify_keys_with() for handling first-level keys
  • see #pass_the_buck() for the way nested structures are handled
  • case for different types taken from MultiXML (multi_xml.rb)
  • TODO: look at optimization


105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/cloud_powers/helper.rb', line 105

def deep_modify_keys_with(params)
  case params
  when Hash
    params.inject({}) do |carry, (k, v)|
      carry.tap do |h|
        if block_given?
          key = yield k

          value = if v.kind_of?(Hash)
              deep_modify_keys_with(v) { |new_key| Proc.new.call(new_key) }
            else
              v
            end

          h[key] = value
        else
          h[k] = v
        end
      end
    end
  when Array
    params.map{ |value| symbolize_keys(value) }
  else
    params
  end
end

#format_error_message(error) ⇒ Object

Join the message and backtrace into a String with line breaks

Parameters

  • error Exception

Returns String



139
140
141
142
143
144
145
146
# File 'lib/cloud_powers/helper.rb', line 139

def format_error_message(error)
  begin
    [error.message, error.backtrace.join("\n")].join("\n")
  rescue Exception
    # if the formatting won't work, return the original exception
    error
  end
end

#log_file ⇒ Object

Gets the path from the environment and sets @log_file using the path

Returns Notes

  • See #zfind()


155
156
157
# File 'lib/cloud_powers/helper.rb', line 155

def log_file
  @log_file ||= zfind('LOG_FILE')
end

#logger ⇒ Object

Returns An instance of Logger, cached as @logger@log_file path

Returns Logger

Notes

  • See #create_logger


166
167
168
# File 'lib/cloud_powers/helper.rb', line 166

def logger
  @logger ||= create_logger
end

#modify_keys_with(params) ⇒ Object

Allows you to modify all first-level keys with a block that you pass. If no block is passed, a copy is returned.

Parameters

  • params +Hash+|+Array+
  • block (optional) - should modify the key and return that value so it can be used in the copy

Returns +Hash+|+Array+ - a copy of the given Array or Hash, with all Hash keys modified

Example hash = { 'foo' => 'v1', 'bar' => { fleep: { 'florp' => 'yo' } } } modify_keys_with(hash) { |k| k.to_sym }

=> { :foo => 'v1', :bar => { fleep: { 'florp' => 'yo' } } }

Notes

  • see #deep_modify_keys_with() for handling nested keys
  • case for different types taken from MultiXML (multi_xml.rb)


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

def modify_keys_with(params)
  params.inject({}) do |carry, (k, v)|
    carry.tap do |h|
      key = block_given? ? (yield k) : k
      h[key] = v
    end
  end
end

#smart_retry(test, allowed_attempts = Float::INFINITY) ⇒ Object

Lets you retry a piece of logic with 1 second sleep in between attempts until another bit of logic does what it's supposed to, kind of like continuing to poll something and doing something when a package is ready to be taken and processed.

Parameters

  • allowed_attempts +Number+|+Infinity(default)+ - The number of times the loop should be allowed to...well, loop, before a failed retry occurs.
  • &test Block - A predicate method or block of code that is callable is used to test if the block being retried is successful yet.
  • []

Example check_stuff = lambda { |params| return true } smart_retry(3, check_stuff(params)) { do_stuff_that_needs_to_be_checked }



212
213
214
215
216
217
218
219
220
# File 'lib/cloud_powers/helper.rb', line 212

def smart_retry(test, allowed_attempts = Float::INFINITY)
  result = yield if block_given?
  tries = 1
  until test.call(result) || tries >= allowed_attempts
    result = yield if block_given?
    tries += 1
    sleep 1
  end
end

#task_exist?(file) ⇒ Boolean

Check if the task file exists in the task directory

Parameters

  • file String

Returns Boolean

Notes

  • See #task_home()

Returns:

  • (Boolean)


271
272
273
274
275
276
277
278
# File 'lib/cloud_powers/helper.rb', line 271

def task_exist?(file)
  begin
    File.new("#{task_home}/#{file}")
    true
  rescue Errno::ENOENT
    false
  end
end

#task_home ⇒ Object

Gives a common home for tasks to live so they can be easily grouped and found. This method will create nested directories, based on the #project_root() method and an additional 'lib/tasks' directory. If no project root has been set by the time this method is called, a new directory will be created relative to the gem's project root.

Returns String

Notes

  • If no project root has been set by the time this method is called, a new

    directory will be created relative to the gem's project root. This might have deeper implications than you want to deal with so it's always a good idea to set your project root as soon as you can.
  • TODO: find a way to have this method figure out the actual project's root, as opposed to just making common "good" assumptions.


238
239
240
241
# File 'lib/cloud_powers/helper.rb', line 238

def task_home
  string_th = FileUtils.mkdir_p("#{project_root}/lib/tasks/").first
  @task_home ||= Pathname.new(string_th).realpath.to_s
end

#task_path(file = '') ⇒ Object

Gives the path from the project root to lib/tasks

Parameters

  • file String (optional) (default is '') - name of a file

Returns

  • path/file String if file parameter is given. return has '.rb' extension included
  • file String if file parameter is not given it will return the #task_require_path()

Notes

  • See #task_home


255
256
257
258
# File 'lib/cloud_powers/helper.rb', line 255

def task_path(file = '')
 return task_home if file.empty?
  Pathname.new("#{task_home}/#{file}").to_s
end

#task_require_path(file_name = '') ⇒ Object

Gives the path from the project root to lib/tasks

Parameters String (optional)

  • file_name name of a file

Returns

  • path/file String if file_name was given
  • path to task_directory if file_name was not given

Notes

  • Neither path nor file will have a file extension
  • See #task_home


292
293
294
295
296
297
298
299
# File 'lib/cloud_powers/helper.rb', line 292

def task_require_path(file_name = '')
  begin
    file_sans_extension = File.basename(file_name, '.*')
    (Pathname.new(task_home) + file_sans_extension).to_s
  rescue Errno::ENOENT
    nil
  end
end

#to_camel(var) ⇒ Object

Change strings into camelCase

Parameters

  • var String

Returns String



308
309
310
311
312
313
# File 'lib/cloud_powers/helper.rb', line 308

def to_camel(var)
  var = var.to_s unless var.kind_of? String
  step_one = to_snake(var)
  step_two = to_pascal(step_one)
  step_two[0, 1].downcase + step_two[1..-1]
end

#to_hyph(var) ⇒ Object

Change strings into a hyphen delimited phrase

Parameters

  • var String

Returns String



322
323
324
325
326
327
328
329
330
331
332
# File 'lib/cloud_powers/helper.rb', line 322

def to_hyph(var)
  var = var.to_s unless var.kind_of? String

  var.gsub(/:{2}|\//, '-').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    gsub(/\s+/, '-').
    tr("_", "-").
    gsub(/^\W/, '').
    downcase
end

#to_i_var(var) ⇒ Object

Change strings into an i-var format

Parameters

  • var String

Returns String



341
342
343
344
# File 'lib/cloud_powers/helper.rb', line 341

def to_i_var(var)
  var = var.to_s unless var.kind_of? String
  /^\W*@\w+/ =~ var ? to_snake(var) : "@#{to_snake(var)}"
end

#to_pascal(var) ⇒ Object

Change strings into PascalCase

Parameters

  • var String

Returns String



353
354
355
356
# File 'lib/cloud_powers/helper.rb', line 353

def to_pascal(var)
  var = var.to_s unless var.kind_of? String
  var.gsub(/^(.{1})|\W.{1}|\_.{1}/) { |s| s.gsub(/[^a-z0-9]+/i, '').capitalize }
end

#to_ruby_file_name(name) ⇒ Object

Change strings into a ruby_file_name with extension

Parameters

  • var String

Returns String

Notes

  • given_string.rb
  • includes ruby file extension
  • see #to_snake()


370
371
372
# File 'lib/cloud_powers/helper.rb', line 370

def to_ruby_file_name(name)
  name[/\.rb$/].nil? ? "#{to_snake(name)}.rb" : "#{to_snake(name)}"
end

#to_snake(var) ⇒ Object

Change strings into PascalCase

Parameters

  • var String

Returns String

Notes

  • given_string
  • will not have file extensions
  • see #to_ruby_file_name()


386
387
388
389
390
391
392
393
394
395
# File 'lib/cloud_powers/helper.rb', line 386

def to_snake(var)
  var = var.to_s unless var.kind_of? String

  var.gsub(/:{2}|\//, '_').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    gsub(/\s+/, '_').
    tr("-", "_").
    downcase
end

#update_message_body(opts = {}) ⇒ Object

This method provides a default overrideable message body for things like basic status updates.

Parameters

  • instanceId Hash

Notes

  • camel casing is used on the keys because most other languages prefer that and it's not a huge problem in ruby. Besides, there's some other handy methods in this module to get you through those issues, like #to_snake() and or #modify_keys_with()


408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'lib/cloud_powers/helper.rb', line 408

def update_message_body(opts = {})
  # TODO: Better implementation of merging message bodies and config needed
  unless opts.kind_of? Hash
    update = opts.to_s
    opts = {}
    opts[:extraInfo] = { message: update }
  end
  updated_extra_info = opts.delete(:extraInfo) || {}

  {
    instanceId:       @instance_id || 'none-aquired',
    type:             'status-update',
    content:          'running',
    extraInfo:        updated_extra_info
  }.merge(opts)
end

#valid_json?(json) ⇒ Boolean

Predicate method to check if a String is parsable, as JSON

Parameters

  • json String

Returns Boolean

Returns:

  • (Boolean)


432
433
434
435
436
437
438
439
# File 'lib/cloud_powers/helper.rb', line 432

def valid_json?(json)
  begin
    JSON.parse(json)
    true
  rescue Exception
    false
  end
end

#valid_url?(url) ⇒ Boolean

Predicate method to check if a String is a valid URL

Parameters

  • url String

Returns Boolean

Returns:

  • (Boolean)


448
449
450
# File 'lib/cloud_powers/helper.rb', line 448

def valid_url?(url)
  url =~ /\A#{URI::regexp}\z/
end