Как отфильтровать результат запроса ActiveRecord путем сравнения с другим экземпляром модели?
У меня есть простой запрос ActiveRecord в соответствии с этим:
similar_changes = Notification.where(change_owner: 'foo1', change_target: 'foo2', change_cancelled: false)
Каждый объект уведомления имеет поле change_type
и у меня есть другая функция, которая проверяет одно уведомление change_type
с одним другим Уведомлением об обратных изменениях (изменениях, которые отменяют друг друга в контексте моего приложения).
Мне нужно принять это уведомление change_type
и сравнить его со всеми остальными в массиве. Я должен ссылаться на объекты так: similar_changes[0]['change_type']
где первый индекс - каждая ActiveRecord в массиве, а второй - словарь, который определяет, какое свойство в объекте Notification.
У меня есть ощущение, что я мог бы сделать это вручную с помощью двух вложенных циклов и операторов if, но я также знаю Ruby и считаю, что это то, что он должен был встроить.
Я не прав или есть лучший способ сделать это?
Вот код (обратите внимание, что весь этот код еще не закончен, так что терпите меня, если он не идеален):
def self.group_similar_changes(owner, target, change_type)
# long query where it selects all rows where change_owner and change_target
# are the same as original
# also where cancelled is false
# determine if cancelled (yaml)
# if cancelled (do nothing)
similar_changes = Notification.where(
change_owner: owner,
change_target: target,
change_cancelled: false
)
similar_changes.each do |change|
cancel_inverse_change(change, change.change_type)
if change.cancelled?
similar_changes.delete(change)
end
end
end
end
def cancel_inverse_change(change, change_type)
if change.inverse?(change_type)
change.cancel
end
end
def inverse?(possible_inverse_change)
is_inverse = false
change_types = YAML.load_file(File.join(NotificationManager::Engine.root, 'config/change_types.yaml'))
if self.change_type == change_types[possible_inverse_change]['inverse']
is_inverse = true
end
return is_inverse
end
1 ответ
Да, твой цикл закончился similar_changes
может быть улучшена.
- Это сбивает с толку, чтобы изменить массив, который вы зацикливаете. Я даже не знаю, надежно ли это, потому что я никогда этого не делаю!
- Также не идиоматично, чтобы Ruby полагался на возвращаемое значение
each
,each
обычно используется, чтобы сделать что-то с элементами Enumerable, который уже существует, поэтому использование его возвращаемого значения кажется странным.
Я бы написал это как
similar_changes.reject do |change|
cancel_inverse_change(change, change.change)
change.cancelled?
end