Class: DeclareSchema::Model::FieldSpec
- Inherits:
-
Object
- Object
- DeclareSchema::Model::FieldSpec
show all
- Defined in:
- lib/declare_schema/model/field_spec.rb
Defined Under Namespace
Classes: UnknownSqlTypeError
Constant Summary
collapse
- MYSQL_TINYTEXT_LIMIT =
0xff
- MYSQL_TEXT_LIMIT =
0xffff
- MYSQL_MEDIUMTEXT_LIMIT =
0xff_ffff
- MYSQL_LONGTEXT_LIMIT =
0xffff_ffff
- MYSQL_TEXT_LIMITS_ASCENDING =
[MYSQL_TINYTEXT_LIMIT, MYSQL_TEXT_LIMIT, MYSQL_MEDIUMTEXT_LIMIT, MYSQL_LONGTEXT_LIMIT].freeze
- TYPE_SYNONYMS =
{ timestamp: :datetime }.freeze
- SQLITE_COLUMN_CLASS =
begin
ActiveRecord::ConnectionAdapters::SQLiteColumn
rescue NameError
NilClass
end
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(model, name, type, options = {}) ⇒ FieldSpec
Returns a new instance of FieldSpec.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
# File 'lib/declare_schema/model/field_spec.rb', line 36
def initialize(model, name, type, options = {})
name == "id" and raise ArgumentError, "you cannot provide a field spec for the primary key"
@model = model
@name = name.to_sym
type.is_a?(Symbol) or raise ArgumentError, "type must be a Symbol; got #{type.inspect}"
@type = type
position_option = options.delete(:position)
@options = options
case type
when :text
@options[:default] and raise "default may not be given for :text field #{model}##{@name}"
if self.class.mysql_text_limits?
@options[:limit] = self.class.round_up_mysql_text_limit(@options[:limit] || MYSQL_LONGTEXT_LIMIT)
end
when :string
@options[:limit] or raise "limit must be given for :string field #{model}##{@name}: #{@options.inspect}; do you want `limit: 255`?"
end
@position = position_option || model.field_specs.length
end
|
Instance Attribute Details
#model ⇒ Object
Returns the value of attribute model.
34
35
36
|
# File 'lib/declare_schema/model/field_spec.rb', line 34
def model
@model
end
|
#name ⇒ Object
Returns the value of attribute name.
34
35
36
|
# File 'lib/declare_schema/model/field_spec.rb', line 34
def name
@name
end
|
#options ⇒ Object
Returns the value of attribute options.
34
35
36
|
# File 'lib/declare_schema/model/field_spec.rb', line 34
def options
@options
end
|
#position ⇒ Object
Returns the value of attribute position.
34
35
36
|
# File 'lib/declare_schema/model/field_spec.rb', line 34
def position
@position
end
|
#type ⇒ Object
Returns the value of attribute type.
34
35
36
|
# File 'lib/declare_schema/model/field_spec.rb', line 34
def type
@type
end
|
Class Method Details
.mysql_text_limits? ⇒ Boolean
method for easy stubbing in tests
17
18
19
20
21
22
23
|
# File 'lib/declare_schema/model/field_spec.rb', line 17
def mysql_text_limits?
if defined?(@mysql_text_limits)
@mysql_text_limits
else
@mysql_text_limits = ActiveRecord::Base.connection.class.name.match?(/mysql/i)
end
end
|
.round_up_mysql_text_limit(limit) ⇒ Object
25
26
27
28
29
30
31
|
# File 'lib/declare_schema/model/field_spec.rb', line 25
def round_up_mysql_text_limit(limit)
MYSQL_TEXT_LIMITS_ASCENDING.find do |mysql_supported_text_limit|
if limit <= mysql_supported_text_limit
mysql_supported_text_limit
end
end or raise ArgumentError, "limit of #{limit} is too large for MySQL"
end
|
Instance Method Details
#default ⇒ Object
101
102
103
|
# File 'lib/declare_schema/model/field_spec.rb', line 101
def default
@options[:default]
end
|
#different_to?(col_spec) ⇒ Boolean
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
# File 'lib/declare_schema/model/field_spec.rb', line 112
def different_to?(col_spec)
!same_type?(col_spec) ||
begin
native_type = native_types[type]
check_attributes = [:null, :default]
check_attributes += [:precision, :scale] if sql_type == :decimal && !col_spec.is_a?(SQLITE_COLUMN_CLASS) check_attributes -= [:default] if sql_type == :text && col_spec.class.name =~ /mysql/i
check_attributes << :limit if sql_type.in?([:string, :binary, :varbinary, :integer, :enum]) ||
(sql_type == :text && self.class.mysql_text_limits?)
check_attributes.any? do |k|
if k == :default
case Rails::VERSION::MAJOR
when 4
col_spec.type_cast_from_database(col_spec.default) != col_spec.type_cast_from_database(default)
else
cast_type = ActiveRecord::Base.connection.lookup_cast_type_from_column(col_spec) or raise "cast_type not found for #{col_spec.inspect}"
cast_type.deserialize(col_spec.default) != cast_type.deserialize(default)
end
else
col_value = col_spec.send(k)
if col_value.nil? && native_type
col_value = native_type[k]
end
col_value != send(k)
end
end
end
end
|
#limit ⇒ Object
85
86
87
|
# File 'lib/declare_schema/model/field_spec.rb', line 85
def limit
@options[:limit] || native_types[sql_type][:limit]
end
|
#null ⇒ Object
97
98
99
|
# File 'lib/declare_schema/model/field_spec.rb', line 97
def null
!:null.in?(@options) || @options[:null]
end
|
#precision ⇒ Object
89
90
91
|
# File 'lib/declare_schema/model/field_spec.rb', line 89
def precision
@options[:precision]
end
|
#same_type?(col_spec) ⇒ Boolean
105
106
107
108
109
110
|
# File 'lib/declare_schema/model/field_spec.rb', line 105
def same_type?(col_spec)
type = sql_type
normalized_type = TYPE_SYNONYMS[type] || type
normalized_col_spec_type = TYPE_SYNONYMS[col_spec.type] || col_spec.type
normalized_type == normalized_col_spec_type
end
|
#scale ⇒ Object
93
94
95
|
# File 'lib/declare_schema/model/field_spec.rb', line 93
def scale
@options[:scale]
end
|
#sql_options ⇒ Object
81
82
83
|
# File 'lib/declare_schema/model/field_spec.rb', line 81
def sql_options
@options.except(:ruby_default, :validates)
end
|
#sql_type ⇒ Object
70
71
72
73
74
75
76
77
78
79
|
# File 'lib/declare_schema/model/field_spec.rb', line 70
def sql_type
@options[:sql_type] || begin
if native_type?(type)
type
else
field_class = DeclareSchema.to_class(type)
field_class && field_class::COLUMN_TYPE or raise UnknownSqlTypeError, "#{type.inspect} for #{model}##{@name}"
end
end
end
|