Module: Foobara::Util

Defined in:
foobara-util-1.1.1/lib/foobara/util/args.rb,
foobara-util-1.1.1/lib/foobara/util/hash.rb,
foobara-util-1.1.1/lib/foobara/util/meta.rb,
foobara-util-1.1.1/lib/foobara/util/tree.rb,
foobara-util-1.1.1/lib/foobara/util/array.rb,
foobara-util-1.1.1/lib/foobara/util/class.rb,
foobara-util-1.1.1/lib/foobara/util/module.rb,
foobara-util-1.1.1/lib/foobara/util/string.rb,
foobara-util-1.1.1/lib/foobara/util/require.rb,
foobara-util-1.1.1/lib/foobara/util/structured.rb,
foobara-util-1.1.1/lib/foobara/util/object_space.rb

Defined Under Namespace

Classes: ParentModuleDoesNotExistError, ReferencePathPart, SubTree, Tree

Constant Summary collapse

IS_CAP =
/[A-Z]/
IS_IDENTIFIER_CHARACTER =
/\w/

Class Method Summary collapse

Class Method Details

.all_blank_or_false?(array) ⇒ Boolean

Returns:

  • (Boolean)


34
35
36
37
38
39
40
# File 'lib/foobara/util/array.rb', line 34

def all_blank_or_false?(array)
  array.all? do |element|
    element.nil? || element == false || (
      (element.is_a?(::Hash) || element.is_a?(::Array) || element.is_a?(::String)) && element.empty?
    )
  end
end

.all_symbolic_elements?(array) ⇒ Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/foobara/util/array.rb', line 26

def all_symbolic_elements?(array)
  array.all?(Symbol)
end

.all_symbolic_keys?(hash) ⇒ Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/foobara/util/hash.rb', line 92

def all_symbolic_keys?(hash)
  all_symbolic_elements?(hash.keys)
end

.all_symbolizable_elements?(array) ⇒ Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/foobara/util/array.rb', line 30

def all_symbolizable_elements?(array)
  array.all? { |key| key.is_a?(Symbol) || key.is_a?(String) }
end

.all_symbolizable_keys?(hash) ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/foobara/util/hash.rb', line 96

def all_symbolizable_keys?(hash)
  all_symbolizable_elements?(hash.keys)
end

.arg_and_opts_to_arg(arg, opts) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/foobara/util/args.rb', line 42

def arg_and_opts_to_arg(arg, opts)
  if arg && !arg.empty?
    if opts && !opts.empty?
      unless opts.is_a?(::Hash)
        # simplecov:disable
        raise ArgumentError, "opts must be a hash not a #{opts}"
        # simplecov:enable
      end

      unless arg.is_a?(::Hash)
        # simplecov:disable
        raise ArgumentError, "arg must be a hash if present when opts is present"
        # simplecov:enable
      end

      arg.merge(opts)
    else
      arg
    end
  elsif opts && !opts.empty?
    opts
  end
end

.args_and_opts_to_args(args, opts) ⇒ Object

Strange utility method here... idea is there's a method that takes 0 or 1 arguments which may or may not be a hash. To make sure we don't act like there's an argument when there's not or fail to combine parts of the hash that wind up in opts, this method comines it into an array of 0 or 1 argument with stuff merged into the argument if needed.



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
# File 'lib/foobara/util/args.rb', line 71

def args_and_opts_to_args(args, opts)
  unless args.is_a?(::Array)
    # simplecov:disable
    raise ArgumentError, "args must be an array of 0 or 1 hashes but received #{args}"
    # simplecov:enable
  end

  case args.size
  when 0
    Util.array(arg_and_opts_to_arg(nil, opts))
  when 1
    # Do not go from 1 argument to 0. ie, [nil] should return [nil] not [].
    if opts && !opts.empty?
      arg = args.first

      unless arg.is_a?(::Hash)
        # simplecov:disable
        raise ArgumentError, "Expected #{arg.inspect} to be a Hash"
        # simplecov:enable
      end

      [arg_and_opts_to_arg(args.first, opts)]
    else
      args
    end

    [arg_and_opts_to_arg(args.first, opts)]
  else
    # simplecov:disable
    raise ArgumentError, "args must be an array of 0 or 1 hashes but received #{args}"
    # simplecov:enable
  end
end

.args_and_opts_to_opts(args, opts) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/foobara/util/args.rb', line 5

