Module: Hashstructor::InstanceMethods
- Included in:
- Hashstructor
- Defined in:
- lib/hashstructor/instance_methods.rb
Overview
Instance methods for Hashstructor objects.
Instance Method Summary collapse
-
#hashstruct(hash) ⇒ Object
private
Constructs the object from the given hash, based on the metadata fed in by ClassMethods#member invocations.
-
#initialize(hash) ⇒ Object
private
Initializes the object.
-
#to_h ⇒ Object
Converts the class back to a hash.
-
#to_hash ⇒ Object
Converts the class back to a hash.
Instance Method Details
#hashstruct(hash) ⇒ Object (private)
Constructs the object from the given hash, based on the metadata fed in by ClassMethods#member invocations.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 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 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/hashstructor/instance_methods.rb', line 71 def hashstruct(hash) raise HashstructorError, "hashstruct expects a hash." unless hash.is_a?(Hash) members = self.class.hashstructor_members # This could be done inline, but I'd rather loop twice and get this check # out of the way ahead of time because of the perf hit when dealing with # deeply nested structures. partitioned_members = members.partition { |m| !hash[m.name].nil? || !hash[m.name.to_s].nil? } existing_members = partitioned_members[0] missing_members = partitioned_members[1] partitioned_missing_members = missing_members.partition { |m| !m.required || (m.required && !m.[:default_value].nil?) } acceptable_missing_members = partitioned_missing_members[0] unacceptable_missing_members = partitioned_missing_members[1] raise HashstructorError, "Missing required members: #{unacceptable_missing_members.map { |m| m.name }.join(", ")}" \ unless unacceptable_missing_members.empty? acceptable_missing_members.each do |member| out_value = case member.member_type when :normal member.[:default_value] when :array [] when :set Set.new when :hash {} end instance_variable_set("@#{member.name}", out_value) end existing_members.each do |member| raw_value = hash[member.name] if raw_value.nil? raw_value = hash[member.name.to_s] end out_value = nil case member.member_type when :normal raise HashstructorError, "member '#{member.name}' expects a single value, got #{raw_value.class.name}." \ if member.[:no_collections] && raw_value.is_a?(Enumerable) out_value = member.parse_single(raw_value) when :hash raise HashstructorError, "member '#{member.name}' expects a Hash, got #{raw_value.class.name}." \ unless raw_value.is_a?(Hash) out_value = {} raw_value.each_pair do |k, v| key = member.[:string_keys] ? k.to_s : k.to_s.to_sym out_value[key] = member.parse_single(v) end when :array, :set raise HashstructorError, "member '#{member.name}' expects an Enumerable, got #{raw_value.class.name}"\ unless raw_value.is_a?(Enumerable) out_value = raw_value.map { |v| member.parse_single(v) } out_value = out_value.to_set if member.member_type == :set end instance_variable_set("@#{member.name}", out_value) end end |
#initialize(hash) ⇒ Object (private)
Initializes the object. This exists for objects that prepend
Hashstructor; objects that include it must explicitly invoke
#hashstruct within their own initialize method.
63 64 65 |
# File 'lib/hashstructor/instance_methods.rb', line 63 def initialize(hash) hashstruct(hash) end |
#to_h ⇒ Object
Converts the class back to a hash.
11 12 13 |
# File 'lib/hashstructor/instance_methods.rb', line 11 def to_h to_hash end |
#to_hash ⇒ Object
Converts the class back to a hash.
18 19 20 21 22 23 24 25 26 27 28 29 30 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 |
# File 'lib/hashstructor/instance_methods.rb', line 18 def to_hash hash = {} self.class.hashstructor_members.each do |member| member_value = instance_variable_get("@#{member.name}") out_value = case member.member_type when :normal member_value.nil? ? nil : member.to_hash_value(member_value) when :array # There's some weird Ruby thing I don't get here, but if I use # a #select instead of an each + container, I end up returning # the actual objects rather than their to_hashes. container = [] member_value.each do |v| container << member.to_hash_value(v) end container when :set container = Set.new member_value.each do |v| container << member.to_hash_value(v) end container when :hash container = {} member_value.each do |k, v| container[k] = member.to_hash_value(v) end container end hash[member.name.to_sym] = out_value end hash end |