rails form_with form_for form for ruby-on-rails ruby-on-rails-3 activerecord symbol

ruby-on-rails - form_with - select rails helper



Cómo almacenar y comparar: símbolos en un ActiveRecord(Ruby on Rails) (7)

Pensé que sería bueno rellenar un campo de estado en una tablaRegistro activo usando constantes. Sin embargo, cuando se trata de verificar si este estado tiene un estado particular, estoy teniendo problemas.

Si hago lo siguiente,

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

luego reajusta el registro e intenta comparar mi estado con el símbolo, la verificación falla. Tengo algo de salida de la consola para mostrar esto.

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

¿Hay una mejor manera de mantener un estado en un registro? ¿Hay alguna manera de probar si un valor de campo actual es igual al símbolo: sin convertir el símbolo: en una cadena? Estoy pensando que puede haber un operador del que no estoy al tanto.


A partir de Rails 4.1, Active Record ahora admite enumeraciones

De las notas de la versión :

2.5 Enumeraciones de registros activos

Declare un atributo enum donde los valores se correlacionan con enteros en la base de datos, pero se puede consultar por nombre.

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 }

Documentación adicional aquí: http://api.rubyonrails.org/v4.1.0/classes/ActiveRecord/Enum.html


A pedido de Ecoologic, aquí está mi comentario como respuesta:

ecoologic tiene una buena solución para usted, pero le recomendaría que se aparte de esto y realice una clase con constantes. Que puede hacer cosas como e.status = Estados :: CANCELADO. E internamente eso podría ser una cadena y no importa. Todavía está usando constantes, y se equivocará si esa constante no existe, y es más limpia de esa manera.


Con Rails 4.1.0, probablemente quiera utilizar enums de Active Record.

Para citar las notas oficiales de la versión :

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 }


Desde Programming Ruby 1.9 , con respecto al operador == en la clase Symbol (página 729):

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

Todo lo que haya almacenado en la base de datos tendrá siempre diferente object_id que el object_id fijo del símbolo (un puntero a una cadena literal, en este caso).


Esto es algo tarde, pero puede ayudar a alguien más.

Si tiene clases con diferentes estados, puede considerar un enfoque que use constantes junto con ámbitos como este:

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

Luego puede encontrar fácilmente registros basados ​​en el estado, de esta manera:

# 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])

¡Espero que esto ayude a alguien más!

EDITAR: Si te gusta más el uso de gemas, la gema simple_enum parece una excelente alternativa.


Si recuerdo bien, los símbolos en ActiveRecord se almacenan en formato yaml, se debe hacer algún tipo de conversión porque no existe un símbolo en db relacional (que conozco, al menos). Cuando lo lees, es una cadena que no coincidirá con tu símbolo y ni siquiera la cadena del símbolo, de hecho, debería ser algo así como:

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

Creo que este complemento puede resolver su problema, pero no lo he usado honestamente. https://github.com/zargony/activerecord_symbolize

* EDIT *

Dejo lo anterior porque recuerdo que esa era la situación que tenía y que puedo corregirme si estoy equivocado, sin embargo, estoy intentando esto ahora y el valor almacenado (Rails 3.1.3) es una cadena simple con el valor de el símbolo, entonces lo siguiente debería ser suficiente.

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

Esto, por supuesto, obligará al valor a ser siempre un símbolo

** EDITAR DESPUÉS DE EDADES ** Creo que está bien en esta situación, ya que está claro que en el DB es una cadena y la lógica es simple, pero desaconsejo totalmente anular los métodos de atributos de DB para agregar lógica más compleja.


También puede sobrescribir el método del reader :

def status read_attribute(:status).to_sym end