deepak/easy_rails_money

View on GitHub
lib/easy_rails_money/active_record/migration/table.rb

Summary

Maintainability
A
0 mins
Test Coverage
module EasyRailsMoney
  module ActiveRecord
    module Migration
      module Table
        # called for change_table
        # currency and #money defined in TableDefinition

        # Creates one or two columns to represent a Money object in the named table
        #
        # An integer column for storing Money in its base unit
        # eg. cents for a Dollar denomination and a string for storing
        # its currency name. Can think of it as a persisted or serialized
        # Money object in the database. The integer column is suffixed
        # with '_money' to aid in reflection ie. to find all money
        # columns. Likewise the currency column is suffixed with '_currency'
        # If does not create an individual currency column if a
        # common currency column is defined
        #
        # @param column_names [Array|Symbol|String] List of money columns to add
        # @return is not important and can change
        #
        # @note If we have defined a currency column for a record then only the integer column is defined.
        # @see EasyRailsMoney::ActiveRecord::Migration::SchemaStatements#add_money
        # @see EasyRailsMoney::ActiveRecord::Migration::TableDefinition#money
        # @see EasyRailsMoney::ActiveRecord::Migration::TableDefinition#currency
        # @see EasyRailsMoney::ActiveRecord::Migration::SchemaStatements#remove_money
        def money(column_names, options={})
          Array(column_names).each do |name|
            column "#{name}_money",    :integer, options
            column "#{name}_currency", :string,  options unless has_currency_column?
          end
        end

        # Removes the columns which represent the Money object
        #
        # Removes the two columns added by money. The money amount and
        # the currency column. If there are no remaining money amount columns
        # and a common currency column exists. then it is also removed
        #
        # @param column_names [Array|Symbol|String] List of money columns to remove
        # @return is not important and can change
        #
        # @note If we have defined a currency column for a record then currency column is removed only if no other money column are there
        #
        # @see EasyRailsMoney::ActiveRecord::Migration::SchemaStatements#remove_money
        # @see EasyRailsMoney::ActiveRecord::Migration::SchemaStatements#add_money
        # @see EasyRailsMoney::ActiveRecord::Migration::TableDefinition#currency
        # @note multiple remove_money calls are not supported in one migration. because at this point the schema is different from the migration defined
        def remove_money(*column_names)
          column_names.each do |name|
            remove "#{name}_money"
            remove "#{name}_currency"
          end
          remove_currency unless has_money_columns?
        end

        # Add a common currency column
        #
        # @return is not important and can change
        #
        # Add a common currency column and remove the individual
        # currrency columns if they exist
        def currency options = {}
          remove_currency_columns
          column :currency, :string, options
        end

        # Removes the common currency column
        #
        # Usually we create an currency column for each money
        # columns. We can have multiple money columns in the same
        # record, in which case we can have a single currency
        # column. This helper removes that common curremcy column. For
        # the existing money column it adds back their currency
        # columns as well. It reflects on the database schema by
        # looking at the column name. By convention the money amount
        # column is prefixed by '_money' and the currency column by '_currency'
        #
        # @see EasyRailsMoney::ActiveRecord::Migration::SchemaStatements#remove_currency
        # @see EasyRailsMoney::ActiveRecord::Migration::SchemaStatements#remove_money
        # @see EasyRailsMoney::ActiveRecord::Migration::TableDefinition#currency
        def remove_currency
          remove :currency
          money_columns do |money_column|
            column "#{money_column}_currency", "string"
          end
        end

        protected
        def remove_currency_columns
          money_columns do |money_column|
            remove "#{money_column}_currency"
          end
        end
                
        def columns
          # @base.schema_cache.clear_table_cache! @table_name
          @base.schema_cache.columns[@table_name].map { |x| x.name }
        end

        def has_currency_column?
          columns.select { |x| x == "currency" }.any?
        end

        def money_columns
          columns.select { |col|
            col =~ /_money/
          }.map { |col|
            name = col.match(/(.+)_money/)[1]
            if block_given?
              yield name
            else
              name
            end
          }
        end

        def has_money_columns?
          money_columns.any?
        end
      end
    end
  end
end