Project

General

Profile

Bug #11656 » model.rb

dgreenbe77 (Daniel Greenberg), 11/04/2015 06:11 PM

 
require 'active_support/inflector'

module Frederick
module Models
class Model
def initialize(options = {})
options.each do |key, value|
send(:"#{key}=", value)
end
end

def to_hash
hash = {}
self.instance_variables.each do |var|
value = self.instance_variable_get var
if value.is_a? Array
new_value = hash_list(value)
elsif value.is_a? Frederick::Models::Model
new_value = value.to_hash
else
new_value = value
end
hash[var[1..-1]] = new_value
end
hash
end

def to_json
Oj.dump(to_hash, mode: :compat)
end

def attr_values
attr_values = {}
self.class::ATTRS.each do |name|
instance_var_value = instance_variable_get("@#{name}")
attr_values[name] = instance_var_value unless instance_var_value.nil?
end
attr_values
end

# Built in Hash#hash method returns diff code across ruby instances
# See: http://stackoverflow.com/questions/6783811/why-is-ruby-string-hash-inconsistent-across-machines
# Instead use MD5 to ensure hashes for objects with same state (instance_values) are always the same
# Use MD5 hashing algorithm over SHA because it is faster
# Chance of collision using MD5 is still infinitesimally small (1/2^128)

# WARNING! CHANGING ORDER OF WHEN YOUR INSTANCE VARS ARE DEFINED
# OR CHANGING WHICH INSTANCE VARS ARE SET PER INSTANCE
# WILL RETURN NEW HASH CODES
# AS THIS WILL CHANGE THE INSTANCE VALUES STRING THAT IS PASSED INTO THE DIGEST ROUTINE
def hash; Digest::MD5.hexdigest(attr_values.to_s); end

def self.hash_codes_with_index(models)
hash_code_map = {}
models.each_with_index { |model, i| hash_code_map[model.hash] = i }
hash_code_map
end

def self.from_hash(hash)
model = self.new
hash.each do |key, value|
if model.respond_to?(:"#{key}")
constantized = self.constantize(key)
if constantized
if value.is_a? Array
model.send(:"#{key}=", constantized.from_list(value))
else
model.send(:"#{key}=", constantized.from_hash(value))
end
else
model.send(:"#{key}=", value)
end
end
end
model
end

def self.from_list(array)
list = []
array.each do |item|
model = self.from_hash(item)
list << model
end
list
end

def self.constantize(key)
begin
Frederick::Models.const_get("Frederick::Models::#{ActiveSupport::Inflector.camelize(ActiveSupport::Inflector.singularize("#{key}"))}")
rescue NameError
nil
end
end

private

def hash_list(array)
list = []
array.each do |item|
if item.is_a? Array
list << hash_list(item)
elsif item.is_a? Frederick::Models::Model
list << item.to_hash
else
list << item
end
end
list
end
end
end
end
(1-1/3)