在ActiveRecord中存储枚举值并转换为字符串以进行显示的最佳方法

时间:2013-02-16 15:37:44

标签: ruby-on-rails rails-activerecord

我试图弄清楚在activerecord中存储枚举值的最佳方法是什么,但将其转换为“标题”以便在应用中显示。

回顾枚举:

UNREVIEWED = {:title => "Unreviewed", :name => "UNREVIEWED"}
REVIEWED = {:title => "Reviewed", :name => "REVIEWED"}
FLAGGED = {:title => "Flagged as inappropriate", :name => "FLAGGED"} 

所以在java版本中,我习惯在数据库中存储ENUMs名称即(REVIEWED),然后将该名称转换为服务器上的实际枚举,以便我可以在其上调用辅助方法,即:

review = Review.valueOf(review)
review.title()

我可以在rails中做类似的事情来实现这个目标吗?

仅供参考我们努力保持我们的应用程序超小,所以如果我能够很容易地完成这个或类似的事情而没有一个很棒的创业板。

任何“标准”的方式,我想我不是第一个与这个问题斗争的人?

谢谢!

4 个答案:

答案 0 :(得分:29)

ActiveRecord枚举是最好的方法,因为它是框架的一部分(从4.1版开始)。

它的用法非常简单:

<强>移植

class AddEnumToMyModel < ActiveRecord::Migration
  def change
    add_column :my_model, :status, :integer, default: 0
  end
end

<强>型号:

class MyModel < ActiveRecord::Base
  enum status: [:draft, :beta, :public]
end

然后使用它:

MyModel.draft # gets all drafts
MyModel.last.draft? # checks if the last model is draft
MyModel.last.status # gets the string description of the status of my model

有关模式信息,请参阅documentation

答案 1 :(得分:6)

有很多关于这个问题的帖子,我想大多数都指出这些帖子:http://thinkinginrails.com/2010/04/using-enums-for-constants/

我认为这是一个过度设计的东西,你不需要像ruby这样的动态类型语言。

只需使用字符串!

然后你可以使用它:

class Review < ActiveRecord::Base
  validates_inclusion_of :status, :in => ["UNREVIEWED", "REVIEWED", "FLAGGED"]
  def status
    read_attribute(:status)
  end
  def status= (value)
    write_attribute(:status, value)
  end
end

答案 2 :(得分:4)

使用@Godsaur示例。

class MyModel < ActiveRecord::Base
  enum status: [:draft, :beta, :public]
end 

您可以将字符串值设为:

MyModel.last.status
=> "beta"

但如果你想要一个&#34;标题&#34;你可以:

MyModel.last.status.titleize
=> "Beta"

答案 3 :(得分:1)

虽然我同意@Godsaur的答案是正确的 - 我个人不喜欢存储整数值来表示有意义的字符串等价物的方法(假设有足够的数据库索引和/或查询字符串的成本)数据库引擎类似于查询整数。

我的方法通常是将文本值存储在数据库中(以便更容易理解数据库记录)。

my_model.rb

class MyModel < ActiveRecord::Base

  STATUSES = HashWithIndifferentAccess.new({unverified: 'unverified', reviewed: 'reviewed', flagged: 'flagged'})
  #the text values are similar to their symbols key
  #you could also define additional attributes for each key if needed. Ex:
  #STATUSES = {unverified: {title: 'Unverified Text Title', txt: 'unverified'}, ...}

  # assuming a 'status' field
  scope :unverified, -> { where(status: STATUSES[:unverified]) }

  def unverified?
    status == STATUSES[:unverified]
  end

  # Or
  STATUSES.each do |sym, val|
    define_method("#{sym}?") {status == val}
  end
end

my_view.erb

<%= MyModel::STATUSES[@my_model.status] %> or 
<%= MyModel::STATUSES[@my_model.status].title %>