Victor Rodrigues
Victor Rodrigues

Reputation: 11711

Is there a way to rename ActiveRecord model columns?

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.

Upvotes: 4

Views: 3484

Answers (2)

Siwei
Siwei

Reputation: 21559

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

Upvotes: 4

Victor Rodrigues
Victor Rodrigues

Reputation: 11711

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

Upvotes: 3

Related Questions