13

我试图找出将枚举值存储在 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中做类似的事情来完成这个吗?

仅供参考,我们正在努力保持我们的应用程序超级小,所以如果我可以在没有 GEM 的情况下轻松完成此任务或类似的事情,那就太好了。

任何“标准”方式来做到这一点,因为我想我不是第一个与这个问题作斗争的人?

谢谢!

4

5 回答 5

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

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

于 2014-01-13T07:18:09.683 回答
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
于 2013-02-16T18:57:18.970 回答
4

使用@Godsaur 示例。

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

您可以将字符串值获取为:

MyModel.last.status
=> "beta"

但如果你想要一个“标题”,你可以:

MyModel.last.status.titleize
=> "Beta"
于 2015-04-01T15:04:48.213 回答
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 %>
于 2014-09-18T01:56:33.397 回答
0

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

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 %>
于 2015-04-29T22:24:22.313 回答