4

I am thinking about choosing rails' ActiveRecord to have access to a legacy database. It's names are really confusing, so it wouldn't be a good idea to use its column names in the model.

Setting table name is really easy. But do I have a way to rename column name, only in the model?

Convention over configuration is great, but in this case I can't change legacy database names.

Using alias_attribute from ActiveSupport doesn't solve my problem, since the object still shows the legacy column names when being serialized or printed. I need to return these models in JSON format, for instance, and alias_attribute wouldn't be suitable for this.

Victor Rodrigues
  • 11,353
  • 23
  • 75
  • 107
  • Looks like a duplicate of [Alias for column names in Rails] : http://stackoverflow.com/questions/4014831/alias-for-column-names-in-rails – Zabba Feb 28 '11 at 21:51
  • 1
    not really. he's talking about aliasing columns, here the question is slightly different. none of its answers applies to what I need to do here. – Victor Rodrigues Feb 28 '11 at 21:54
  • so far, I think the best option is to rewrite ActiveModel::Serialization `serializable_hash` method. Not for everybody, just these models. – Victor Rodrigues Feb 28 '11 at 22:23

2 Answers2

4

use alias_attribute in your model. e.g.

alias_attribute :new_column_name, :column_name_in_db

for more details, refer to : https://stackoverflow.com/a/4017071/445908

Community
  • 1
  • 1
Siwei
  • 19,858
  • 7
  • 75
  • 95
3

What did I do to achieve this?

The code below overwrites default ActiveModel::Serialization's serializable_hash, converting column names in it. Not complete, maybe some refactoring would be nice, but it's working ;)

model example:

class Account < ActiveRecord::Base
  include ActiveModel::ColumnNaming

  set_table_name 'conta_tbl'
  set_primary_key 'cod_conta'

  rename_columns ({
    id:                   'cod_conta',
    billing_group_id:     'id_cobranca',
    invoice_id:           'cod_pagamento'
  })
end

code:

module ActiveModel
  module ColumnNaming
    extend ActiveSupport::Concern

    def serializable_hash(options = nil)
      hash = super(options)
      self.class.columns_map.each do |legacy, renamed|
        hash[renamed] = hash.delete(legacy)
      end
      hash
    end

    module ClassMethods
      def columns_map
        @columns_map
      end

      def rename_columns(map)
        @columns_map = map.invert
        columns_map.each { |key, value| alias_attribute value.to_sym, key.to_sym }
      end
    end
  end
end
Victor Rodrigues
  • 11,353
  • 23
  • 75
  • 107