Class: DeclareSchema::Model::Column

Inherits:
Object
  • Object
show all
Defined in:
lib/declare_schema/model/column.rb

Overview

This class is a wrapper for the ActiveRecord::…::Column class

Constant Summary collapse

SCHEMA_KEYS =
[:type, :limit, :precision, :scale, :null, :default].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, current_table_name, column) ⇒ Column

Returns a new instance of Column.



92
93
94
95
96
97
98
# File 'lib/declare_schema/model/column.rb', line 92

def initialize(model, current_table_name, column)
  @model = model or raise ArgumentError, "must pass model"
  @current_table_name = current_table_name or raise ArgumentError, "must pass current_table_name"
  @column = column or raise ArgumentError, "must pass column"
  @type = @column.type
  self.class.native_type?(@type) or raise UnknownTypeError, "#{@type.inspect}"
end

Instance Attribute Details

#typeObject (readonly)

Returns the value of attribute type.



90
91
92
# File 'lib/declare_schema/model/column.rb', line 90

def type
  @type
end

Class Method Details

.deserialize_default_value(column, type, default_value) ⇒ Object



53
54
55
56
57
58
# File 'lib/declare_schema/model/column.rb', line 53

def deserialize_default_value(column, type, default_value)
  type or raise ArgumentError, "must pass type; got #{type.inspect}"
  cast_type = ActiveRecord::Base.connection.lookup_cast_type_from_column(column) or
    raise "cast_type not found for #{type}"
  cast_type.deserialize(default_value)
end

.equivalent_schema_attributes?(schema_attributes_lhs, schema_attributes_rhs) ⇒ Boolean

Returns:



81
82
83
84
85
86
87
# File 'lib/declare_schema/model/column.rb', line 81

def equivalent_schema_attributes?(schema_attributes_lhs, schema_attributes_rhs)
  db_adapter_name = ActiveRecord::Base.connection.class.name
  normalized_lhs = normalize_schema_attributes(schema_attributes_lhs, db_adapter_name)
  normalized_rhs = normalize_schema_attributes(schema_attributes_rhs, db_adapter_name)

  normalized_lhs == normalized_rhs
end

.native_type?(type) ⇒ Boolean

Returns:



10
11
12
# File 'lib/declare_schema/model/column.rb', line 10

def native_type?(type)
  type != :primary_key && (native_types.empty? || native_types[type]) # empty will happen with NullDBAdapter used in assets:precompile
end

.native_typesObject

MySQL example: { primary_key: “bigint auto_increment PRIMARY KEY”,

string: { name: "varchar", limit: 255 },
text: { name: "text", limit: 65535},
integer: {name: "int", limit: 4 },
float: {name: "float", limit: 24 },
decimal: { name: "decimal" },
datetime: { name: "datetime" },
timestamp: { name: "timestamp" },
time: { name: "time" },
date: { name: "date" },
binary: { name>: "blob", limit: 65535 },
boolean: { name: "tinyint", limit: 1 },
json: { name: "json" } }

SQLite example: { primary_key: “integer PRIMARY KEY AUTOINCREMENT NOT NULL”,

string: { name: "varchar" },
text: { name: "text"},
integer: { name: "integer" },
float: { name: "float" },
decimal: { name: "decimal" },
datetime: { name: "datetime" },
time: { name: "time" },
date: { name: "date" },
binary: { name: "blob" },
boolean: { name: "boolean" },
json: { name: "json" } }


42
43
44
45
46
47
48
49
50
51
# File 'lib/declare_schema/model/column.rb', line 42

def native_types
  @native_types ||= ActiveRecord::Base.connection.native_database_types.tap do |types|
    if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
      types[:text][:limit]    ||= 0xffff
      types[:binary][:limit]  ||= 0xffff

      types[:varbinary] ||= { name: "varbinary" } # TODO: :varbinary is an Invoca addition to Rails; make it a configurable option
    end
  end
end

.normalize_schema_attributes(schema_attributes, db_adapter_name) ⇒ Object

Normalizes schema attributes for the given database adapter name. Note that the un-normalized attributes are still useful for generating migrations because those may be run with a different adapter. This method never mutates its argument.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/declare_schema/model/column.rb', line 64

def normalize_schema_attributes(schema_attributes, db_adapter_name)
  case schema_attributes[:type]
  when :boolean
    schema_attributes.reverse_merge(limit: 1)
  when :integer
    schema_attributes.reverse_merge(limit: 8) if db_adapter_name.match?(/sqlite/i)
  when :float
    schema_attributes.except(:limit)
  when :text
    schema_attributes.except(:limit)          if db_adapter_name.match?(/sqlite/i)
  when :datetime
    schema_attributes.reverse_merge(precision: 0)
  when NilClass
    raise ArgumentError, ":type key not found; keys: #{schema_attributes.keys.inspect}"
  end || schema_attributes
end

Instance Method Details

#schema_attributesObject

omits keys with nil values



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/declare_schema/model/column.rb', line 103

def schema_attributes
  SCHEMA_KEYS.each_with_object({}) do |key, result|
    value =
      case key
      when :default
        self.class.deserialize_default_value(@column, @type, @column.default)
      else
        col_value = @column.send(key)
        if col_value.nil? && (native_type = self.class.native_types[@column.type])
          native_type[key]
        else
          col_value
        end
      end

    result[key] = value unless value.nil?
  end.tap do |result|
    if ActiveRecord::Base.connection.class.name.match?(/mysql/i) && @column.type.in?([:string, :text])
      result.merge!(collation_and_charset_for_column(@current_table_name, @column.name))
    end
  end
end