Module: Hashmake::HashMakeable
- Defined in:
- lib/hashmake/hash_makeable.rb
Overview
This module should be included for any class that wants to be ‘hash-makeable’, which means that a new object instance expects all its arguments to come in a single Hash. See the hash_make method in this module and the ArgSpec class for more details.
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
-
.included(base) ⇒ Object
Use the included hook to also extend the including class with HashMake class methods.
Instance Method Summary collapse
-
#find_arg_specs ⇒ Object
Look in the current class for a constant that is a Hash containing (only) ArgSpec objects.
-
#hash_make(arg_specs, hashed_args, assign_args = true) ⇒ Object
Process a hash that contains ‘hashed args’.
-
#make_hash(arg_specs = nil) ⇒ Object
Produce a hash that contains ‘hashed args’.
-
#validate_arg(arg_spec, val) ⇒ Object
Check the given value, using the given ArgSpec object.
Class Method Details
.included(base) ⇒ Object
Use the included hook to also extend the including class with HashMake class methods
16 17 18 |
# File 'lib/hashmake/hash_makeable.rb', line 16 def self.included(base) base.extend(ClassMethods) end |
Instance Method Details
#find_arg_specs ⇒ Object
Look in the current class for a constant that is a Hash containing (only) ArgSpec objects. Returns the first constant matching this criteria, or nil if none was found.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/hashmake/hash_makeable.rb', line 111 def find_arg_specs self.class.constants.each do |constant| val = self.class.const_get(constant) if val.is_a? Hash all_arg_specs = true val.each do |key,value| unless value.is_a? ArgSpec all_arg_specs = false break end end if all_arg_specs return val end end end return nil end |
#hash_make(arg_specs, hashed_args, assign_args = true) ⇒ Object
Process a hash that contains ‘hashed args’. Each hashed arg is intended to be used in initializing an object instance.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/hashmake/hash_makeable.rb', line 31 def hash_make arg_specs, hashed_args, assign_args = true arg_specs.each do |key, arg_spec| raise ArgumentError, "arg_specs item #{arg_spec} is not a ArgSpec" unless arg_spec.is_a?(ArgSpec) end raise ArgumentError, "hashed_args is not a Hash" unless hashed_args.is_a?(Hash) arg_specs.each do |key, arg_spec| if hashed_args.has_key?(key) val = hashed_args[key] if Hashmake::hash_makeable?(arg_spec.type) # If the val is not of the right type, but is a Hash, attempt to # make an object of the right type if it is hash-makeable if arg_spec.container == Array && val.is_a?(Array) val.each_index do |i| item = val[i] if !item.is_a?(arg_spec.type) && item.is_a?(Hash) val[i] = arg_spec.type.new item end end elsif arg_spec.container == Hash && val.is_a?(Hash) val.each_key do |item_key| item = val[item_key] if !item.is_a?(arg_spec.type) && item.is_a?(Hash) val[item_key] = arg_spec.type.new item end end else if !val.is_a?(arg_spec.type) && val.is_a?(Hash) val = arg_spec.type.new val end end end else if arg_spec.reqd raise ArgumentError, "hashed_args does not have required key #{key}" else if arg_spec.default.is_a?(Proc) && arg_spec.type != Proc val = arg_spec.default.call else val = arg_spec.default end end end validate_arg arg_spec, val if assign_args self.instance_variable_set("@#{key.to_s}".to_sym, val) end end end |
#make_hash(arg_specs = nil) ⇒ Object
Produce a hash that contains ‘hashed args’. Each hashed arg is intended to be used in initializing an object instance.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/hashmake/hash_makeable.rb', line 141 def make_hash arg_specs = nil if arg_specs.nil? arg_specs = self.find_arg_specs raise "No arg specs given, and no class constant that is a Hash containing only ArgSpec objects was found" if arg_specs.nil? end arg_specs.each do |key, arg_spec| raise ArgumentError, "arg_specs item #{arg_spec} is not a ArgSpec" unless arg_spec.is_a?(ArgSpec) end hash = {} arg_specs.each do |key, arg_spec| sym = "@#{key}".to_sym raise ArgumentError, "current obj #{self} does not include instance variable #{sym}" if !self.instance_variables.include?(sym) val = self.instance_variable_get(sym) should_assign = false if arg_spec.reqd should_assign = true else if arg_spec.default.is_a?(Proc) should_assign = (val != arg_spec.default.call) else should_assign = (val != arg_spec.default) end end if should_assign if val.is_a?(Array) && arg_spec.container == Array ary = val val = [] ary.each do |item| if Hashmake::hash_makeable?(item.class) and item.class == arg_spec.type val << item.make_hash else val << item end end elsif val.is_a?(Hash) && arg_spec.container == Hash hsh = val val = {} hsh.each do |hsh_key,item| if Hashmake::hash_makeable? item.class and item.class == arg_spec.type val[hsh_key] = item.make_hash else val[hsh_key] = item end end elsif Hashmake::hash_makeable?(val.class) and item.class == arg_spec.type val = val.make_hash end hash[key] = val end end return hash end |
#validate_arg(arg_spec, val) ⇒ Object
Check the given value, using the given ArgSpec object. An ArgumentError exception will be raised if the value is not valid.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/hashmake/hash_makeable.rb', line 85 def validate_arg arg_spec, val if arg_spec.container == Array raise ArgumentError, "val #{val} is not an array" unless val.is_a?(Array) val.each do |item| raise ArgumentError, "array item #{item} is not a #{arg_spec.type}" unless item.is_a?(arg_spec.type) raise ArgumentError, "array item #{item} is not valid" unless arg_spec.validator.call(item) end elsif arg_spec.container == Hash raise ArgumentError, "val #{val} is not a hash" unless val.is_a?(Hash) val.values.each do |item| raise ArgumentError, "hash item #{item} is not a #{arg_spec.type}" unless item.is_a?(arg_spec.type) raise ArgumentError, "hash item #{item} is not valid" unless arg_spec.validator.call(item) end elsif arg_spec.container.nil? raise ArgumentError, "val #{val} is not a #{arg_spec.type}" unless val.is_a?(arg_spec.type) raise ArgumentError, "val #{val} is not valid" unless arg_spec.validator.call(val) else raise ArgumentError, "arg_spec.container #{arg_spec.container} is not valid" end return true end |