Выбор некоторых хэшей из набора хэшей на основе значения в Ruby

Общая проблема, которую я решаю:

Я новичок в Ruby и работаю над созданием метода поиска для своего приложения, в котором пользователь ищет имя одной модели, foo, которая может иметь много экземпляров этого имени, и мы возвращаем результаты всех связанных экземпляров. другой модели, Day. Однако каждый foo имеет несколько версий дня, с которым он связан (всего существует 4 разных версии, с которыми он может быть связан. Мы отображаем эти версии через foo, а foo содержит их в логических значениях: include_in_standard, include_in_v1 и т. д.).

Мне нужен мой метод поиска, чтобы сообщить мне, какие версии foo включены для каждого дня, чтобы я мог соответствующим образом отображать результаты поиска. Кроме того, для разных пользователей доступны только определенные дни. У меня получилось так, что я передаю информацию о днях и версиях из модели в контроллер, однако в контроллере у меня проблема с получением только дней, которые доступны текущему пользователю.

Структура кода:

В модели Day у меня есть метод поиска, который возвращает следующее:

results={:result_case=>result_case, :days_set=>days_set, :term0=>term0, :term1=>term1}

result_case — целое число, term0 и term1 — строки.

days_set - это набор, который формируется следующим образом

days_set=Set.new
array_of_foo.each do |f|
  f.join_table_connecting_foo_and_days.days.each do |foo|
    days_set+={:day=>d, :standard=>f.include_in_standard, :v1=>f.include_in_v1, :v2=>f.include_in_v2, :v3=>f.include_in_v3, :v4=>f.include_in_v4}
  end
end
days_set

В моем контроллере я вызываю метод поиска, который возвращает результаты, и присваиваю его локальной переменной results в контроллере. У меня также есть массив всех дней, доступных для current_user, available_days.

Микроцель:

Я хочу получить набор или массив, который представляет собой просто хэши из days_set, где день включен в available_days. То есть, если мой days_set в настоящее время

[{:day=>d1, :standard=>true, :v1=>false, :v2=>false, :v3=>true, :v4=>true},
  {:day=>d2, :standard=>false, :v1=>true, :v2=>false, :v3=>true, :v4=>false},
  {:day=>d3, :standard=>false, :v1=>false, :v2=>false, :v3=>true, :v4=>true},
  {:day=>d4, :standard=>true, :v1=>true, :v2=>true, :v3=>true, :v4=>true},
  {:day=>d5, :standard=>false, :v1=>false, :v2=>false, :v3=>true, :v4=>false},
  {:day=>d6, :standard=>true, :v1=>false, :v2=>true, :v3=>false, :v4=>true}]

available_days=[d1, d3, d4]

тогда я хочу

[{:day=>d1, :standard=>true, :v1=>false, :v2=>false, :v3=>true, :v4=>true},
  {:day=>d3, :standard=>false, :v1=>false, :v2=>false, :v3=>true, :v4=>true},
  {:day=>d4, :standard=>true, :v1=>true, :v2=>true, :v3=>true, :v4=>true}]

Ошибка/проблема/код, который не работает:

Я пытался искать идеи о том, как это сделать в другом месте, но я не думаю, что у меня есть словарь кодирования, чтобы описать то, что я пытаюсь сделать.

Я думал, что это сработает, но он генерирует ошибку Не удается преобразовать символ в целое число в строке, отмеченной ** (которой нет в коде).

