6

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.

Robert Brown
  • 10,888
  • 7
  • 34
  • 40
arkadiy kraportov
  • 3,679
  • 4
  • 33
  • 42

4 Answers4

6

@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.

buruzaemon
  • 3,847
  • 1
  • 23
  • 44
1

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.

Eric Anderson
  • 3,692
  • 4
  • 31
  • 34
0

Yuck! You have my sympathy. I like old_school.names all the time, even when the engine allows for other malarkey...

I assume this is a legacy app?

How about creating a set of views for your rails app to work with?

Robert Brown
  • 10,888
  • 7
  • 34
  • 40
0

Ruby on Rails is opinionated software. It means that its designers have chosen to do things in a specific way and in order to be able to use RoR with success, pleasure, ease, smoothness, etc. you must do it in that specific way. As such if you can't or don't want to follow RoR's table and column naming conventions you are advised to select another framework.

However if you want to stay with RoR yet you want snake_case method names, you can open the ActiveRecord::Base class, intercept calls to undefined methods, ensure that they match the ^[a-z]+(_[a-z]+)*$ regular exception, and if so, convert them to the upper case and call the upper case method. BUT I STRONGLY ADVISE YOU NOT TO DO THAT!!!* :D

Community
  • 1
  • 1
Behrang
  • 46,888
  • 25
  • 118
  • 160
  • Rails may be opinionated software, but it certainly will not stop you from choosing to walk off a cliff should you decide to hiking off the well-worn path. :-) – buruzaemon May 13 '11 at 16:14
  • 2
    _"As such if you can't or don't want to follow RoR's table and column naming conventions you are advised to select another framework"_. I disagree with that advice. "Opinionated" does not mean strict, just easier if you follow the convention. I have worked with legacy schema that do not follow rails conventions on several occasions, with successful outcomes. – Robert Brown May 16 '11 at 00:20
  • What you say is called "Convention or Configuration". RoR follows CoC but it is opinionated software. It's not designed to be a general purpose framework. I have/am using RoR in a project with custom schema naming conventions and most of RoR's querying features are not working for us and we have to fallback to SQL queries. – Behrang May 16 '11 at 03:02
  • That's fine. I'm not saying RoR will work with any schema, and maybe it wont work for @arkadiy here. But but you are saying that RoR wont work unless the schema follows the RoR convention, which I don't agree with. – Robert Brown May 16 '11 at 04:33
  • 2
    It doesn't work the way it should. For example for me `Foo.find(:all, :include => :bars )` is not working ATM, because my `bars` table is instead named `tblBar`. And there's no way to fix this in our app. In non-opinionated frameworks you can even have composite primary keys but with ActiveRecord your PK should be single-column. – Behrang May 16 '11 at 04:40
  • @Behrang, have you raised a SO question for this problem? I have done that in the past no problem. Also, there's a plugin for composite keys (although I've never had to use it). – Robert Brown May 16 '11 at 07:06