def args_and_opts_to_opts(args, opts)
  unless args.is_a?(::Array)
    # simplecov:disable
    raise ArgumentError, "args must be an array of 0 or 1 hashes but received #{args}"
    # simplecov:enable
  end

  unless opts.is_a?(::Hash)
    # simplecov:disable
    raise ArgumentError, "opts must be a hash not a #{opts.class}"
    # simplecov:enable
  end

  case args.size
  when 0
    opts
  when 1
    arg = args.first

    if opts && !opts.empty?
      unless arg.is_a?(::Hash)
        # simplecov:disable
        raise ArgumentError, "opts must be a hash not a #{arg.class}"
        # simplecov:enable
      end

      arg.merge(opts)
    else
      arg
    end
  else
    # simplecov:disable
    raise ArgumentError, "args must be an array of 0 or 1 hashes but received #{args}"
    # simplecov:enable
  end
end

.array(object) ⇒ Object



15
16
17
18
19
20
21
22
23
24
# File 'lib/foobara/util/array.rb', line 15

def array(object)
  case object
  when nil
    []
  when Array
    object
  else
    [object]
  end
end

.camelize(string, upcase_first = false) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/foobara/util/string.rb', line 9

def camelize(string, upcase_first = false)
  if string.nil?
    # simplecov:disable
    warn "Passing nil to .#{__callee__} is deprecated. Pass a string only."
    return nil
    # simplecov:enable
  end

  if string.is_a?(::Symbol)
    string = string.to_s
  end

  retval = +""

  string.each_char do |char|
    if ["_", "-"].include?(char)
      upcase_first = true
    elsif upcase_first
      retval << char.upcase
      upcase_first = false
    else
      retval << char.downcase
    end
  end

  retval
end

.classify(string) ⇒ Object



5
6
7
# File 'lib/foobara/util/string.rb', line 5

def classify(string)
  camelize(string, true)
end

.const_get_up_hierarchy(mod, name) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/foobara/util/module.rb', line 74

def const_get_up_hierarchy(mod, name)
  mod.const_get(name)
rescue NameError => e
  if mod == Object || e.message !~ /uninitialized constant (.*::)?#{name}\z/
    # simplecov:disable
    raise
    # simplecov:enable
  end

  mod = if mod.name&.include?("::")
          module_for(mod)
        else
          Object
        end

  const_get_up_hierarchy(mod, name)
end

.constant_value(mod, constant, inherit: false) ⇒ Object



36
37
38
39
40
# File 'lib/foobara/util/module.rb', line 36

def constant_value(mod, constant, inherit: false)
  if mod.constants(inherit).include?(constant.to_sym)
    mod.const_get(constant, inherit)
  end
end

.constant_values(mod, is_a: nil, extends: nil, inherit: false) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/foobara/util/module.rb', line 42

def constant_values(mod, is_a: nil, extends: nil, inherit: false)
  if inherit && !mod.is_a?(Class)
    # simplecov:disable
    raise "Cannot pass inherit: true for something that is not a Class"
    # simplecov:enable
  end

  if inherit
    superklass = mod.superclass
    values = constant_values(mod, is_a:, extends:)
    if superklass == Object
      values
    else
      [
        *values,
        *constant_values(superklass, is_a:, extends:, inherit:)
      ]
    end
  else
    is_a = Util.array(is_a)
    extends = Util.array(extends)
    constants = mod.constants.sort

    constants.map { |const| constant_value(mod, const) }.select do |object|
      (is_a.nil? || is_a.empty? || is_a.any? { |klass| object.is_a?(klass) }) &&
        (extends.nil? || extends.empty? || (object.is_a?(Class) && extends.any? do |klass|
          object.ancestors.include?(klass)
        end))
    end.compact
  end
end

.constantify(string) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/foobara/util/string.rb', line 40

def constantify(string)
  if string.nil?
    # simplecov:disable
    warn "Passing nil to .#{__callee__} is deprecated. Pass a string only."
    return nil
    # simplecov:enable
  end

  if string.is_a?(::Symbol)
    string = string.to_s
  end

  if string =~ /\A[A-Z_]*\z/
    string.dup
  else
    underscore(string).upcase
  end
end

.constantify_sym(string) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/foobara/util/string.rb', line 59

def constantify_sym(string)
  if string.nil?
    # simplecov:disable
    warn "Passing nil to .#{__callee__} is deprecated. Pass a string only."
    return nil
    # simplecov:enable
  end

  constantify(string).to_sym
end

.deep_dup(object) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/foobara/util/structured.rb', line 31

def deep_dup(object)
  case object
  when ::Array
    object.map { |element| deep_dup(element) }
  when ::Hash
    object.to_h { |k, v| [deep_dup(k), deep_dup(v)] }
  when ::String
    # Important to not dup ::Module... but going to exclude everything but String for now to prevent that issue
    # and others.
    object.dup
  else
    object
  end
