Module: Finest::Helper
Overview
Finest Builder
Instance Method Summary collapse
-
#accessor_builder(key, val) ⇒ Object
Builds an instance variable as well as its class method accessors from a key value pair.
- #attribute_from_inner_key(elem, attr, in_key = nil) ⇒ Object
-
#build_by_keys(json = {}, keys = []) {|_self| ... } ⇒ Object
Parses a given json structure looking for specific keys inside the structure if passed.
- #method_missing(name, *args) ⇒ Object
-
#nested_hash_value(obj, key) ⇒ Object
Goes through a complex Hash nest and gets the value of a passed key.
- #respond_to_missing?(method_name, include_private = false) ⇒ Boolean
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args) ⇒ Object
94 95 96 |
# File 'lib/finest/builder.rb', line 94 def method_missing(name, *args) accessor_builder(name.to_s.gsub(/=$/, ''), args[0]) if name.to_s =~ /=$/ end |
Instance Method Details
#accessor_builder(key, val) ⇒ Object
Builds an instance variable as well as its class method accessors from a key value pair.
47 48 49 50 51 |
# File 'lib/finest/builder.rb', line 47 def accessor_builder(key, val) instance_variable_set("@#{key}", val) self.class.send(:define_method, key.to_s, proc { instance_variable_get("@#{key}") }) self.class.send(:define_method, "#{key}=", proc { |val| instance_variable_set("@#{key}", val) }) end |
#attribute_from_inner_key(elem, attr, in_key = nil) ⇒ Object
102 103 104 |
# File 'lib/finest/builder.rb', line 102 def attribute_from_inner_key(elem, attr, in_key = nil) { attr.to_sym => nested_hash_value(elem, in_key&.present? ? in_key : attr.to_s) } end |
#build_by_keys(json = {}, keys = []) {|_self| ... } ⇒ Object
Parses a given json structure looking for specific keys inside the structure if passed
The result it’s stored on a instance variable called to_h and accessible through accessor with same name as well as it created a instance method for every key. All methods are created using the snake case approach.
e = MyObjectBuilder.new({"client"=> {"idSA"=>1,"id"=>3434, "ManagementType"=>"iOSUnsupervised"}})
Result:
e.client.to_h[:id_sa]
e.client.id_sa
Any key value less than three characters will just be down cased.
e.client.to_h[:id]
e.client.id
32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/finest/builder.rb', line 32 def build_by_keys(json = {}, keys = []) keys = keys.empty? ? json.keys : keys raise ArgumentError unless keys&.respond_to?(:each) json.transform_keys!(&:to_s) keys&.reject! { |key| key.end_with?('=') } keys&.each do |key| send("#{key.to_s.snake_case}=", nested_hash_value(json, key.to_s)) end yield self if block_given? self end |
#nested_hash_value(obj, key) ⇒ Object
Goes through a complex Hash nest and gets the value of a passed key. First wil check whether the object has the key? method, which will mean it’s a Hash and also if the Hash the method parameter key
if obj.respond_to?(:key?) && obj.key?(key)
If result object is a hash itself, will call constructor method to parse this hash first.
if obj[key].is_a?(Hash)
self.class.new(obj[key])
If it’s an array, will call the constructor method for each element of the array, mapping the result.
elsif (obj[key].is_a?(Array))
As mentioned before, this methods looks for the key passed as parameter, if it’s not found, will go through the nested hash looking for the key, calling itself recursively.
This way we can look for specific keys inside a complex hash structure and ignore the rest. The result of this action will be an object with the keys found and their values. If eventually the keys was not found, it will assign nil to the instance variable.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/finest/builder.rb', line 74 def nested_hash_value(obj, key) if obj.respond_to?(:key?) && obj.key?(key) if obj[key].is_a?(Hash) self.class.new(obj[key]) elsif (obj[key].is_a?(Array)) obj[key].map! do |a| a.respond_to?(:key?) ? self.class.new(a) : a end else obj[key] end elsif obj.respond_to?(:each) r = nil obj.find do |*a| r = nested_hash_value(a.last, key) end r end end |
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
98 99 100 |
# File 'lib/finest/builder.rb', line 98 def respond_to_missing?(method_name, include_private = false) method_name.to_s.start_with?('to_') || super end |