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?
10 answers
Si usted está buscando solo atributos, entonces usted puede obtenerlos por:
@post.attributes
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.
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
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)
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.
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
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
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]] } ]
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
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"},
...
] ...
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