end

.deep_stringify_keys(object) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
# File 'lib/foobara/util/structured.rb', line 5

def deep_stringify_keys(object)
  case object
  when ::Array
    object.map { |element| deep_stringify_keys(element) }
  when ::Hash
    object.to_h do |k, v|
      [k.is_a?(::Symbol) ? k.to_s : k, deep_stringify_keys(v)]
    end
  else
    object
  end
end

.deep_symbolize_keys(object) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/foobara/util/structured.rb', line 18

def deep_symbolize_keys(object)
  case object
  when ::Array
    object.map { |element| deep_symbolize_keys(element) }
  when ::Hash
    object.to_h do |k, v|
      [k.is_a?(::String) ? k.to_sym : k, deep_symbolize_keys(v)]
    end
  else
    object
  end
end

.descendants(klass) ⇒ Object



5
6
7
8
9
10
11
12
13
14
# File 'lib/foobara/util/class.rb', line 5

def descendants(klass)
  all = Set.new

  klass.subclasses.each do |subclass|
    all << subclass
    all |= descendants(subclass)
  end

  all
end

.find_constant_through_class_hierarchy(klass, constant) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/foobara/util/class.rb', line 33

def find_constant_through_class_hierarchy(klass, constant)
  if klass.const_defined?(constant)
    klass.const_get(constant)
  else
    find_constant_through_class_hierarchy(klass.superclass, constant)
  end
end

.humanize(string) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/foobara/util/string.rb', line 148

def humanize(string)
  if string.nil?
    # simplecov:disable
    warn "Passing nil to .#{__callee__} is deprecated. Pass a string only."
    return nil
    # simplecov:enable
  end

  if string.is_a?(::Symbol)
    string = string.to_s
  end

  return "" if string.empty?

  string = string.gsub("_", " ")
  string[0] = string[0].upcase

  string
end

.instances(klass) ⇒ Object

WARNING: This approach is known as being slow. Probably better for you class to track its own instances if this is being used for smoething more than debugging.



18
19
20
# File 'lib/foobara/util/class.rb', line 18

def instances(klass)
  ObjectSpace.each_object(klass).to_a
end

.kebab_case(string) ⇒ Object



110
111
112
113
114
115
116
117
118
119
# File 'lib/foobara/util/string.rb', line 110

def kebab_case(string)
  if string.nil?
    # simplecov:disable
    warn "Passing nil to .#{__callee__} is deprecated. Pass a string only."
    return nil
    # simplecov:enable
  end

  underscore(string).gsub("_", "-")
end

.make_class(name, superclass = nil, which: :class, tag: false, &block) ⇒ Object



16
17
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
56
57
58
59
60
61
62
63
64
# File 'lib/foobara/util/meta.rb', line 16

def make_class(name, superclass = nil, which: :class, tag: false, &block)
  name = name.to_s if name.is_a?(::Symbol)

  if superclass.is_a?(Class)
    superclass = superclass.name
  end

  inherit = superclass ? " < ::#{superclass}" : ""

  superclass ||= :Object

  name = name[2..] if name.start_with?("::")

  already_exists = Object.const_defined?(name, false)

  if !already_exists && tag
    should_tag = true
  end

  parent_name = parent_module_name_for(name)

  if parent_name && !Object.const_defined?(parent_name, false)
    raise ParentModuleDoesNotExistError.new(name:, parent_name:)
  end

  unless already_exists
    # rubocop:disable-next Security/Eval, Style/DocumentDynamicEvalDefinition
    eval(<<~RUBY, binding, __FILE__, __LINE__ + 1)
      #{which} ::#{name}#{inherit}
      end
    RUBY
  end

  klass = Object.const_get(name, false)

  if should_tag
    klass.instance_variable_set(:@foobara_created_via_make_class, true)
  end

  if block
    if klass.is_a?(::Class)
      klass.class_eval(&block)
    else
      klass.module_eval(&block)
    end
  end

  klass
end

.make_class_p(name, superclass = nil, which: :class, tag: false) ⇒ Object



66
67
68
69
70
71
# File 'lib/foobara/util/meta.rb', line 66

def make_class_p(name, superclass = nil, which: :class, tag: false, &)
  make_class(name, superclass, which:, tag:, &)
rescue ParentModuleDoesNotExistError => e
  make_class_p(e.parent_name, which: :module, tag:, &)
  make_class(name, superclass, which:, tag:, &)
end

.make_module(name) ⇒ Object

