How to store and compare :symbols in an ActiveRecord (Ruby on Rails)

后端 未结 7 1365
梦谈多话
梦谈多话 2021-02-05 04:51

I thought it would be good to populate a status field in an activeRecord table using constants. However, when it comes to checking if this status has a particular status, I\'m h

相关标签:
7条回答
  • 2021-02-05 04:59

    If I remember well symbols in ActiveRecord are stored in yaml format, some kind of conversion must be done because there is no such thing as a symbol in relational db (which I'm aware of, at least). When you read it it's then a string which will not match your symbol and not even the string of the symbol, in fact it should be something like:

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

    I think this plugin can solve your problem, but I haven't used it honestly. https://github.com/zargony/activerecord_symbolize

    * EDIT *

    I leave the above because I remember that was the situation I had and I can be corrected if I'm wrong, nonetheless I'm trying this right now and the stored value (Rails 3.1.3) is a simple string with the value of the symbol, so the following should be enough.

    class Example < ActiveRecord::Base
    
      def aaa
        super.to_sym
      end
    
      def aaa=(value)
        super(value.to_sym)
        aaa
      end
    
    end
    

    This of course will force the value to always be a symbol

    ** EDIT AFTER AGES ** I think it's fine in this situation as it's clear that in the db it's a string and the logic is simple, but I strongly discourage overriding db attribute methods to add more complex logic.

    0 讨论(0)
  • 2021-02-05 05:02

    At the request of ecoologic, here is my comment as an answer:

    ecoologic has a good solution for you, but I would recommend steering away from this and making a class with constants in it. That you can do things like e.status = Statuses::CANCELLED. And internally that could be a string and it doesn't matter. You're still using constants, and it will error out if that constant doesn't exist, and it's cleaner that way.

    0 讨论(0)
  • 2021-02-05 05:08

    Also you can overwrite the reader method:

    def status
      read_attribute(:status).to_sym
    end
    
    0 讨论(0)
  • 2021-02-05 05:09

    As of Rails 4.1, Active Record now supports enums

    From the release notes:

    2.5 Active Record enums

    Declare an enum attribute where the values map to integers in the database, but can be queried by name.

    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 }
    

    Additional documentation here: http://api.rubyonrails.org/v4.1.0/classes/ActiveRecord/Enum.html

    0 讨论(0)
  • 2021-02-05 05:16

    With Rails 4.1.0, you'd probably want to use Active Record enums.

    To quote the 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 }
    
    0 讨论(0)
  • 2021-02-05 05:19

    From Programming Ruby 1.9, regarding the == operator in the Symbol class (p. 729):

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

    Whatever you have stored in the DB will always have different object_id than the fixed object_id of the symbol (a pointer to a string literal, in this case).

    0 讨论(0)
提交回复
热议问题