RestPack/restpack_service

View on GitHub
lib/restpack_service/activerecord/postgres_array_patch.rb

Summary

Maintainability
C
1 day
Test Coverage
#http://stackoverflow.com/questions/17385023/cant-store-array-in-json-field-in-postgresql-rails-cant-cast-array-to-json
require 'active_record'
require 'active_record/connection_adapters/postgresql/cast'
module ActiveRecord::ConnectionAdapters::PostgreSQLColumn::Cast
  def json_to_string(object)
    if Hash === object || Array === object
      ActiveSupport::JSON.encode(object)
    else
      object
    end
  end
end

require 'active_record/connection_adapters/postgresql/quoting'
module ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::Quoting
  def quote(value, column = nil) #:nodoc:
    return super unless column

    sql_type = type_to_sql(column.type, column.limit, column.precision, column.scale)

    case value
    when Range
      if /range$/ =~ sql_type
        "'#{ActiveRecord::ConnectionAdapters::PostgreSQLColumn.range_to_string(value)}'::#{sql_type}"
      else
        super
      end
    when Array
      case sql_type
      when 'point' then super(ActiveRecord::ConnectionAdapters::PostgreSQLColumn.point_to_string(value))
      when 'json' then super(ActiveRecord::ConnectionAdapters::PostgreSQLColumn.json_to_string(value))
      else
        if column.array
          "'#{ActiveRecord::ConnectionAdapters::PostgreSQLColumn.array_to_string(value, column, self).gsub(/'/, "''")}'"
        else
          super
        end
      end
    when Hash
      case sql_type
      when 'hstore' then super(ActiveRecord::ConnectionAdapters::PostgreSQLColumn.hstore_to_string(value), column)
      when 'json' then super(ActiveRecord::ConnectionAdapters::PostgreSQLColumn.json_to_string(value), column)
      else super
      end
    when IPAddr
      case sql_type
      when 'inet', 'cidr' then super(ActiveRecord::ConnectionAdapters::PostgreSQLColumn.cidr_to_string(value), column)
      else super
      end
    when Float
      if value.infinite? && column.type == :datetime
        "'#{value.to_s.downcase}'"
      elsif value.infinite? || value.nan?
        "'#{value.to_s}'"
      else
        super
      end
    when Numeric
      if sql_type == 'money' || [:string, :text].include?(column.type)
        # Not truly string input, so doesn't require (or allow) escape string syntax.
        "'#{value}'"
      else
        super
      end
    when String
      case sql_type
      when 'bytea' then "'#{escape_bytea(value)}'"
      when 'xml'   then "xml '#{quote_string(value)}'"
      when /^bit/
        case value
        when /^[01]*$/      then "B'#{value}'" # Bit-string notation
        when /^[0-9A-F]*$/i then "X'#{value}'" # Hexadecimal notation
        end
      else
        super
      end
    else
      super
    end
  end

  def type_cast(value, column, array_member = false)
    return super(value, column) unless column

    case value
    when Range
      return super(value, column) unless /range$/ =~ column.sql_type
      ActiveRecord::ConnectionAdapters::PostgreSQLColumn.range_to_string(value)
    when NilClass
      if column.array && array_member
        'NULL'
      elsif column.array
        value
      else
        super(value, column)
      end
    when Array
      case column.sql_type
      when 'point' then ActiveRecord::ConnectionAdapters::PostgreSQLColumn.point_to_string(value)
      when 'json' then ActiveRecord::ConnectionAdapters::PostgreSQLColumn.json_to_string(value)
      else
        return super(value, column) unless column.array
        ActiveRecord::ConnectionAdapters::PostgreSQLColumn.array_to_string(value, column, self)
      end
    when String
      return super(value, column) unless 'bytea' == column.sql_type
      { :value => value, :format => 1 }
    when Hash
      case column.sql_type
      when 'hstore' then ActiveRecord::ConnectionAdapters::PostgreSQLColumn.hstore_to_string(value)
      when 'json' then ActiveRecord::ConnectionAdapters::PostgreSQLColumn.json_to_string(value)
      else super(value, column)
      end
    when IPAddr
      return super(value, column) unless ['inet','cidr'].include? column.sql_type
      ActiveRecord::ConnectionAdapters::PostgreSQLColumn.cidr_to_string(value)
    else
      super(value, column)
    end
  end
end