Module: NRSER
- Defined in:
- lib/nrser.rb,
lib/nrser/hash.rb,
lib/nrser/array.rb,
lib/nrser/logger.rb,
lib/nrser/truthy.rb,
lib/nrser/version.rb,
lib/nrser/collection.rb,
lib/nrser/enumerable.rb,
lib/nrser/refinements.rb,
lib/nrser/refinements/hash.rb,
lib/nrser/refinements/array.rb,
lib/nrser/refinements/object.rb,
lib/nrser/refinements/string.rb,
lib/nrser/refinements/pathname.rb
Defined Under Namespace
Modules: Collection, Types Classes: Logger
Constant Summary collapse
- TRUTHY_STRINGS =
Down-cased versions of strings that are considered to communicate truth.
Set.new [ 'true', 't', 'yes', 'y', 'on', '1', ]
- FALSY_STRINGS =
Down-cased versions of strings that are considered to communicate false.
Set.new [ 'false', 'f', 'no', 'n', 'off', '0', '', ]
- VERSION =
"0.0.18"
Class Method Summary collapse
-
.as_array(value) ⇒ Array
Return an array given any value in the way that makes most sense:.
-
.as_hash(value, key = nil) ⇒ Hash
Treat the value as the value for ‘key` in a hash if it’s not already a hash and can’t be converted to one:.
-
.collection?(obj) ⇒ Boolean
test if an object is considered a collection.
- .common_prefix(strings) ⇒ Object
-
.dedent(str) ⇒ Object
common_prefix.
-
.each(obj) { ... } ⇒ Object
yield on each element of a collection or on the object itself if it’s not a collection.
-
.erb(bnd, str) ⇒ Object
(also: template)
filter_repeated_blank_lines.
-
.except_keys(hash, *keys) ⇒ Hash
Returns a new hash without ‘keys`.
-
.except_keys!(hash, *keys) ⇒ Hash
Removes the given keys from hash and returns it.
-
.falsy?(object) ⇒ Boolean
Opposite of NRSER.truthy?.
-
.filter_repeated_blank_lines(str) ⇒ Object
dedent.
- .format_exception(e) ⇒ Object
-
.indent(str, amount = 2, indent_string = nil, indent_empty_lines = false) ⇒ Object
adapted from acrive_support 4.2.0.
- .leaves(hash, path: [], results: {}) ⇒ Object
-
.map(obj) { ... } ⇒ Object
if ‘obj` is a collection, calls `#map` with the block.
- .map_hash_values(hash, &block) ⇒ return_type
-
.map_values(enumerable, &block) ⇒ Hash
Maps an enumerable object to a new hash with the same keys and values obtained by calling ‘block` with the current key and value.
-
.slice_keys(hash, *keys) ⇒ Object
Lifted from ActiveSupport.
-
.squish(str) ⇒ Object
(also: unblock)
turn a multi-line string into a single line, collapsing whitespace to a single space.
- .symbolize_keys(hash) ⇒ Object
-
.symbolize_keys!(hash) ⇒ return_type
Mutates ‘hash` by converting all keys that respond to `#to_sym` to symbols.
-
.transform_keys(hash, &block) ⇒ Hash
Returns a new hash with each key transformed by the provided block.
-
.transform_keys!(hash) ⇒ Hash
Lifted from ActiveSupport.
-
.truncate(str, truncate_at, options = {}) ⇒ Object
Truncates a given
textafter a givenlengthiftextis longer thanlength:. -
.truthy?(object) ⇒ Boolean
Evaluate an object (that probably came from outside Ruby, like an environment variable) to see if it’s meant to represent true or false.
Class Method Details
.as_array(value) ⇒ Array
Return an array given any value in the way that makes most sense:
-
If ‘value` is an array, return it.
-
If ‘value` is `nil`, return `[]`.
-
If ‘value` responds to `#to_a`, try calling it. If it succeeds, return that.
-
Return an array with ‘value` as it’s only item.
Refinement
Added to ‘Object` in `nrser/refinements`.
23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/nrser/array.rb', line 23 def self.as_array value return value if value.is_a? Array return [] if value.nil? if value.respond_to? :to_a begin return value.to_a rescue end end [value] end |
.as_hash(value, key = nil) ⇒ Hash
It might be nice to have a ‘check` option that ensures the resulting hash has a value for `key`.
Treat the value as the value for ‘key` in a hash if it’s not already a hash and can’t be converted to one:
-
If the value is a ‘Hash`, return it.
-
If ‘value` is `nil`, return `{}`.
-
If the value responds to ‘#to_h` and `#to_h` succeeds, return the resulting hash.
-
Otherwise, return a new hash where ‘key` points to the value. **`key` MUST be provided in this case.**
Useful in method overloading and similar situations where you expect a hash that may specify a host of options, but want to allow the method to be called with a single value that corresponds to a default key in that option hash.
Refinement
Added to ‘Object` in `nrser/refinements`.
Example Time!
Say you have a method ‘m` that handles a hash of HTML options that can look something like
{class: 'address', data: {confirm: 'Really?'}}
And can call ‘m` like
m({class: 'address', data: {confirm: 'Really?'}})
but often you are just dealing with the ‘:class` option. You can use as_hash to accept a string and treat it as the `:class` key:
using NRSER
def m opts
opts = opts.as_hash :class
# ...
end
If you pass a hash, everything works normally, but if you pass a string ‘’address’‘ it will be converted to `’address’‘.
About ‘#to_h` Support
Right now, as_hash also tests if ‘value` responds to `#to_h`, and will try to call it, using the result if it doesn’t raise. This lets it deal with Ruby’s “I used to be a Hash until someone mapped me” values like ‘[[:class, ’address’]]‘. I’m not sure if this is the best approach, but I’m going to try it for now and see how it pans out in actual usage.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/nrser/hash.rb', line 96 def self.as_hash value, key = nil return value if value.is_a? Hash return {} if value.nil? if value.respond_to? :to_h begin return value.to_h rescue end end # at this point we need a key argument if key.nil? raise ArgumentError, "Need key to construct hash with value #{ value.inspect }, " + "found nil." end {key => value} end |
.collection?(obj) ⇒ Boolean
test if an object is considered a collection.
23 24 25 |
# File 'lib/nrser/collection.rb', line 23 def collection? obj Collection::STDLIB.any? {|cls| obj.is_a? cls} || obj.is_a?(Collection) end |
.common_prefix(strings) ⇒ Object
18 19 20 21 22 23 24 25 26 27 |
# File 'lib/nrser.rb', line 18 def common_prefix strings raise ArgumentError.new("argument can't be empty") if strings.empty? sorted = strings.sort.reject {|line| line == "\n"} i = 0 while sorted.first[i] == sorted.last[i] && i < [sorted.first.length, sorted.last.length].min i = i + 1 end strings.first[0...i] end |
.dedent(str) ⇒ Object
common_prefix
29 30 31 32 33 34 35 36 37 |
# File 'lib/nrser.rb', line 29 def dedent str return str if str.empty? lines = str.lines indent = common_prefix(lines).match(/^\s*/)[0] return str if indent.empty? lines.map {|line| line = line[indent.length..line.length] if line.start_with? indent }.join end |
.each(obj) { ... } ⇒ Object
yield on each element of a collection or on the object itself if it’s not a collection. avoids having to normalize to an array to iterate over something that may be an object OR a collection of objects.
37 38 39 40 41 42 43 44 |
# File 'lib/nrser/collection.rb', line 37 def each obj, &block if collection? obj obj.each &block else block.call obj obj end end |
.erb(bnd, str) ⇒ Object Also known as: template
filter_repeated_blank_lines
57 58 59 60 |
# File 'lib/nrser.rb', line 57 def erb bnd, str require 'erb' filter_repeated_blank_lines ERB.new(dedent(str)).result(bnd) end |
.except_keys(hash, *keys) ⇒ Hash
Returns a new hash without ‘keys`.
Lifted from ActiveSupport.
184 185 186 |
# File 'lib/nrser/hash.rb', line 184 def self.except_keys hash, *keys except_keys! hash.dup, *keys end |
.except_keys!(hash, *keys) ⇒ Hash
Removes the given keys from hash and returns it.
Lifted from ActiveSupport.
165 166 167 168 |
# File 'lib/nrser/hash.rb', line 165 def self.except_keys! hash, *keys keys.each { |key| hash.delete(key) } hash end |
.falsy?(object) ⇒ Boolean
Opposite of truthy?.
68 69 70 |
# File 'lib/nrser/truthy.rb', line 68 def self.falsy? object ! truthy?(object) end |
.filter_repeated_blank_lines(str) ⇒ Object
dedent
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/nrser.rb', line 39 def filter_repeated_blank_lines str out = [] lines = str.lines skipping = false str.lines.each do |line| if line =~ /^\s*$/ unless skipping out << line end skipping = true else skipping = false out << line end end out.join end |
.format_exception(e) ⇒ Object
64 65 66 |
# File 'lib/nrser.rb', line 64 def format_exception e "#{ e.message } (#{ e.class }):\n #{ e.backtrace.join("\n ") }" end |
.indent(str, amount = 2, indent_string = nil, indent_empty_lines = false) ⇒ Object
adapted from acrive_support 4.2.0
72 73 74 75 76 |
# File 'lib/nrser.rb', line 72 def indent str, amount = 2, indent_string=nil, indent_empty_lines=false indent_string = indent_string || str[/^[ \t]/] || ' ' re = indent_empty_lines ? /^/ : /^(?!$)/ str.gsub(re, indent_string * amount) end |
.leaves(hash, path: [], results: {}) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/nrser/hash.rb', line 3 def self.leaves hash, path: [], results: {} hash.each { |key, value| new_path = [*path, key] case value when Hash leaves value, path: new_path, results: results else results[new_path] = value end } results end |
.map(obj) { ... } ⇒ Object
if ‘obj` is a collection, calls `#map` with the block. otherwise, applies block to the object and returns the result.
55 56 57 58 59 60 61 |
# File 'lib/nrser/collection.rb', line 55 def map obj, &block if collection? obj obj.map &block else block.call obj end end |
.map_hash_values(hash, &block) ⇒ return_type
Document map_hash_values method.
Returns @todo Document return value.
127 128 129 130 131 |
# File 'lib/nrser/hash.rb', line 127 def self.map_hash_values hash, &block result = {} hash.each { |key, value| result[key] = block.call key, value } result end |
.map_values(enumerable, &block) ⇒ Hash
Maps an enumerable object to a new hash with the same keys and values obtained by calling ‘block` with the current key and value.
If ‘enumerable` *does not* sucessfully respond to `#to_h` then it’s treated as a hash where it’s elements are the keys and all the values are ‘nil`.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/nrser/enumerable.rb', line 11 def self.map_values enumerable, &block # Short-cut for Hash itself - though it would of course work through the # next step, it's going to probably be *the* most common argument type, # and there's no reason to do the tests and set up the exception # handler if we already know what's up with it. return NRSER.map_hash_values(enumerable) if enumerable.is_a? Hash if enumerable.respond_to? :to_h begin hash = enumerable.to_h rescue TypeError => e else return NRSER.map_hash_values hash end end result = {} enumerable.each { |key| result[key] = block.call key, nil } result end |
.slice_keys(hash, *keys) ⇒ Object
Lifted from ActiveSupport.
262 263 264 265 266 267 268 269 270 271 |
# File 'lib/nrser/hash.rb', line 262 def self.slice_keys hash, *keys # We're not using this, but, whatever, leave it in... if hash.respond_to?(:convert_key, true) keys.map! { |key| hash.convert_key(key) } end keys.each_with_object(hash.class.new) { |k, new_hash| new_hash[k] = hash[k] if hash.has_key?(k) } end |
.squish(str) ⇒ Object Also known as: unblock
turn a multi-line string into a single line, collapsing whitespace to a single space.
same as ActiveSupport’s String.squish, adapted from there.
12 13 14 |
# File 'lib/nrser.rb', line 12 def squish str str.gsub(/[[:space:]]+/, ' ').strip end |
.symbolize_keys(hash) ⇒ Object
252 253 254 255 |
# File 'lib/nrser/hash.rb', line 252 def self.symbolize_keys hash # File 'lib/active_support/core_ext/hash/keys.rb', line 54 transform_keys(hash) { |key| key.to_sym rescue key } end |
.symbolize_keys!(hash) ⇒ return_type
Mutates ‘hash` by converting all keys that respond to `#to_sym` to symbols.
Lifted from ActiveSupport.
246 247 248 |
# File 'lib/nrser/hash.rb', line 246 def self.symbolize_keys! hash transform_keys!(hash) { |key| key.to_sym rescue key } end |
.transform_keys(hash, &block) ⇒ Hash
Returns a new hash with each key transformed by the provided block.
Lifted from ActiveSupport.
221 222 223 224 225 226 227 228 |
# File 'lib/nrser/hash.rb', line 221 def self.transform_keys hash, &block # File 'lib/active_support/core_ext/hash/keys.rb', line 12 result = {} hash.each_key do |key| result[yield(key)] = hash[key] end result end |
.transform_keys!(hash) ⇒ Hash
Lifted from ActiveSupport.
201 202 203 204 205 206 207 |
# File 'lib/nrser/hash.rb', line 201 def self.transform_keys! hash # File 'lib/active_support/core_ext/hash/keys.rb', line 23 hash.keys.each do |key| hash[yield(key)] = hash.delete(key) end hash end |
.truncate(str, truncate_at, options = {}) ⇒ Object
Truncates a given text after a given length if text is longer than length:
'Once upon a time in a world far far away'.truncate(27)
# => "Once upon a time in a wo..."
Pass a string or regexp :separator to truncate text at a natural break:
'Once upon a time in a world far far away'.truncate(27, separator: ' ')
# => "Once upon a time in a..."
'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
# => "Once upon a time in a..."
The last characters will be replaced with the :omission string (defaults to “…”) for a total length not exceeding length:
'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
# => "And they f... (continued)"
adapted from
101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/nrser.rb', line 101 def truncate(str, truncate_at, = {}) return str.dup unless str.length > truncate_at omission = [:omission] || '...' length_with_room_for_omission = truncate_at - omission.length stop = \ if [:separator] str.rindex([:separator], length_with_room_for_omission) || length_with_room_for_omission else length_with_room_for_omission end "#{str[0, stop]}#{omission}" end |
.truthy?(object) ⇒ Boolean
Evaluate an object (that probably came from outside Ruby, like an environment variable) to see if it’s meant to represent true or false.
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 |
# File 'lib/nrser/truthy.rb', line 34 def self.truthy? object case object when nil false when String downcased = object.downcase if TRUTHY_STRINGS.include? downcased true elsif FALSY_STRINGS.include? downcased false else raise ArgumentError, "String #{ object.inspect } not recognized as true or false." end when TrueClass, FalseClass object else raise TypeError, "Can't evaluate truthiness of #{ object.inspect }" end end |