TODO: Kind of weird that make_module is implemented in terms of make_class instead of the other way around



74
75
76
# File 'lib/foobara/util/meta.rb', line 74

def make_module(name, &)
  make_class(name, which: :module, &)
end

.make_module_p(name, tag: false) ⇒ Object



78
79
80
# File 'lib/foobara/util/meta.rb', line 78

def make_module_p(name, tag: false, &)
  make_class_p(name, which: :module, tag:, &)
end

.module_for(mod) ⇒ Object



5
6
7
8
9
10
11
12
# File 'lib/foobara/util/module.rb', line 5

def module_for(mod)
  name = mod.name

  return unless name

  name = parent_module_name_for(mod.name)
  Object.const_get(name) if name
end

.non_full_name(mod) ⇒ Object



18
19
20
21
22
23
24
25
26
# File 'lib/foobara/util/module.rb', line 18

def non_full_name(mod)
  name = if mod.is_a?(::String)
           mod
         else
           mod.name
         end

  name&.[](/([^:]+)\z/, 1)
end

.non_full_name_underscore(mod) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/foobara/util/module.rb', line 28

def non_full_name_underscore(mod)
  name = non_full_name(mod)

  if name
    underscore(name)
  end
end

.object_id_to_object(object_id) ⇒ Object



15
16
17
18
19
# File 'lib/foobara/util/object_space.rb', line 15

def object_id_to_object(object_id)
  ObjectSpace._id2ref(object_id)
rescue RangeError
  nil
end

.parent_module_name_for(module_name) ⇒ Object



14
15
16
# File 'lib/foobara/util/module.rb', line 14

def parent_module_name_for(module_name)
  module_name[/(.*)::/, 1]
end

.power_set(array) ⇒ Object



7
8
9
10
11
12
13
# File 'lib/foobara/util/array.rb', line 7

def power_set(array)
  return [EMPTY_ARRAY] if array.empty?

  head, *tail = array
  subsets = power_set(tail)
  subsets + subsets.map { |subset| [head, *subset] }
end


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/foobara/util/tree.rb', line 128

def print_tree(data, io: $stdout, to_name: nil, to_parent: nil)
  data = data.to_a if data.is_a?(::Hash)

  if to_name.nil? && to_parent.nil?
    to_name = :first.to_proc
    to_parent = proc do |object|
      parent_name = object.last
      data.find { |pair| pair.first == parent_name }
    end
  end

  tree = Util::Tree.new(data, to_parent)

  io.puts tree.to_s(to_name)
end

.referencing_paths(object) ⇒ Object



21
22
23
24
25
26
# File 'lib/foobara/util/object_space.rb', line 21

def referencing_paths(object)
  paths = _referencing_paths(object.__id__, object_id_referenced_by_map)
  paths.sort_by!(&:size)
  paths.reverse!
  paths
end

.remove_blank(hash) ⇒ Object



104
105
106
# File 'lib/foobara/util/hash.rb', line 104

def remove_blank(hash)
  remove_empty(hash).compact
end

.remove_constant(const_name) ⇒ Object



92
93
94
95
96
97
# File 'lib/foobara/util/module.rb', line 92

def remove_constant(const_name)
  *path, name = const_name.split("::")
  mod = path.inject(Object) { |m, constant| m.const_get(constant) }

  mod.send(:remove_const, name)
end

.remove_empty(hash) ⇒ Object



100
101
102
# File 'lib/foobara/util/hash.rb', line 100

def remove_empty(hash)
  hash.reject { |_k, v| (v.is_a?(::Hash) || v.is_a?(::Array)) && v.empty? }
end

.require_directory(directory) ⇒ Object



5
6
7
# File 'lib/foobara/util/require.rb', line 5

def require_directory(directory)
  require_pattern("#{directory}/**/*.rb")
end

.require_pattern(glob) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/foobara/util/require.rb', line 9

def require_pattern(glob)
  files = Dir[glob]

  if files.empty?
    # simplecov:disable
    raise "Didn't find anything to require for #{glob}"
    # simplecov:enable
  end

  files.sort_by { |file| [file.count("/"), file.length, file] }.reverse.each do |f|
    require f
  end
end

.sort_by_keys(hash) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/foobara/util/hash.rb', line 5

def sort_by_keys(hash)
  keys = hash.keys

  keys.sort!

  sorted_hash = {}

  keys.each do |key|
    sorted_hash[key] = hash[key]
  end

  sorted_hash
end

.sort_by_keys!(hash) ⇒ Object



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
# File 'lib/foobara/util/hash.rb', line 19