days_set=results[:days_set]
** new_days_set=days_set.keep_if{|day_hash| available_days.include? day_hash[:day]

Вопросы:

  1. Как я могу получить хэши в моем наборе days_set, чей день находится в available_days?

  2. Я сталкивался с этой ошибкой Не удается преобразовать символ в целое число чаще, чем с любой другой ошибкой, по крайней мере раз в неделю, а может и чаще. Я чувствую, что это указывает на какую-то концепцию, которую я не совсем понимаю. Можете ли вы сказать мне, что это за концепция, чтобы я мог искать информацию о ней и/или направлять меня к какой-либо информации о ней? Я не знаю, как называется то, что я ищу, поэтому его трудно найти.

Спасибо.


person ctaymor    schedule 23.07.2013    source источник
comment
Вы используете драгоценный камень для Set? Это не стандартный класс Ruby.   -  person lurker    schedule 24.07.2013
comment
@mbrach Это находится в документации Ruby, поэтому я предположил, что это стандартный класс Ruby.   -  person ctaymor    schedule 24.07.2013
comment
Ах да, ты прав. Мой irb выдал мне ошибку, но я забыл потребовать lib.   -  person lurker    schedule 24.07.2013
comment
Для человека, который проголосовал против этого, было бы очень полезно, если бы вы также оставили комментарий о том, почему, чтобы я мог научиться задавать лучшие вопросы. Спасибо.   -  person ctaymor    schedule 24.07.2013


Ответы (1)


Чтобы получить подмножество дней:

new_days = days_set.select { |ds| available_days.include? ds[:day] }

Это даст вам массив. Или вы можете использовать .to_set для получения набора:

new_days_set = (days_set.select { |ds| available_days.include? ds[:day] }).to_set

Ошибка «невозможно преобразовать символ в целое число» возникает из-за того, что где-то вы, вероятно, пытаетесь сравнить символ, например :day, с целочисленным значением, например d1. Или, если ds[:day] (значение ключа :day для хеш-элемента ds) является символом, а ваш массив available_days представляет собой массив целых чисел.

person lurker    schedule 23.07.2013
comment
Спасибо, что нашли время, чтобы помочь мне. Ваше решение также дает мне ошибку «невозможно преобразовать символ в целое число». Я думаю, может быть, я не совсем понимаю, как связаны символы и хэши. Разве ds[:day] не должен давать мне номер идентификатора объекта day, на который сопоставляется атрибут :day хэша ds? То есть, поскольку в первом хэше :day=›d1, не должна ли при переборе хэшей первого хэша ds[:day] возвращать d1? - person ctaymor; 24.07.2013
comment
@Magelet интересно. Когда я смоделирую ваш сценарий, он сработает. Но я присваиваю целочисленные значения d1, d2 и т. д. Как устанавливаются ваши значения? Символ похож на постоянную строку. Это просто тег для хеш-элемента. Вы можете сказать :day => 3 или "day" => 3, и оба варианта будут работать в хеше. Но между тем, что вы делаете, и тем, что я показываю, должно быть что-то другое. Например, если у вас есть :day => d1, то d1 — это переменная, которая должна представлять какое-то значение. Я использую ваш тестовый сценарий, заданный с помощью d1, d2 и т. д. Этот пример работает для вас в irb? - person lurker; 24.07.2013
comment
d1, d2 и т. д. являются объектами моей модели/класса Day, а не целыми числами (хотя я думаю, что когда я помещаю день в day_set, см. в разделе структуры вопроса, где формируется days_set, то, что на самом деле происходит введите идентификатор be, который должен быть целым числом?). Я попробую это с целыми числами в irb, чтобы посмотреть, прояснит ли это что-нибудь. - person ctaymor; 24.07.2013
comment
Спасибо, информация помогает. В исходном описании проблемы указано :day => d, но я не вижу определения d. Я уверен, что проблема именно в этой области. В вашем упрощенном примере, если d1 и т. д. установлены в целые числа, все работает. Итак, в вашем примере из реальной жизни у вас есть целые числа в одном месте, но символы в другом, и они сравниваются с помощью includes? или другого метода. - person lurker; 24.07.2013
comment
Думаю, я, возможно, понял, что происходит. Я получаю доступные дни из массива классов. Бар имеет_много дней, поэтому похоже, что метод, который я использую для сопоставления объектов бара с их днями, не сработает ( available_bar.flat_map {|b| b.days}. По крайней мере, когда я выбираю один день, b .days не работает. Мне нужно больше изучить ассоциации и выяснить, как правильно получить к ним доступ. Я думаю, что проблема в том, что массив доступных дней шаткий. - person ctaymor; 24.07.2013
comment
Спасибо, что потратили столько времени, чтобы помочь мне понять, что было не так. Оказывается, при построении набора дней я пытался добавить хеш, представляющий информацию о дне, с помощью +=, но, похоже, мне нужно было использовать ‹‹. Похоже, это было большой проблемой, потому что вместо хэша мне давали массив в дневном наборе. - person ctaymor; 24.07.2013
comment
@Magelet Я рад, что ты разобрался. - person lurker; 24.07.2013