0

Here is a ruby hash:

a = {
  :testOne => 1,
  :testTwo => 2
} 

How can I rename the keys so that they are underscored?

a = {
  :test_one => 1,
  :test_two => 2
}

Ken Bloom got me on the right tract here. You do need ActiveSupport or Rails3. You don't need any specific gems for this solution however:

hash = Hash[a.map {|k,v| [k.to_s.underscore.to_sym, v]}]

Thanks ken!

thenengah
  • 42,557
  • 33
  • 113
  • 157
  • 1
    ActiveSupport is a gem, but using a gem is not inherently bad as long as it is one that is very popular, such as ActiveSupport. The bigger issue is that ActiveSupport is a very large gem, so you want to grab only the parts you need: `require 'active_support/core_ext/string/inflections'`. – the Tin Man Jul 05 '11 at 21:54

2 Answers2

4
Hash[a.map { |k,v| [k.to_s.downcase.sub('test','test_').to_sym, v] }]

Update: If you need to find the common root string, you can use this:

root = a.keys.inject do |m, e|
    s = m.to_s
    s.chop! while !e.to_s.start_with? s
    s
  end
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • Thanks, how is this better than the solution I a adjusted from Ken's answer? – thenengah Jul 05 '11 at 21:44
  • 2
    As you can see, this doesn't use the method `underscore` or `to_h` which are parts of other gems. What @DigitalRoss has provided here doesn't require either, but will do the conversion about which you inquired. – Ryanmt Jul 05 '11 at 21:48
  • `sub('test','test_')` How is this dynamic or could it be made to be dynamic? – thenengah Jul 05 '11 at 22:17
  • ThisIsNotTheMostGeneralWayToConvertCamelCaseStringsToUnderscores. it_will_fail_with_the_first_sentence_of_this_answer. ThatIsWhyIUsedActiveSupport. but_you_can_also_look_at_the_answers_in_the_comment_by_G_A. – Ken Bloom Jul 06 '11 at 01:48
  • @Ken, sure, but that answer was already posted, and there seemed to be some interest in a simplified solution. Sometimes you don't find out what the OP really wanted until you try something. – DigitalRoss Jul 06 '11 at 14:47
2

This answer requires the facets gem, and activesupport (which is part of rails).

require 'active_support'
require 'facets'

a.map{|k,v| [k.to_s.underscore.to_sym, v]}.to_h
#                  ^^^^^^^^^^^             ^^^^ from facets
#                  from activesupport
Ken Bloom
  • 57,498
  • 14
  • 111
  • 168
  • Thanks! But I am looking for a way to do this without a gem. – thenengah Jul 05 '11 at 21:28
  • +1, I delete my answer, you were faster. Use Hash[...] is facets is not available. Note that also that this creates a new hash (which is the right thing to do!) – tokland Jul 05 '11 at 21:29
  • 1
    Camelcase to underscore code can be found in the answer to this question. http://stackoverflow.com/questions/1509915/converting-camel-case-to-underscore-case-in-ruby – GregA100k Jul 05 '11 at 21:35