./lib/overload/hash.rb in lux-fw-0.5.37 vs ./lib/overload/hash.rb in lux-fw-0.6.2
- old
+ new
@@ -1,121 +1,39 @@
-# frozen_string_literal: true
-
-require_relative '../common/free_struct'
-
class Hash
- def h
- Hashie::Mash.new(self)
- end
-
- def h_wia
- HashWithIndifferentAccess.new(self)
- end
-
- # readonly hash with .to_h
- def to_readonly name=nil
- Class.new.tap do |c|
- c.define_singleton_method(:to_h) do
- m_list = methods(false) - [:to_h]
- m_list.inject({}) do |h,m|
- h[m] = send(m)
- h[m] = h[m].to_h if h[m].class == Class
- h
- end
- end
-
- each do |k, v|
- v = v.to_readonly if v.class == Hash
- c.define_singleton_method(k) { v }
- end
- end
- end
-
- # {...}.to_opts :name, :age
- # {...}.to_opts name: String, age: Integer
- def to_opts *keys
- if keys.first.is_a?(Hash)
- # if given Hash check opt class types
- keys.first.each do |key, target_class|
- source = self[key]
-
- if target_class && !source.nil? && !source.is_a?(target_class)
- raise ArgumentError.new(%[Expected argument :#{key} to be of type "#{target_class}" not "#{source.class}"])
- end
- end
-
- keys = keys.first.keys
- end
-
- not_allowed = self.keys - keys
- raise ArgumentError.new('Key :%s not allowed in option' % not_allowed.first) if not_allowed.first
-
- FreeStruct.new keys.inject({}) { |total, key|
- raise 'Hash key :%s is not allowed!' % key unless keys.include?(key)
- total[key] = self[key]
- total
- }
- end
-
- def to_struct
- to_opts *keys
- end
-
- def tag node=nil, text=nil
- HtmlTagBuilder.build self, node, text
- end
-
def blank?
self.keys.count == 0
end
def to_query namespace=nil
- self.keys.sort.map { |k|
+ keys = self.keys.sort
+
+ return unless keys.first
+
+ '?' + keys.map do |k|
name = namespace ? "#{namespace}[#{k}]" : k
"#{name}=#{CGI::escape(self[k].to_s)}"
- }.join('&')
+ end.join('&')
end
- def data_attributes
- self.keys.sort.map{ |k| 'data-%s="%s"' % [k, self[k].to_s.gsub('"', '"')]}.join(' ')
+ def to_attributes
+ self.keys.sort.map{ |k| '%s="%s"' % [k, self[k].to_s.gsub('"', '"')]}.join(' ')
end
def pluck *args
string_args = args.map(&:to_s)
self.select{ |k,v| string_args.index(k.to_s) }
end
- def transform_keys
- return enum_for(:transform_keys) unless block_given?
- result = self.class.new
- each_key do |key|
- result[yield(key)] = self[key]
- end
- result
+ def stringify_keys
+ transform_keys { |key| key.to_s }
end
- def transform_keys!
- return enum_for(:transform_keys!) unless block_given?
- keys.each do |key|
- self[yield(key)] = delete(key)
- end
- self
- end
-
def symbolize_keys
- transform_keys{ |key| key.to_sym rescue key }
+ transform_keys { |key| key.respond_to?(:to_sym) ? key.to_sym : key }
end
- def symbolize_keys!
- transform_keys!{ |key| key.to_sym rescue key }
- end
-
- def pretty_generate
- JSON.pretty_generate(self).gsub(/"([\w\-]+)":/) { %["#{$1.yellow}":] }
- end
-
- # Returns hash with only se
+ # Returns hash with only selected keys
def slice *keys
keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
end
@@ -140,10 +58,64 @@
dup.except!(*keys)
end
# Hash#except in place, modifying current hash
def except!(*keys)
- keys.each { |key| delete(key) }
+ keys.each { |key| delete(key.to_s); delete(key.to_sym) }
self
+ end
+
+ def remove_empty covert_to_s = false
+ self.keys.inject({}) do |t, el|
+ v = self[el]
+ t[covert_to_s ? el.to_s : el] = v if el.present? && v.present?
+ t
+ end
+ end
+
+ def to_js opts = {}
+ data = opts[:empty] ? self : remove_empty
+ data = data.to_json.gsub(/"(\w+)":/, "\\1:")
+ data = data.gsub(/",(\w)/, '", \1') unless opts[:narrow]
+ data
+ end
+
+ def transform_keys &block
+ if block
+ Hash.new.tap do |result|
+ for key, value in self
+ value = value.transform_keys(&block) if value.is_a?(Hash)
+ result[block.call(key)] = value
+ end
+ end
+ else
+ enum_for(:transform_keys)
+ end
+ end
+
+ # clean empty values from hash, deep
+ def deep_compact value = nil
+ value ||= self
+
+ res_hash = value.map do |key, value|
+ value = deep_compact(value) if value.is_a?(Hash)
+
+ # we need to remove '0' because that is what empty checkbox inserts, but it is nil
+ value = nil if [{}, [], '0'].include?(value)
+ value = nil if value.blank?
+ [key, value]
+ end
+
+ res_hash.to_h.compact
+ end
+
+ def self.deep_compact value
+ (value || {}).deep_compact
+ end
+
+ def html_safe key
+ if data = self[key]
+ self[key] = data.html_safe
+ end
end
end