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, position: 0, **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
60
61
62
63
64
65
66
|
# File 'lib/declare_schema/model/field_spec.rb', line 36
def initialize(model, name, type, position: 0, **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 = 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`?"
when :bigint
@type = :integer
@options = options.merge(limit: 8)
end
unless type.in?([:text, :string])
@options[:collation] and raise "collation may only given for :string and :text fields"
@options[:charset] and raise "charset may only given for :string and :text fields"
end
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
#charset ⇒ Object
118
119
120
121
122
|
# File 'lib/declare_schema/model/field_spec.rb', line 118
def charset
if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
(@options[:charset] || model.table_options[:charset] || Generators::DeclareSchema::Migration::Migrator.default_charset).to_s
end
end
|
#collation ⇒ Object
112
113
114
115
116
|
# File 'lib/declare_schema/model/field_spec.rb', line 112
def collation
if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
(@options[:collation] || model.table_options[:collation] || Generators::DeclareSchema::Migration::Migrator.default_collation).to_s
end
end
|
#default ⇒ Object
108
109
110
|
# File 'lib/declare_schema/model/field_spec.rb', line 108
def default
@options[:default]
end
|
#different_to?(table_name, col_spec) ⇒ Boolean
131
132
133
|
# File 'lib/declare_schema/model/field_spec.rb', line 131
def different_to?(table_name, col_spec)
!same_as(table_name, col_spec)
end
|
#limit ⇒ Object
92
93
94
|
# File 'lib/declare_schema/model/field_spec.rb', line 92
def limit
@options[:limit] || native_types[sql_type][:limit]
end
|
#null ⇒ Object
104
105
106
|
# File 'lib/declare_schema/model/field_spec.rb', line 104
def null
!:null.in?(@options) || @options[:null]
end
|
#precision ⇒ Object
96
97
98
|
# File 'lib/declare_schema/model/field_spec.rb', line 96
def precision
@options[:precision]
end
|
#same_as(table_name, col_spec) ⇒ Object
135
136
137
138
139
|
# File 'lib/declare_schema/model/field_spec.rb', line 135
def same_as(table_name, col_spec)
same_type?(col_spec) &&
same_attributes?(col_spec) &&
(!type.in?([:text, :string]) || same_charset_and_collation?(table_name, col_spec))
end
|
#same_type?(col_spec) ⇒ Boolean
124
125
126
127
128
129
|
# File 'lib/declare_schema/model/field_spec.rb', line 124
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
100
101
102
|
# File 'lib/declare_schema/model/field_spec.rb', line 100
def scale
@options[:scale]
end
|
#sql_options ⇒ Object
88
89
90
|
# File 'lib/declare_schema/model/field_spec.rb', line 88
def sql_options
@options.except(:ruby_default, :validates)
end
|
#sql_type ⇒ Object
77
78
79
80
81
82
83
84
85
86
|
# File 'lib/declare_schema/model/field_spec.rb', line 77
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
|