使用Rails时,在Ruby中处理常量的最佳方式是什么?
我有一些常量代表我的模型的字段中的有效选项。 在Ruby中处理这些常量的最好方法是什么?
你可以使用一个数组或哈希来达到这个目的(在你的environment.rb中):
OPTIONS = ['one', 'two', 'three'] OPTIONS = {:one => 1, :two => 2, :three => 3}
或者一个枚举类,它允许你枚举你的常量以及用来关联它们的键:
class Enumeration def Enumeration.add_item(key,value) @hash ||= {} @hash[key]=value end def Enumeration.const_missing(key) @hash[key] end def Enumeration.each @hash.each {|key,value| yield(key,value)} end def Enumeration.values @hash.values || [] end def Enumeration.keys @hash.keys || [] end def Enumeration.[](key) @hash[key] end end
然后你可以从这里得到:
class Values < Enumeration self.add_item(:RED, '#f00') self.add_item(:GREEN, '#0f0') self.add_item(:BLUE, '#00f') end
并像这样使用:
Values::RED => '#f00' Values::GREEN => '#0f0' Values::BLUE => '#00f' Values.keys => [:RED, :GREEN, :BLUE] Values.values => ['#f00', '#0f0', '#00f']
我把它们直接放在模型类中,就像这样:
class MyClass < ActiveRecord::Base ACTIVE_STATUS = "active" INACTIVE_STATUS = "inactive" PENDING_STATUS = "pending" end
然后,当使用另一个类的模型时,我引用常量
@model.status = MyClass::ACTIVE_STATUS @model.save
如果是推动模型行为,那么常量应该是模型的一部分:
class Model < ActiveRecord::Base ONE = 1 TWO = 2 validates_inclusion_of :value, :in => [ONE, TWO] end
这将允许您使用内置的Railsfunction:
>> m=Model.new => #<Model id: nil, value: nil, created_at: nil, updated_at: nil> >> m.valid? => false >> m.value = 1 => 1 >> m.valid? => true
另外,如果你的数据库支持枚举,那么你可以使用类似Enum Column插件的东西。
Rails 4.1增加了对ActiveRecord枚举的支持 。
声明一个enum属性,其值在数据库中映射为整数,但可以按名称查询。
class Conversation < ActiveRecord::Base enum status: [ :active, :archived ] end conversation.archived! conversation.active? # => false conversation.status # => "archived" Conversation.archived # => Relation for all archived Conversations
请参阅其文档以获得详细的信息。
你也可以在你的模型中使用它,如下所示:
class MyModel SOME_ATTR_OPTIONS = { :first_option => 1, :second_option => 2, :third_option => 3 } end
像这样使用它:
if x == MyModel::SOME_ATTR_OPTIONS[:first_option] do this end
您也可以使用模块将常量组合到主题中,
class Runner < ApplicationRecord module RUN_TYPES SYNC = 0 ASYNC = 1 end end
然后,
> Runner::RUN_TYPES::SYNC => 0 > Runner::RUN_TYPES::ASYNC => 1