【问题标题】:What is the best way to handle constants in Ruby when using Rails?使用 Rails 时,在 Ruby 中处理常量的最佳方法是什么?
【发布时间】:2010-09-20 21:53:25
【问题描述】:

我有一些常量代表我模型的一个字段中的有效选项。在 Ruby 中处理这些常量的最佳方法是什么?

【问题讨论】:

标签: ruby-on-rails ruby constants enumeration


【解决方案1】:

您可以为此目的使用数组或哈希(在您的 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']

【讨论】:

  • 我决定采用这个解决方案。我不得不说,它正是我想要的,并且与 ActiveRecord 配合得很好。谢谢! :D
【解决方案2】:

我直接把它们放在模型类中,像这样:

class MyClass < ActiveRecord::Base
  ACTIVE_STATUS = "active"
  INACTIVE_STATUS = "inactive"
  PENDING_STATUS = "pending"
end

然后,当使用另一个类的模型时,我会引用常量

@model.status = MyClass::ACTIVE_STATUS
@model.save

【讨论】:

  • 那是一个方法而不是一个类。需要使用“class”而不是“def”。
【解决方案3】:

如果是驱动模型行为,那么常量应该是模型的一部分:

class Model < ActiveRecord::Base
  ONE = 1
  TWO = 2

  validates_inclusion_of :value, :in => [ONE, TWO]
end

这将允许您使用内置的 Rails 功能:

>> 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 插件之类的东西。

【讨论】:

    【解决方案4】:

    添加了 Rails 4.1 support for ActiveRecord enums

    声明一个枚举属性,其中值映射到数据库中的整数,但可以通过名称查询。

    class Conversation < ActiveRecord::Base
      enum status: [ :active, :archived ]
    end
    
    conversation.archived!
    conversation.active? # => false
    conversation.status  # => "archived"
    
    Conversation.archived # => Relation for all archived Conversations
    

    请参阅its documentation 了解详细信息。

    【讨论】:

    • 我认为这是最好的答案。
    • 当您尝试将列表中没有的值分配给状态字段时准备好获取异常,并准备好在添加另一个具有 [:active] 值的枚举字段时出现名称冲突. Rails 实现这个功能真的很尴尬。
    • 我制作了一个用于验证枚举包含的 gem github.com/CristiRazvi/enum_attributes_validation
    【解决方案5】:

    你也可以在你的模型中使用它,像这样:

    
    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
    
    

    【讨论】:

    • 谢谢。将符号分组到一个数组中是一种灵感。
    【解决方案6】:

    您还可以使用模块将常量分组为主题 --

    class Runner < ApplicationRecord
        module RUN_TYPES
            SYNC = 0
            ASYNC = 1
        end
    end
    

    然后有,

    > Runner::RUN_TYPES::SYNC
     => 0
    > Runner::RUN_TYPES::ASYNC
     => 1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-29
      • 1970-01-01
      • 2010-11-09
      • 2021-02-22
      • 1970-01-01
      • 2019-03-13
      • 2010-12-04
      • 1970-01-01
      相关资源
      最近更新 更多