On Sun, 20 Aug 2006, Daniel Schierbeck wrote:

>> depending on what you want, the snake_case code i posted works differently:
>> 
>>   irb(main):025:0> lowerize 'BARFoo'
>>   => "barfoo"
>> 
>>   irb(main):026:0> snake_case 'BARFoo'
>>   => "bar_foo"
>> 
>> neither is right - just fyi.
>
> Correct. Your solution has a flaw, too.
>
>  "fooBar".scan(/[A-Z][a-z]+/).map{|w|w.downcase}.join('_') => "bar"

good catch!

> Lets see if we can solve this without peeking at the Rails source :)

here's a start:

harp:~ > cat a.rb
def snake_case string
   return string unless string =~ %r/[A-Z]/
   string.reverse.scan(%r/[A-Z]+|[^A-Z]*[A-Z]+?|[^A-Z]+/).reverse.map{|word| word.reverse.downcase}.join '_'
end

def camel_case string
   return string if string =~ %r/[A-Z]/ and string !~ %r/_/
   words = string.strip.split %r/\s*_+\s*/
   words.map!{|w| w.downcase.sub(%r/^./){|c| c.upcase}}
   words.join
end

if $0 == __FILE__
   require 'test/unit'
   require 'enumerator'

   class T < Test::Unit::TestCase
     tests = {
       "snake_case" => %w[
         ThisIsSomeString this_is_some_string
         fooBar foo_bar
         FooBar foo_bar
         Foo foo
       ],

       "camel_case" => %w[
         this_is_some_string ThisIsSomeString
         foo_bar FooBar
         foo Foo
         foo_bar_foobar FooBarFoobar
       ]
     }

     tests.each do |meth, list|
       testno = -1
       list.each_slice(2) do |arg, expected|
         define_method "test_#{ meth }_#{ testno += 1 }" do
           actual = send meth, arg
           assert_equal expected, actual
         end
       end
     end
   end
end


harp:~ > ruby a.rb
Loaded suite a
Started
........
Finished in 0.001527 seconds.

8 tests, 8 assertions, 0 failures, 0 errors


cheers.

-a
-- 
to foster inner awareness, introspection, and reasoning is more efficient than
meditation and prayer.
- h.h. the 14th dali lama