【问题标题】:How to compare Rails enum types如何比较 Rails 枚举类型
【发布时间】:2014-12-29 12:27:02
【问题描述】:

我的 Rails (4) 应用程序中有以下枚举模型:

class Dual < ActiveRecord::Base
  enum dual: [:dual, :not_dual]

  validates :dual, uniqueness: true
  validates :dual, presence: true
end

我还有另一个模型,它有很多 Duals:

class SillColour < ActiveRecord::Base
  has_many :sill_colour_duals, dependent: :destroy
  has_many :duals, through: :sill_colour_duals
end

我希望能够测试SillColour 的实例是否具有Dual 枚举。这就是我可以开始工作的全部:

dual = Dual.find(1)
not_dual = Dual.find(2)

sill_colour.duals.include?(dual)
sill_colour.duals.include?(not_dual)

显然这是非常不可靠的,因为 Duals 的 ID 可能是生产中的任何东西(因为测试 ID 是固定的)。我试过这个:

dual = Dual.where(dual: 0)
not_dual = Dual.where(dual: 1)

甚至给定数据库对偶表如下所示:

 id | dual 
----+------
  1 |    0
  2 |    1

我的测试失败了,这似乎是因为 dualnon_dual 不再正确比较。我用 pry 检查了它们,它们看起来和以前一样,但显然它们不是。

肯定有更好的方法吗?我设想能够做到这一点:

sill_colour.duals.include?(Dual.dual)
sill_colour.duals.include?(Dual.not_dual)

但这也不起作用。

有什么建议吗?

【问题讨论】:

  • 试试sill_colour.duals.any? {|d| d.dual?}sill_colour.duals.any? {|d| d.not_dual?}
  • 谢谢!这成功了!尽管 Rubocop 不喜欢它:'Pass &:dual?作为任何的论据?而不是一个块。我正在调查。
  • 而不是块:sill_colour.duals.where(dual: Dual.dual['dual']).any? 返回真或假。您不是在寻找真假答案吗?
  • 另外,Dual.dual['dual'] 看起来很讨厌。如果允许,您可能希望将双枚举更改为 dual_status 之类的东西。所以上面的语句将是sill_colour.duals.where(dual_status: Dual.dual_status['dual']).any?

标签: ruby-on-rails ruby enums


【解决方案1】:

我会尝试用我的应用程序中的代码来回答

class User < ActiveRecord::Base
  has_many :contacts
end

class Contact < ActiveRecord::Base
  enum status: [:dual, :not_dual]

  # see scopes
  scope :dual, -> {where(status:  Contact.statuses['dual']) }
  scope :not_dual, -> {where(status:  Contact.statuses['not_dual']) }
end

现在控制台,检查用户实例是否有双重状态的联系人:

2.1.5 :001 > u = User.last
  User Load (0.8ms)  SELECT  "users".* FROM "users"   ORDER BY "users"."id" DESC LIMIT 1
 => #<User id: 1, email: "...", ...> 
2.1.5 :003 > u.contacts.dual
  Contact Load (0.3ms)  SELECT "contacts".* FROM "contacts"  WHERE "contacts"."user_id" = $1 AND "contacts"."status" = 0  [["user_id", 1]]
 => #<ActiveRecord::AssociationRelation []> 
2.1.5 :004 > u.contacts.not_dual
  Contact Load (0.3ms)  SELECT "contacts".* FROM "contacts"  WHERE "contacts"."user_id" = $1 AND "contacts"."status" = 1  [["user_id", 1]]
 => #<ActiveRecord::AssociationRelation []> 

如您所见,两者都返回空数组,因此在空数组上调用 any? 将同时返回 false。因为我和 status dual 或 not_dual 没有任何联系,所以我们创建一个。

查找联系人:

2.1.5 :005 > c = Contact.last
  Contact Load (0.5ms)  SELECT  "contacts".* FROM "contacts"   ORDER BY "contacts"."id" DESC LIMIT 1
  => #<Contact id: 3, user_id: 1, ..., ...., status: nil> 

设置为对偶:

2.1.5 :006 > c.dual!
   (0.1ms)  BEGIN
  SQL (15.1ms)  UPDATE "contacts" SET "status" = $1, "updated_at" = $2 WHERE "contacts"."id" = 3  [["status", 0], ["updated_at", "2014-12-29 13:16:45.576778"]]
   (25.5ms)  COMMIT
 => true

现在检查用户是否有双重或非双重联系人:

2.1.5 :009 > u.contacts.dual.any?
   (0.2ms)  SELECT COUNT(*) FROM "contacts"  WHERE "contacts"."user_id" = $1 AND "contacts"."status" = 0  [["user_id", 1]]
 => true 
2.1.5 :010 > u.contacts.not_dual.any?
   (0.3ms)  SELECT COUNT(*) FROM "contacts"  WHERE "contacts"."user_id" = $1 AND "contacts"."status" = 1  [["user_id", 1]]
 => false 
2.1.5 :011 > 

检查用户实例是否有 dual 枚举返回 true。在您的情况下,它将是 sill_colour,而不是用户。

如果您不喜欢范围,可以使用where

u.contacts.where(status: Contact.statuses['dual']).any?
=> true

http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html

class Dual < ActiveRecord::Base
  enum status: [:dual, :not_dual]
end

拥有上述类,您可以像这样检查状态:

dual = Dual.find(params[:id])
dual.dual? # will return true or false depends on the status you set.
dual.not_dual? # same, true or false
dual.status = "dual" # if status was set to 0 or not_dual if status was set to 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-28
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 2017-02-08
    相关资源
    最近更新 更多