Module: JSI::Util
Overview
JSI::Util contains public utilities
Defined Under Namespace
Modules: Arraylike, Hashlike, Private
Constant Summary
Constants included from Private
Private::EMPTY_ARY, Private::EMPTY_SET, Private::LAST_ARGUMENT_AS_KEYWORD_PARAMETERS
Instance Method Summary collapse
-
#as_json(object, *opt) ⇒ Array, ...
recursive method to express the given argument object in json-compatible types of Hash, Array, and basic types of String/boolean/numeric/nil.
- #deep_stringify_symbol_keys(object) ⇒ Object
-
#ensure_module_set(modules) ⇒ Set
ensures the given param becomes a frozen Set of Modules.
-
#modified_copy(object) {|Object| ... } ⇒ object.class
yields the content of the given param
object
. -
#stringify_symbol_keys(hashlike) ⇒ same class as the param `hash`, or Hash if the former cannot be done
a hash copied from the given hashlike, in which any symbol keys are converted to strings.
Methods included from Private
#ok_ruby_method_name?, #require_jmespath, #ycomb
Instance Method Details
#as_json(object, *opt) ⇒ Array, ...
recursive method to express the given argument object in json-compatible types of Hash, Array, and basic types of String/boolean/numeric/nil. this will raise TypeError if an object is given that is not a type that seems to be expressable as json.
similar effect could be achieved by requiring 'json/add/core' and using #as_json, but I don't much care for how it represents classes that are not naturally expressable in JSON, and prefer not to load its monkey-patching.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/jsi/util.rb', line 46 def as_json(object, *opt) if object.is_a?(JSI::Base) as_json(object.jsi_node_content, *opt) elsif object.respond_to?(:to_hash) (object.respond_to?(:map) ? object : object.to_hash).map do |k, v| unless k.is_a?(Symbol) || k.respond_to?(:to_str) raise(TypeError, "json object (hash) cannot be keyed with: #{k.pretty_inspect.chomp}") end {k.to_s => as_json(v, *opt)} end.inject({}, &:update) elsif object.respond_to?(:to_ary) (object.respond_to?(:map) ? object : object.to_ary).map { |e| as_json(e, *opt) } elsif [String, TrueClass, FalseClass, NilClass, Numeric].any? { |c| object.is_a?(c) } object elsif object.is_a?(Symbol) object.to_s elsif object.is_a?(Set) as_json(object.to_a, *opt) elsif object.respond_to?(:as_json) as_json(object.as_json(*opt), *opt) else raise(TypeError, "cannot express object as json: #{object.pretty_inspect.chomp}") end end |
#deep_stringify_symbol_keys(object) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/jsi/util.rb', line 98 def deep_stringify_symbol_keys(object) if object.respond_to?(:to_hash) JSI::Util.modified_copy(object) do |hash| out = {} (hash.respond_to?(:each) ? hash : hash.to_hash).each do |k, v| out[k.is_a?(Symbol) ? k.to_s : deep_stringify_symbol_keys(k)] = deep_stringify_symbol_keys(v) end out end elsif object.respond_to?(:to_ary) JSI::Util.modified_copy(object) do |ary| (ary.respond_to?(:each) ? ary : ary.to_ary).map do |e| deep_stringify_symbol_keys(e) end end else object end end |
#ensure_module_set(modules) ⇒ Set
ensures the given param becomes a frozen Set of Modules. returns the param if it is already that, otherwise initializes and freezes such a Set.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/jsi/util.rb', line 125 def ensure_module_set(modules) if modules.is_a?(Set) && modules.frozen? set = modules else set = Set.new(modules).freeze end not_modules = set.reject { |s| s.is_a?(Module) } if !not_modules.empty? raise(TypeError, [ "ensure_module_set given non-Module objects:", *not_modules.map { |ns| ns.pretty_inspect.chomp }, ].join("\n")) end set end |
#modified_copy(object) {|Object| ... } ⇒ object.class
yields the content of the given param object
. for objects which have a #jsi_modified_copy
method of their own (JSI::Base, JSI::MetaschemaNode) that method is invoked with the given
block. otherwise the given object itself is yielded.
the given block must result in a modified copy of its block parameter (not destructively modifying the yielded content).
23 24 25 26 27 28 29 |
# File 'lib/jsi/util.rb', line 23 def modified_copy(object, &block) if object.respond_to?(:jsi_modified_copy) object.jsi_modified_copy(&block) else return yield(object) end end |
#stringify_symbol_keys(hashlike) ⇒ same class as the param `hash`, or Hash if the former cannot be done
a hash copied from the given hashlike, in which any symbol keys are converted to strings. behavior on collisions is undefined (but in the future could take a block like ActiveSupport::HashWithIndifferentAccess#update)
at the moment it is undefined whether the returned hash is the same
instance as the hash
param. if hash
is already a hash which contains
no symbol keys, this method MAY return that same instance. use #dup on
the return if you need to ensure it is not the same instance as the
argument instance.
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/jsi/util.rb', line 85 def stringify_symbol_keys(hashlike) unless hashlike.respond_to?(:to_hash) raise(ArgumentError, "expected argument to be a hash; got #{hashlike.class.inspect}: #{hashlike.pretty_inspect.chomp}") end JSI::Util.modified_copy(hashlike) do |hash| out = {} hash.each do |k, v| out[k.is_a?(Symbol) ? k.to_s : k] = v end out end end |