2012-01-27 69 views
22

我认为使用常量填充activeRecord表中的状态字段会很好。但是,在检查此状态是否具有特定状态时,我遇到了问题。如何存储和比较:ActiveRecord中的符号(Ruby on Rails)

如果我这样做,

e = Mytable.new 
e.status = :cancelled 
e.save 

然后refind记录,并尝试和我的状态比作象征,检查失败。我有一些来自控制台的输出来显示。

irb(main):060:0> e.status.eql?("cancelled") 
=> true 
irb(main):061:0> e.status.eql?(:cancelled) 
=> false 
irb(main):062:0> e.status == :cancelled 
=> false 
irb(main):063:0> e.status == "cancelled" 
=> true 
irb(main):064:0> e.status == :cancelled.to_s 
=> true 

是否有更好的方式来保存记录中的状态?有没有一种测试方法,如果当前字段值等于:符号而不将该符号转换为字符串?我在想可能有一位我不知道的运营商。

+1

ecoologic有你一个很好的解决方案,但我会建议也许从这个转向远离,也许做一个类与它的常量。您可以执行诸如“e.status = Statuses :: CANCELLED”之类的操作。内部可以是一个字符串,并不重要。你仍然在使用常量,如果该常量不存在,它将会出错,并且它更干净。 – MrDanA 2012-01-27 18:24:28

+0

你为什么不重写列的getter? – apneadiving 2012-01-27 18:35:07

+0

在阅读这两条评论之前,我修改了我的答案,但我想说我喜欢@MrDanA解决方案,您应该写一个答案,我会为它投票! – ecoologic 2012-01-27 21:09:55

回答

7

在ecoologic的要求,在这里是作为一个答案我的评论:

ecoologic有你一个很好的解决方案,但我会从这个建议转向远离,使一类在它的常量。您可以执行诸如e.status = Statuses :: CANCELED之类的操作。内部可以是一个字符串,并不重要。你仍然在使用常量,如果该常量不存在,它将会出错,并且它更干净。

+0

作为最佳实践,你会把这门课放在哪里?在它自己的文件在lib或助手? – seanyboy 2012-01-28 11:21:18

+0

我已将状态类放置在模型文件中。它运作良好。我还添加了一个self.method类将状态转换为颜色。因此,这一切都在一个地方。 – seanyboy 2012-01-28 11:58:21

+1

我通常把它们放在自己的lib文件中,是的。然后您可以通过编辑您的应用程序配置文件自动加载文件(而不必“需要”)。 – MrDanA 2012-01-28 15:30:19

7

如果我记得很好,ActiveRecord中的符号以yaml格式存储,必须进行某种转换,因为在关系数据库中没有这样的符号(至少我知道它)。当你读它,它是那么这将不匹配您的符号甚至没有符号的字符串的字符串,实际上它应该是这样的:

:x # => "--- :x\n" 

我认为这个插件可以解决你的问题,但我避风港没有诚实地使用它。 https://github.com/zargony/activerecord_symbolize

*编辑*

我离开上面,因为我记得那是我的情况,如果我错了,我可以得到纠正,但是我想这个,现在和存储值(Rails 3.1.3)是一个带符号值的简单字符串,所以以下内容应该足够了。

class Example < ActiveRecord::Base 

    def aaa 
    super.to_sym 
    end 

    def aaa=(value) 
    super(value.to_sym) 
    aaa 
    end 

end 

当然,这将迫使值永远是一个符号

**编辑AGES后** 我认为这是在这种情况下罚款,很明显,在分贝它是一个字符串和逻辑很简单,但我强烈建议不要重写db属性方法来添加更复杂的逻辑。

+1

也请记住,在用户输入中使用:to_sym是个坏主意:http://www.tricksonrails.com/2010/06/avoid-memory-leaks-in-ruby-rails-code-and-protect-against -denial-of-service/ – oseiskar 2013-04-25 13:02:28

+0

值得一提的是,这是不好的做法 – ecoologic 2013-04-25 22:52:16

1

编程Ruby 1.9的,关于符号类的==操作符(第729):

Returns true only if sym and obj are symbols with the same object_id. 

无论您有任何存储在数据库中总是有不同的object_id比固定OBJECT_ID符号(在这种情况下是指向字符串文字的指针)。

5

您也可以覆盖reader方法:

def status 
    read_attribute(:status).to_sym 
end 
8

这有点晚,但可以帮助别人。

如果你有不同的状态类,你可以使用常量,像这样的作用域一起考虑的一个办法:

class Account < ActiveRecord::Base 
    #------------------------------------------------------------------------------- 
    # Configuration 
    #------------------------------------------------------------------------------- 

    # STATUS is used to denote what state the account is in. 
    STATUS = { :active => 1, :suspended => 2, :closed => 3 } 

    # Scopes 
    scope :active, where(:status => Account::STATUS[:active]) 
    scope :suspended, where(:status => Account::STATUS[:suspended]) 
    scope :closed, where(:status => Account::STATUS[:closed]) 
    ... 
end 

然后你就可以很容易地找到记录基于状态,就像这样:

# get all active accounts 
active_accounts = Consumer.active.all 
# get 50 suspended accounts 
suspended_accounts = Consumer.suspended.limit(50) 
# get accounts that are closed and [some search criteria] 
closed_accounts = Consumer.closed.where([some search criteria]) 

希望这可以帮助别人!

编辑: 如果你更多地使用宝石,simple_enum宝石看起来是一个很好的选择。

12

使用Rails 4.1.0,您可能想要使用Active Record枚举。

引述official release notes

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

铁轨4.1,活动记录现在支持枚举

release notes

2.5的Active Record枚举

声明一个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 

Conversation.statuses # => { "active" => 0, "archived" => 1 } 

附加文档在这里:http://api.rubyonrails.org/v4.1.0/classes/ActiveRecord/Enum.html

相关问题