Rails结合了enum和find_or_initialize_by方法的搜索

时间:2015-06-20 11:42:56

标签: ruby-on-rails ruby activerecord enums

此问题基于以下问题:Rails find_or_create_by with/without where

我遇到了一些关于enum&的奇怪问题。 rails中的find_or_initialize_by方法。

假设我有模型Task

class Task < AR::Base
  enum status: { todo: 0, awaiting: 1, done: 2, another_one: 3, et.c. }

我希望通过todoawaiting任务查找,如果不存在,请创建一个新任务,但没有todoawaiting值(状态)应该只是零)。但是,ActiveRecord::Enum在这里罢工!

在大多数情况下,这是正常的代码:

Task.where(status: [Task.statuses[:todo], Task.statuses[:awaiting]]).find_or_initialize_by(title: 'epic')

但由于this字符串,我感到烦恼'[0, 1]' is not a valid status异常。如果没有多余的代码,我该如何避免这种异常呢?

2 个答案:

答案 0 :(得分:0)

查询枚举属性时,应使用the symbol representing the enum而不是实际的整数列值:

@task = Task.where(status: [:todo, :awaiting])
            .find_or_initialize_by(title: 'epic')

因此,'[0, 1]' is not a valid status因为Rails试图提供帮助并为您查找枚举值。通常,除非您正在构建自定义SQL字符串,否则几乎不需要使用实际的整数值:

Task.where.not(status: :awaiting)

Rails还根据枚举生成范围:

@tasks = Task.todo.awaiting.find_or_initialize_by(title: 'epic')
# or
@tasks = Task.todo.merge(Task.awaiting)
             .find_or_initialize_by(title: 'epic')

答案 1 :(得分:0)

现在我看到一个相对较酷的解决方案。如果有人能更好地提供解决方案,那将会很棒。

  1. 安装gem 'active_record_union'
  2. 使用它!

    Task.todo.union(Task.awaiting).union(Task.starting)