Varun Jain
Varun Jain

Reputation: 1911

Ruby convert all values in a hash to string

I have the following snippet of code to fetch certain columns from the db:

 @data =  Topic.select("id,name").where("id in (?)",@question.question_topic.split(",")).map(&:attributes)

In the resulting Array of Hashes which is :

Current:

@data =    [ { "id" => 2, "name" => "Sports" }]

To be changed to:

@data =    [ { "id" => "2", "name" => "Sports" }]

I want to convert "id" to string from fixnum. Id is integer in the db. What is the cleanest way to do this?

Note: After using .map(&:attributes) it is not an active record relation.

Upvotes: 1

Views: 13809

Answers (5)

Yuri Tytarenko
Yuri Tytarenko

Reputation: 21

@data.each {|data_item| data_item.transform_values!(&:to_s)}

Upvotes: 0

Justin Kenyon
Justin Kenyon

Reputation: 1

You can use Ruby's #inject here:

@data.map do |datum|
  new_datum = datum.inject({}) do |converted_datum, (key, value)|
    converted_datum[key] = value.to_s

    converted_datum
  end
end

This will work to convert all values to strings, regardless of the key.

If you are using Rails it can be even cleaner with Rails' #each_with_object:

@data.map do |datum|
  datum.each_with_object({}) do |(key, value), converted_datum|
    converted_datum[key] = value.to_s
  end
end

Upvotes: 0

Winston Kotzan
Winston Kotzan

Reputation: 2087

This will iterate all the key names in the hash and replace the value with the #to_s version of the datum associated with the key. nil's converted to empty strings. Also, this assumes you don't have complex data within the hash like embedded arrays or other hashes.

def hash_values_to_string(hash)
  hash.keys.each {|k| hash[k]=hash[k].to_s}; hash
end

Upvotes: -1

Niall Paterson
Niall Paterson

Reputation: 3580

What you're looking for is simply

@data.each { |obj| obj["id"] = obj["id"].to_s }

There isn't really a simpler way (I think that's straightforward enough anyway).

Going by the title which implies a different question - converting every value in the hash to a string you can do this:

@data.each do |obj| 
  obj.map do |k, v|        
      {k => v.to_s} 
  end
end

Just leaving that there anyway.

Upvotes: 1

Marek Lipka
Marek Lipka

Reputation: 51151

You can do it with proper map usage:

topics = Topic.select("id,name").where("id in (?)",@question.question_topic.split(","))
@data = topics.map do |topic|
  {
    'id' => topic.id.to_s,
    'name' => topic.name
  }
end

Upvotes: 3

Related Questions