Jon Heckman
Jon Heckman

Reputation: 450

Ruby String variable returning true for .is_a?(Array)

I have a method that will either get an array or a string

For the method to work correctly, I need to convert that string to an array. Since it will sometimes get string, I wanted to have it check if the variable is an array, and if not convert it to an array. So I did the following:

unless variablename.is_a?(Array)
  variablename = variablename.lines.to_a
end

The second line of this fails and I get a ruby error that 'lines' is not available to an array object.

I also tried .kind_of? with same results

I got my answer but I also wanted to clear up what exactly I was asking. I am testing to see if variablename is an array. For some reason when variablename is an array, it still runs and than the second line fails with the following error: undefined method `lines' for #Array:0x000000021382b8 (NoMethodError)

Upvotes: 1

Views: 21869

Answers (3)

Stefan
Stefan

Reputation: 114208

Rather than checking the type (is_a? String) I'd check if the object responds to the method needed for conversion. Assuming that you want to iterate over lines provided either as an array of lines or as a (multi-line) string, something like this would work:

def do_stuff(lines)
  lines = lines.each_line if lines.respond_to?(:each_line)
  lines.each do |line|
    # do stuff
  end
end

Upvotes: 0

7stud
7stud

Reputation: 48599

def do_stuff(x)
  x = x.lines.to_a if x.is_a? String
  x
end 

data = [
  "hello\nworld",
  [1, 2, 3]
]

data.each do |item|
  p do_stuff item
end

Now, with unless:

def do_stuff(x)
  unless x.is_a?(Array)
    x = x.lines.to_a
  end
  x
end 

data = [
  "hello\nworld",
  [1, 2, 3],
  ['a', 'b']
]

data.each do |item|
  p do_stuff item
end

--output:--
["hello\n", "world"]
[1, 2, 3]
["a", "b"]

But it makes more sense to check for a String object before calling a String method on the object than checking for not an Array.

Upvotes: 3

sawa
sawa

Reputation: 168169

You don't need to_a after lines. It is always an array. You can do this:

case variablename
when Array then variablename
when String then variablename.lines
else p variablename.class # For debugging. This should not happen.
end


Looking at your error message with the inspection #Array:0x000000021382b8, variablename is probably not an Array.

Upvotes: 0

Related Questions