Краткий ответ :
Ошибка вызвана тем, что arr = []
, тогда вы вызываете arr.push(<another_array>)
, что означает, что переменная является массивом массивов .
Позже вы звоните obj[hash.keys[index]]
, но (из-за вышеизложенного) obj
на самом деле Array
, а не Hash
. Вот почему вы получаете ошибку TypeError: no implicit conversion of Symbol into Integer
.
Я мог бы попытаться исправить ваш код с помощью обходного пути (возможно, Array#flatten
), но гораздо лучшей идеей было бы реорганизовать объект, чтобы упростить его.
Давайте разгадать этот шаг за шагом:
- Почему все эти странные ссылки на
hash.keys[index]
?
Потому что вы пытаетесь получить 3 переменные, но объявляете только две - поэтому первая - это комбинация двух значений с неправильным именем. Вместо: hash.each_with_index do |key, index|
вам нужно: hash.each_with_index do |(key, value), index|
. Это упрощает код до:
class Where
@boris = {:name => 'Boris The Blade', :quote => "Heavy is good. Heavy is reliable. If it doesn't work you can always hit them.", :title => 'Snatch', :rank => 4}
@charles = {:name => 'Charles De Mar', :quote => 'Go that way, really fast. If something gets in your way, turn.', :title => 'Better Off Dead', :rank => 3}
@wolf = {:name => 'The Wolf', :quote => 'I think fast, I talk fast and I need you guys to act fast if you wanna get out of this', :title => 'Pulp Fiction', :rank => 4}
@glen = {:name => 'Glengarry Glen Ross', :quote => "Put. That coffee. Down. Coffee is for closers only.", :title => "Blake", :rank => 5}
@fixtures = [@boris, @charles, @wolf, @glen]
def self.where(hash = {})
arr = []
hash.each_with_index do |(key, value), index|
puts arr;
case value
when Integer
puts 'hitting integer'
if index === 0
puts 'hitting 1'
arr.push(@fixtures.select { |obj| obj[key] === value })
else
puts 'hitting 2'
arr.select { |obj| obj[key] === value }
end
when String
puts 'hitting string'
if index === 0
puts 'hitting 3'
arr.push(@fixtures.select { |obj| obj[key] === value })
else
puts 'hitting 4'
arr.select { |obj| obj[key] === value }
end
when Regexp
puts 'hitting Regexp'
if index === 0
puts 'hitting 5'
arr.push(@fixtures.select { |obj| obj[key].index(value) != nil })
else
puts 'hitting 6'
arr.select { |obj| obj[key].index(value) != nil }
end
end
end
return self
end
end
puts Where.where(:rank => 4, :quote => /get/)
(Обратите внимание, что я еще не исправил вашу ошибку!)
- Почему существует переменная
arr
, а логика окружает if index === 0
?
Исправление требует небольшого изменения мышления - ваш текущий дизайн может работать только для проверки до двух условий в хэше where
, так как вы сохраняете результаты первой проверки во временном массиве. Это не нужно; вместо этого вы можете написать что-то вроде:
class Where
@boris = {:name => 'Boris The Blade', :quote => "Heavy is good. Heavy is reliable. If it doesn't work you can always hit them.", :title => 'Snatch', :rank => 4}
@charles = {:name => 'Charles De Mar', :quote => 'Go that way, really fast. If something gets in your way, turn.', :title => 'Better Off Dead', :rank => 3}
@wolf = {:name => 'The Wolf', :quote => 'I think fast, I talk fast and I need you guys to act fast if you wanna get out of this', :title => 'Pulp Fiction', :rank => 4}
@glen = {:name => 'Glengarry Glen Ross', :quote => "Put. That coffee. Down. Coffee is for closers only.", :title => "Blake", :rank => 5}
@fixtures = [@boris, @charles, @wolf, @glen]
def self.where(hash = {})
@fixtures.select do |fixture|
hash.all? do |key, value|
case value
when Integer
puts 'hitting integer'
fixture[key] === value
when String
puts 'hitting string'
fixture[key] === value
when Regexp
puts 'hitting Regexp'
fixture[key] === value
end
end
end
end
end
puts Where.where(:rank => 4, :quote => /get/)
(Вау, это сократило лот! - и переменная index
теперь даже не нужна. Это исправляет вашу первоначальную ошибку, но код по-прежнему не совсем работает ...)
- Сравнение
String === Regexp
всегда будет неудачным.
См. документацию - вам действительно нужно использовать Regexp === String
здесь, а не наоборот. Изменение этого, наконец, дает нам рабочий код:
class Where
@boris = {:name => 'Boris The Blade', :quote => "Heavy is good. Heavy is reliable. If it doesn't work you can always hit them.", :title => 'Snatch', :rank => 4}
@charles = {:name => 'Charles De Mar', :quote => 'Go that way, really fast. If something gets in your way, turn.', :title => 'Better Off Dead', :rank => 3}
@wolf = {:name => 'The Wolf', :quote => 'I think fast, I talk fast and I need you guys to act fast if you wanna get out of this', :title => 'Pulp Fiction', :rank => 4}
@glen = {:name => 'Glengarry Glen Ross', :quote => "Put. That coffee. Down. Coffee is for closers only.", :title => "Blake", :rank => 5}
@fixtures = [@boris, @charles, @wolf, @glen]
def self.where(hash = {})
@fixtures.select do |fixture|
hash.all? do |key, value|
case value
when Integer
puts 'hitting integer'
value === fixture[key]
when String
puts 'hitting string'
value === fixture[key]
when Regexp
puts 'hitting Regexp'
value === fixture[key]
end
end
end
end
end
puts Where.where(:rank => 4, :quote => /get/)
- Это все еще очень повторяется! ...
Возможно, вы действительно хотите этот оператор case
со всеми puts
вызовами для отладки, но в противном случае код снова может быть значительно упрощен:
class Where
@boris = {:name => 'Boris The Blade', :quote => "Heavy is good. Heavy is reliable. If it doesn't work you can always hit them.", :title => 'Snatch', :rank => 4}
@charles = {:name => 'Charles De Mar', :quote => 'Go that way, really fast. If something gets in your way, turn.', :title => 'Better Off Dead', :rank => 3}
@wolf = {:name => 'The Wolf', :quote => 'I think fast, I talk fast and I need you guys to act fast if you wanna get out of this', :title => 'Pulp Fiction', :rank => 4}
@glen = {:name => 'Glengarry Glen Ross', :quote => "Put. That coffee. Down. Coffee is for closers only.", :title => "Blake", :rank => 5}
@fixtures = [@boris, @charles, @wolf, @glen]
def self.where(hash = {})
@fixtures.select do |fixture|
hash.all? do |key, value|
puts "Checking #{key} => #{value.inspect}"
value === fixture[key]
end
end
end
end
puts Where.where(:rank => 4, :quote => /get/)