Objeto Rails a hash


Tengo el siguiente objeto que ha sido creado

@post = Post.create(:name => 'test', :post_number => 20, :active => true)

Una vez que esto se guarda, quiero ser capaz de obtener el objeto de nuevo a un hash, por ejemplo, haciendo algo como:

@object.to_hash

¿Cómo es posible esto desde dentro de rails?

Author: lucapette, 2010-10-06

10 answers

Si usted está buscando solo atributos, entonces usted puede obtenerlos por:

@post.attributes
 250
Author: Swanand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-06 12:12:40

En la versión más reciente de Rails (aunque no se puede decir cuál exactamente), puedes usar el método as_json:

@post = Post.first
hash = @post.as_json
puts hash.pretty_inspect

Producirá:

{ 
  :name => "test",
  :post_number => 20,
  :active => true
}

Para ir un poco más allá, podría anular ese método para personalizar la forma en que aparecen sus atributos, haciendo algo como esto:

class Post < ActiveRecord::Base
  def as_json(*args)
    {
      :name => "My name is '#{self.name}'",
      :post_number => "Post ##{self.post_number}",
    }
  end
end

Luego, con la misma instancia que la anterior, mostrará:

{ 
  :name => "My name is 'test'",
  :post_number => "Post #20"
}

Esto, por supuesto, significa que debe especificar explícitamente qué atributos deben aparecer.

Espero que esto ayudar.

EDITAR:

También puedes comprobar la gema Hashifiable.

 36
Author: Raf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-08 09:28:02
@object.as_json

As_json tiene una forma muy flexible de configurar objetos complejos de acuerdo con las relaciones del modelo

EJEMPLO

Modelo campaña pertenece a tienda y tiene una list

Modelo list tiene muchas list_tasks y cada uno de list_tasks tiene muchas comentarios

Podemos obtener un json que combina todos esos datos fácilmente.

@campaign.as_json(
    {
        except: [:created_at, :updated_at],
        include: {
            shop: {
                except: [:created_at, :updated_at, :customer_id],
                include: {customer: {except: [:created_at, :updated_at]}}},
            list: {
                except: [:created_at, :updated_at, :observation_id],
                include: {
                    list_tasks: {
                        except: [:created_at, :updated_at],
                        include: {comments: {except: [:created_at, :updated_at]}}
                    }
                }
            },
        },
        methods: :tags
    })

Aviso métodos:: etiquetas puede ayudarle a adjuntar cualquier adicional objeto que no tiene relaciones con los demás. Solo necesita definir un método con el nombre tagsen model campaign. Este método debe devolver lo que necesite (por ejemplo, etiquetas.todos)

Documentación oficial para as_json

 19
Author: Serge Seletskyy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-25 08:27:35

Puede obtener los atributos de un objeto modelo devueltos como un hash utilizando

@post.attributes

O

@post.as_json

as_json le permite incluir asociaciones y sus atributos, así como especificar qué atributos incluir/excluir (consulte la documentación ). Sin embargo, si solo necesita los atributos del objeto base, el benchmarking en mi aplicación con ruby 2.2.3 y rails 4.2.2 demuestra que attributes requiere menos de la mitad de tiempo que as_json.

>> p = Problem.last
 Problem Load (0.5ms)  SELECT  "problems".* FROM "problems"  ORDER BY "problems"."id" DESC LIMIT 1
=> #<Problem id: 137, enabled: true, created_at: "2016-02-19 11:20:28", updated_at: "2016-02-26 07:47:34"> 
>>
>> p.attributes
=> {"id"=>137, "enabled"=>true, "created_at"=>Fri, 19 Feb 2016 11:20:28 UTC +00:00, "updated_at"=>Fri, 26 Feb 2016 07:47:34 UTC +00:00}
>>
>> p.as_json
=> {"id"=>137, "enabled"=>true, "created_at"=>Fri, 19 Feb 2016 11:20:28 UTC +00:00, "updated_at"=>Fri, 26 Feb 2016 07:47:34 UTC +00:00}
>>
>> n = 1000000
>> Benchmark.bmbm do |x|
?>   x.report("attributes") { n.times { p.attributes } }
?>   x.report("as_json")    { n.times { p.as_json } }
>> end
Rehearsal ----------------------------------------------
attributes   6.910000   0.020000   6.930000 (  7.078699)
as_json     14.810000   0.160000  14.970000 ( 15.253316)
------------------------------------ total: 21.900000sec

             user     system      total        real
attributes   6.820000   0.010000   6.830000 (  7.004783)
as_json     14.990000   0.050000  15.040000 ( 15.352894)
 7
Author: John Cole,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 20:27:23

Hay algunas grandes sugerencias aquí.

Creo que vale la pena señalar que puede tratar un modelo de ActiveRecord como un hash de la siguiente manera:

@customer = Customer.new( name: "John Jacob" )
@customer.name    # => "John Jacob"
@customer[:name]  # => "John Jacob"
@customer['name'] # => "John Jacob"

Por lo tanto, en lugar de generar un hash de los atributos, puede usar el objeto en sí como un hash.

 6
Author: Jeffrey Harrington,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 17:50:42

Definitivamente podría usar los atributos para devolver todos los atributos, pero podría agregar un método de instancia a Post, llamarlo "to_hash" y hacer que devuelva los datos que desea en un hash. Algo así como

def to_hash
 { name: self.name, active: true }
end
 6
Author: Curtis Edmond,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-23 06:47:21

No estoy seguro de si eso es lo que necesitas, pero prueba esto en ruby console:

h = Hash.new
h["name"] = "test"
h["post_number"] = 20
h["active"] = true
h

Obviamente te devolverá un hash en la consola. si desea devolver un hash desde dentro de un método, en lugar de solo "h", intente usar "return h.inspect", algo similar a:

def wordcount(str)
  h = Hash.new()
  str.split.each do |key|
    if h[key] == nil
      h[key] = 1
    else
      h[key] = h[key] + 1
    end
  end
  return h.inspect
end
 2
Author: Yuri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-11 20:46:30

Mi solución:

Hash[ post.attributes.map{ |a| [a, post[a]] } ]
 1
Author: fayvor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-05 20:04:42

La respuesta de Swanand es genial.

Si está utilizando FactoryGirl, puede usar su método build para generar el atributo hash sin la clave id. por ejemplo,

build(:post).attributes
 0
Author: Siwei Shen申思维,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-18 08:40:00

Vieja pregunta, pero muy referenciada ... Creo que la mayoría de la gente usa otros métodos, pero hay de hecho un método to_hash, tiene que ser configurado correctamente. Generalmente, pluck es una mejor respuesta después de rails 4 ... responder a esto principalmente porque tuve que buscar un montón para encontrar este hilo o cualquier cosa útil & asumiendo que otros están golpeando el mismo problema...

Nota: no se recomienda esto para todo el mundo, pero casos edge!


De la api de ruby on rails ... http://api.rubyonrails.org/classes/ActiveRecord/Result.html ...

This class encapsulates a result returned from calling #exec_query on any database connection adapter. For example:

result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts')
result # => #<ActiveRecord::Result:0xdeadbeef>

...

# Get an array of hashes representing the result (column => value):
result.to_hash
# => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
      {"id" => 2, "title" => "title_2", "body" => "body_2"},
      ...
     ] ...
 0
Author: Mirv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-16 15:04:08