Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CamelCase instead of snake_case in Rails DB

My DB tables and field names are in CamelCase. Is it possible to convert those names into snake_case on a fly? To make model methods look pretty?

The app is JRubyOnRails 3.0 / MSSQL DB / ActiveRecord-JDBC-adapter.

like image 718
arkadiy kraportov Avatar asked May 12 '11 08:05

arkadiy kraportov


People also ask

Does rails use camel case?

There are no cases where we can have a conflict or an ambiguity between names (Rails never uses camelCase)

What is camelCase in Ruby?

It's not complicated: camelCase has a lowercase first character. PascalCase has an uppercase first character.

Is JavaScript camelCase or Snake_case?

camelCase is used by JavaScript itself, by jQuery, and other JavaScript libraries. Do not start names with a $ sign. It will put you in conflict with many JavaScript library names.

Why we use camelCase in JS?

When multiple words are used to form a variable, camel case joins those words together, without any white space, and delineates the start of each new word with a capital letter.


2 Answers

@arkadiy,as a matter of fact, I was looking into this just this very day.

For table names, we of course have the set_table_name method:

class CamelCasedFoo < ActiveRecord::Base
  set_table_name :CamelCasedTable
end

For things like primary keys, we have set_primary_key:

class CamelCasedBar < ActiveRecord::Base
  ...
  set_primary_key "CamelCasedTableID"
end

And it should be possible to alias funky, legacy column names to something more rails-friendly with alias_attribute:

class CamelCasedBaz < ActiveRecord::Base
  ...
  alias_attribute :preferred_delivery, :DeliveryFrequency
end

One key thing to keep in mind is to watch out for any column names that are ruby or rails keywords or magic field names.

Rails appears to have all that metaprogramming goodness to allow you to work around legacy db table names and columns. You may wish to have a read of Jonathan Hui's blog post on "Ruby on Rails 3 Model Working with Legacy Database". And you might want to have a look at the safe_attributes gem.

like image 82
buruzaemon Avatar answered Oct 27 '22 09:10

buruzaemon


I had the same need. @buruzaemon's answer of setting the table_name and primary_key are good but I have a few suggestions to make it better.

I believe the set_* style methods have fallen out of favor and simply setting the attribute directly is recommended these days. So

class Project < ActiveRecord::Base
  self.table_name = 'Projects'
  self.primary_key = 'ProjectId'
end

In addition using alias_attribute to manually alias every attribute seems tedious. It also seems like it could be easy to forget one. Although @Behrangf recommends against it, I don't see anything wrong with using a little meta-programming magic to automatically provide the snake_case version of your attributes. I've created a module that does this automatically. It's not even tied to ActiveRecord so you could also use it in an API wrapper or something else that is mirroring a system that doesn't follow the Ruby conventions. I am tracking the module on Gist but for convenience is is reproduced below:

module Snakeable

  # Patch in our automatic snake_case methods
  def method_missing method, *args 
    if is_snake_case?(method) &&
      respond_to?(camelized = method.to_s.camelize.to_sym)
      send camelized, *args
    else
      super
    end
  end

  # So the object including this module will respond to
  # Object#respond_to? correctly
  def respond_to? method, *args
    super || (
      is_snake_case?(method) &&
      super(method.to_s.camelize.to_sym, *args)
    )
  end

  private

  # Is the given method using the snake_case format
  def is_snake_case? method
    method.to_s =~ /^[a-z]+(?:_[a-z]+)*[?=!]?$/
  end

end

This module does depend on ActiveSupport's camelize method.

like image 32
Eric Anderson Avatar answered Oct 27 '22 10:10

Eric Anderson