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

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

IE

评论枚举:

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中做到这一点?

仅供参考我们试图保持我们的应用程序超小,所以如果我能够很容易地实现这个或类似的东西没有一个伟大的创业板。

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

谢谢!

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 

有关模式信息,请参阅文档 。

有很多关于这个问题的post,我猜大多数都是这个post: 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 

使用@Godsaur示例。

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

您可以获取字符串值:

 MyModel.last.status => "beta" 

但如果你想要一个“头衔”,你可以:

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

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

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

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 %> 

我同意@tamersalama。 这是使用自定义Enum类在DB中使用字符串的简单方法。 请注意,这也支持用于下拉菜单的人类可读名称。

https://gist.github.com/alexch/a7be54e1b085718473ff

SQL:

 Table name: snacks id :integer ice_cream :string 

扶手:

 class Snack < ActiveRecord::Base FLAVORS = Enum.new [ [:vanilla, "Vanilla"], [:chocolate, "Chocolate"], [:rocky_road, "Rocky Road"] ]) ] end 

HTML:

 <%= simple_form_for @snack do |f| %> <%= f.collection_select :ice_cream, Snack::FLAVORS, :value, :label %> <% end %>