def sort_by_keys!(hash)
  last_key = keys_to_move = nil

  hash.each_key do |key|
    if last_key
      if key < last_key
        if keys_to_move
          keys_to_move << key
        else
          keys_to_move = [key]
        end

        next
      end
    end

    last_key = key
  end

  return hash unless keys_to_move

  keys_to_move.sort!

  keys_to_move.each do |key|
    value = hash.delete(key)
    hash[key] = value
  end

  hash
end

.start_with?(large_array, small_array) ⇒ Boolean

Returns:

  • (Boolean)


42
43
44
45
46
47
48
49
50
# File 'lib/foobara/util/array.rb', line 42

def start_with?(large_array, small_array)
  return false unless large_array.size >= small_array.size

  small_array.each.with_index do |item, index|
    return false unless large_array[index] == item
  end

  true
end

.super_method_of(current_instance, from_class, method_name) ⇒ Object

Kind of surprising that Ruby doesn't have a built in way to do this.



23
24
25
26
27
# File 'lib/foobara/util/class.rb', line 23

def super_method_of(current_instance, from_class, method_name)
  method = current_instance.method(method_name)
  method = method.super_method until method.owner == from_class
  method.super_method
end

.super_method_takes_parameters?(current_instance, from_class, method_name) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/foobara/util/class.rb', line 29

def super_method_takes_parameters?(current_instance, from_class, method_name)
  super_method_of(current_instance, from_class, method_name).parameters.any?
end

.symbolize_keys(hash) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/foobara/util/hash.rb', line 50

def symbolize_keys(hash)
  unless all_symbolizable_keys?(hash)
    # simplecov:disable
    raise "Cannot symbolize keys for #{hash} because they are not all symbolizable"
    # simplecov:enable
  end

  unless hash.instance_of?(::Hash)
    unless hash.respond_to?(:to_h)
      # simplecov:disable
      raise ArgumentError, "Could not turn #{hash} into an instance of Hash"
      # simplecov:enable
    end

    hash = hash.to_h
  end

  hash.transform_keys(&:to_sym)
end

.symbolize_keys!(hash) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/foobara/util/hash.rb', line 70

def symbolize_keys!(hash)
  unless all_symbolizable_keys?(hash)
    # simplecov:disable
    raise "Cannot symbolize keys for #{hash} because they are not all symbolizable"
    # simplecov:enable
  end

  hash.transform_keys!(&:to_sym)

  unless hash.instance_of?(::Hash)
    # simplecov:disable
    unless all_symbolic_keys?(hash)
      # This can happen with HashWithIndifferentAccess
      raise ArgumentError,
            "Cannot symbolize keys for #{hash} because its transform_keys! method does not behave as expected"
    end
    # simplecov:enable
  end

  hash
end

.to_or_sentence(strings, connector = ", ") ⇒ Object



144
145
146
# File 'lib/foobara/util/string.rb', line 144

def to_or_sentence(strings, connector = ", ")
  to_sentence(strings, connector, ", or ")
end

.to_sentence(strings, connector = ", ", last_connector = ", and ") ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
# File 'lib/foobara/util/string.rb', line 132

def to_sentence(strings, connector = ", ", last_connector = ", and ")
  return "" if strings.empty?

  *strings, last = strings

  if strings.empty?
    last
  else
    [strings.join(connector), last].join(last_connector)
  end
end

.underscore(string) ⇒ Object



70
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
# File 'lib/foobara/util/string.rb', line 70

def underscore(string)
  if string.nil?
    # simplecov:disable
    warn "Passing nil to .#{__callee__} is deprecated. Pass a string only."
    return nil
    # simplecov:enable
  end

  if string.is_a?(::Symbol)
    string = string.to_s
  end

  return "" if string.empty?

  string = string.gsub(/[-.]/, "_")

  retval = +""
  is_start = true

  string.each_char do |char|
    if IS_IDENTIFIER_CHARACTER =~ char
      if IS_CAP =~ char
        char = char.downcase
        char = "_#{char}" unless is_start
        is_start = false
      elsif char == "_"
        is_start = true
      else
        is_start = false
      end
    else
      is_start = true
    end

    retval << char
  end

  retval
end

.underscore_sym(string) ⇒ Object



121
122
123
124
125
126
127
128
129
130
# File 'lib/foobara/util/string.rb', line 121

def underscore_sym(string)
  if string.nil?
    # simplecov:disable
    warn "Passing nil to .#{__callee__} is deprecated. Pass a string only."
    return nil
    # simplecov:enable
  end

  underscore(string).to_sym
end