Ruby样式问题:使用不同的可能值存储哈希常量

Bri*_*ong 6 ruby ruby-on-rails

这更像是一个风格问题,我想知道别人做了什么.

假设我的数据库中有一个名为"status"的字段,用于博客文章.我希望它有几个可能的值,例如"草稿","等待审核"和"发布",仅作为示例.

显然,我们不希望每次都在这些神奇的值中"硬编码",这不会是干的.

所以我有时做的是这样的:

class Post
  STATUS = {
    :draft => "draft",
    :awaiting_review => "awaiting review",
    :posted => "posted"
  }

  ...

end
Run Code Online (Sandbox Code Playgroud)

然后,我可以编写代码之后将其称为STATUS[:draft]Post::STATUS[:draft]

这项工作正常,但有一些我不喜欢的事情.

  1. 如果你有一个拼写错误并且调用STATUS[:something_that_does_not_exist]它不会引发错误,它只会返回nil,并且可能会在你注意到bug之前在数据库等中设置它
  2. 它看起来不像干净或ruby-ish写东西if some_var == Post::STATUS[:draft]...

我不知道,有些东西告诉我有更好的方法,但只是想看看其他人做了什么.谢谢!

Far*_*rel 8

您可以使用Hash.new并为其提供一个块参数,如果密钥未知,则会调用该参数.

class Post
  STATUS = Hash.new{ |hash, key| raise( "Key #{ key } is unknown" )}.update(
    :draft => "draft",
    :awaiting_review => "awaiting review",
   :posted => "posted" )
end
Run Code Online (Sandbox Code Playgroud)

它有点乱,但它的工作原理.

irb(main):007:0> Post::STATUS[ :draft ]
=> "draft"
irb(main):008:0> Post::STATUS[ :bogus ]
RuntimeError: Key bogus is unknown
    from (irb):2
    from (irb):8:in `call'
    from (irb):8:in `default'
    from (irb):8:in `[]'
    from (irb):8
Run Code Online (Sandbox Code Playgroud)


Joh*_*lla 6

这是一个常见问题.考虑这样的事情:

class Post < ActiveRecord::Base
  validates_inclusion_of :status, :in => [:draft, :awaiting_review, :posted]
  def status
    read_attribute(:status).to_sym
  end
  def status= (value)
    write_attribute(:status, value.to_s)
  end
end
Run Code Online (Sandbox Code Playgroud)

您可以使用名为symbolize的第三方ActiveRecord插件来使这更容易:

class Post < ActiveRecord::Base
  symbolize :status
end
Run Code Online (Sandbox Code Playgroud)