Como converter os resultados do ActiveRecord em uma série de hashes

112

Tenho um resultado ActiveRecord de uma operação de localização:

tasks_records = TaskStoreStatus.find(
  :all,
  :select => "task_id, store_name, store_region",
  :conditions => ["task_status = ? and store_id = ?", "f", store_id]
)

Agora, quero converter esses resultados em uma matriz de hashes como esta:

[0] ->  { :task_d => 10, :store_name=> "Koramanagala", :store_region=> "India" }

[1] -> { :task_d => 10, :store_name=> "Koramanagala", :store_region=> "India" }

[2] ->  { :task_d => 10, :store_name=> "Koramanagala", :store_region=> "India" }

para que eu possa iterar pela matriz e adicionar mais elementos aos hashes e, posteriormente, converter o resultado em JSONpara minha resposta da API. Como posso fazer isso?

Avinash Mb
fonte
Consulte também stackoverflow.com/q/20794398/165673
Yarin

Respostas:

210

as_json

Você deve usar o as_jsonmétodo que converte objetos ActiveRecord em Ruby Hashes, apesar de seu nome

tasks_records = TaskStoreStatus.all
tasks_records = tasks_records.as_json

# You can now add new records and return the result as json by calling `to_json`

tasks_records << TaskStoreStatus.last.as_json
tasks_records << { :task_id => 10, :store_name => "Koramanagala", :store_region => "India" }
tasks_records.to_json

serializable_hash

Você também pode converter qualquer objeto ActiveRecord em um Hash com serializable_hashe pode converter qualquer resultado ActiveRecord em um Array com to_a, portanto, para seu exemplo:

tasks_records = TaskStoreStatus.all
tasks_records.to_a.map(&:serializable_hash)

E se você quiser uma solução feia para Rails antes da v2.3

JSON.parse(tasks_records.to_json) # please don't do it
Hdorio
fonte
4
+1 Por sugerir serializable_hash - esta é a primeira vez que encontro uma resposta que menciona isso. Infelizmente, estou usando a última solução JSON, mas agora examinarei o uso de serializable_hash. Eu só preciso descobrir como incluir o nome da classe em cada registro, o mesmo que você pode obter se incluir root em JSON.
Dom
@Dom 웃 Se bem entendi, veja isto: stackoverflow.com/questions/17090891/…
hdorio
@Dom veja minha resposta abaixo.
Fredrik E
Outra maneira possível é tasks_records = TaskStoreStatus.all.map(&:attributes).
Rigo
Grandes soluções realmente mais aqui, mas a minha pergunta poderia ser Quais são os benefícios de usar um ou outro .as_json, &:serializable_hashe &:attributes? Tem a ver com auxiliares ActiveRecord ou diretamente com desempenho? obrigado antecipadamente pessoal! @Dom @Rigo @Fredrik E
alexventuraio
35

Talvez?

result.map(&:attributes)

Se você precisar de chaves de símbolos:

result.map { |r| r.attributes.symbolize_keys }
Elena Unanyan
fonte
9

Para o ActiveRecord atual (4.2.4+), há um método to_hashno Resultobjeto que retorna um array de hashes. Você pode então mapear sobre ele e converter em hashes simbolizados:

# 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"},
      ...
     ]

result.to_hash.map(&:symbolize_keys)
# => [{:id => 1, :title => "title_1", :body => "body_1"},
      {:id => 2, :title => "title_2", :body => "body_2"},
      ...
     ]

Veja a documentação ActiveRecord :: Result para mais informações .

Sventechie
fonte
Não pode ser mais simples e claro do que isso. Muito obrigado.
WM
1
Uma nota se sua versão do ActiveRecord não está reconhecendo o to_hashmétodo: tente to_ary. Estranhamente, isso funcionou para mim.
Phil