declare_schema 0.8.0.pre.6 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -1
- data/Gemfile.lock +1 -1
- data/lib/declare_schema/model.rb +50 -58
- data/lib/declare_schema/model/field_spec.rb +2 -2
- data/lib/declare_schema/model/habtm_model_shim.rb +1 -1
- data/lib/declare_schema/version.rb +1 -1
- data/lib/generators/declare_schema/migration/migrator.rb +9 -8
- data/spec/lib/declare_schema/field_spec_spec.rb +8 -6
- data/spec/lib/declare_schema/interactive_primary_key_spec.rb +3 -3
- data/spec/lib/declare_schema/model/habtm_model_shim_spec.rb +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae6f3f47d3ad4fa0b1d2e30d8f34b7ac5825b690838492ac57846dcd53396e9a
|
4
|
+
data.tar.gz: 129d77729c08d2fb41e506571ead2a82dd76c0c1675c18556bc3811e0adf3362
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b145fdd60646c467772034afa2a29e30d29a4d35445c7e769bab731c043cb38c8e0b365ac7f6dc416e93fafdc1edd6e77724085054a6a442934cc191e335fdf
|
7
|
+
data.tar.gz: 1356d29f00f1eb4a72b567c48c57c6683bcc56852dfb68a3252b521a74c6c0afcfdf5765d94a31d3322ee297465c3ca60ec611090cf3ad5dd935e2bc343285ed
|
data/CHANGELOG.md
CHANGED
@@ -4,8 +4,9 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
4
4
|
|
5
5
|
Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
-
## [0.8.0] -
|
7
|
+
## [0.8.0] - 2021-02-22
|
8
8
|
### Removed
|
9
|
+
- Removed assumption that primary key is named 'id'.
|
9
10
|
- Removed `sql_type` that was confusing because it was actually the same as `type` (ex: :string) and not
|
10
11
|
in fact the SQL type (ex: ``varchar(255)'`).
|
11
12
|
|
data/Gemfile.lock
CHANGED
data/lib/declare_schema/model.rb
CHANGED
@@ -38,7 +38,7 @@ module DeclareSchema
|
|
38
38
|
|
39
39
|
# eval avoids the ruby 1.9.2 "super from singleton method ..." error
|
40
40
|
|
41
|
-
eval
|
41
|
+
eval <<~EOS
|
42
42
|
def self.inherited(klass)
|
43
43
|
unless klass.field_specs.has_key?(inheritance_column)
|
44
44
|
fields do |f|
|
@@ -48,14 +48,14 @@ module DeclareSchema
|
|
48
48
|
end
|
49
49
|
super
|
50
50
|
end
|
51
|
-
|
51
|
+
EOS
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
56
|
module ClassMethods
|
57
57
|
def index(fields, options = {})
|
58
|
-
#
|
58
|
+
# make index idempotent
|
59
59
|
index_fields_s = Array.wrap(fields).map(&:to_s)
|
60
60
|
unless index_definitions.any? { |index_spec| index_spec.fields == index_fields_s }
|
61
61
|
index_definitions << ::DeclareSchema::Model::IndexDefinition.new(self, fields, options)
|
@@ -74,7 +74,7 @@ module DeclareSchema
|
|
74
74
|
end
|
75
75
|
|
76
76
|
# tell the migration generator to ignore the named index. Useful for existing indexes, or for indexes
|
77
|
-
# that can't be automatically generated (for example:
|
77
|
+
# that can't be automatically generated (for example: a prefix index in MySQL)
|
78
78
|
def ignore_index(index_name)
|
79
79
|
ignore_indexes << index_name.to_s
|
80
80
|
end
|
@@ -85,10 +85,10 @@ module DeclareSchema
|
|
85
85
|
# declarations.
|
86
86
|
def declare_field(name, type, *args, **options)
|
87
87
|
try(:field_added, name, type, args, options)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
88
|
+
_add_serialize_for_field(name, type, options)
|
89
|
+
_add_formatting_for_field(name, type)
|
90
|
+
_add_validations_for_field(name, type, args, options)
|
91
|
+
_add_index_for_field(name, args, options)
|
92
92
|
field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, position: field_specs.size, **options)
|
93
93
|
attr_order << name unless attr_order.include?(name)
|
94
94
|
end
|
@@ -97,41 +97,10 @@ module DeclareSchema
|
|
97
97
|
if index_definitions.any?(&:primary_key?)
|
98
98
|
index_definitions
|
99
99
|
else
|
100
|
-
index_definitions + [
|
100
|
+
index_definitions + [_rails_default_primary_key]
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
if ::Rails::VERSION::MAJOR < 5
|
105
|
-
def primary_key
|
106
|
-
super || 'id'
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# returns the primary key (String) as declared with primary_key =
|
111
|
-
# unlike the `primary_key` method, DOES NOT query the database to find the actual primary key in use right now
|
112
|
-
# if no explicit primary key set, returns the default_defined_primary_key
|
113
|
-
def defined_primary_key
|
114
|
-
if defined?(@primary_key)
|
115
|
-
@primary_key&.to_s
|
116
|
-
end || default_defined_primary_key
|
117
|
-
end
|
118
|
-
|
119
|
-
# if this is a derived class, returns the base class's defined_primary_key
|
120
|
-
# otherwise, returns 'id'
|
121
|
-
def default_defined_primary_key
|
122
|
-
if self == base_class
|
123
|
-
'id'
|
124
|
-
else
|
125
|
-
base_class.defined_primary_key
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
private
|
130
|
-
|
131
|
-
def rails_default_primary_key
|
132
|
-
::DeclareSchema::Model::IndexDefinition.new(self, [primary_key.to_sym], unique: true, name: DeclareSchema::Model::IndexDefinition::PRIMARY_KEY_NAME)
|
133
|
-
end
|
134
|
-
|
135
104
|
# Extend belongs_to so that it creates a FieldSpec for the foreign key
|
136
105
|
def belongs_to(name, scope = nil, **options)
|
137
106
|
column_options = {}
|
@@ -172,7 +141,7 @@ module DeclareSchema
|
|
172
141
|
declare_field(fkey.to_sym, :integer, column_options)
|
173
142
|
if refl.options[:polymorphic]
|
174
143
|
foreign_type = options[:foreign_type] || "#{name}_type"
|
175
|
-
|
144
|
+
_declare_polymorphic_type_field(foreign_type, column_options)
|
176
145
|
index([foreign_type, fkey], index_options) if index_options[:name] != false
|
177
146
|
else
|
178
147
|
index(fkey, index_options) if index_options[:name] != false
|
@@ -180,26 +149,49 @@ module DeclareSchema
|
|
180
149
|
end
|
181
150
|
end
|
182
151
|
|
152
|
+
if ::Rails::VERSION::MAJOR < 5
|
153
|
+
def primary_key
|
154
|
+
super || 'id'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# returns the primary key (String) as declared with primary_key =
|
159
|
+
# unlike the `primary_key` method, DOES NOT query the database to find the actual primary key in use right now
|
160
|
+
# if no explicit primary key set, returns the default_defined_primary_key
|
161
|
+
def _defined_primary_key
|
162
|
+
if defined?(@primary_key)
|
163
|
+
@primary_key&.to_s
|
164
|
+
end || _default_defined_primary_key
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
# if this is a derived class, returns the base class's _defined_primary_key
|
170
|
+
# otherwise, returns 'id'
|
171
|
+
def _default_defined_primary_key
|
172
|
+
if self == base_class
|
173
|
+
'id'
|
174
|
+
else
|
175
|
+
base_class._defined_primary_key
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def _rails_default_primary_key
|
180
|
+
::DeclareSchema::Model::IndexDefinition.new(self, [_defined_primary_key.to_sym], unique: true, name: DeclareSchema::Model::IndexDefinition::PRIMARY_KEY_NAME)
|
181
|
+
end
|
182
|
+
|
183
183
|
# Declares the "foo_type" field that accompanies the "foo_id"
|
184
184
|
# field for a polymorphic belongs_to
|
185
|
-
def
|
185
|
+
def _declare_polymorphic_type_field(foreign_type, column_options)
|
186
186
|
declare_field(foreign_type, :string, column_options.merge(limit: 255))
|
187
187
|
# FIXME: Before declare_schema was extracted, this used to now do:
|
188
188
|
# never_show(type_col)
|
189
189
|
# That needs doing somewhere
|
190
190
|
end
|
191
191
|
|
192
|
-
# Declare a rich-type for any attribute (i.e. getter method). This
|
193
|
-
# does not effect the attribute in any way - it just records the
|
194
|
-
# metadata.
|
195
|
-
def declare_attr_type(name, type, options = {})
|
196
|
-
attr_types[name] = klass = DeclareSchema.to_class(type)
|
197
|
-
klass.try(:declared, self, name, options)
|
198
|
-
end
|
199
|
-
|
200
192
|
# Add field validations according to arguments in the
|
201
193
|
# field declaration
|
202
|
-
def
|
194
|
+
def _add_validations_for_field(name, type, args, options)
|
203
195
|
validates_presence_of name if :required.in?(args)
|
204
196
|
validates_uniqueness_of name, allow_nil: !:required.in?(args) if :unique.in?(args)
|
205
197
|
|
@@ -218,18 +210,18 @@ module DeclareSchema
|
|
218
210
|
end
|
219
211
|
end
|
220
212
|
|
221
|
-
def
|
213
|
+
def _add_serialize_for_field(name, type, options)
|
222
214
|
if (serialize_class = options.delete(:serialize))
|
223
215
|
type == :string || type == :text or raise ArgumentError, "serialize field type must be :string or :text"
|
224
216
|
serialize_args = Array((serialize_class unless serialize_class == true))
|
225
217
|
serialize(name, *serialize_args)
|
226
218
|
if options.has_key?(:default)
|
227
|
-
options[:default] =
|
219
|
+
options[:default] = _serialized_default(name, serialize_class == true ? Object : serialize_class, options[:default])
|
228
220
|
end
|
229
221
|
end
|
230
222
|
end
|
231
223
|
|
232
|
-
def
|
224
|
+
def _serialized_default(attr_name, class_name_or_coder, default)
|
233
225
|
# copied from https://github.com/rails/rails/blob/7d6cb950e7c0e31c2faaed08c81743439156c9f5/activerecord/lib/active_record/attribute_methods/serialization.rb#L70-L76
|
234
226
|
coder = if class_name_or_coder == ::JSON
|
235
227
|
ActiveRecord::Coders::JSON
|
@@ -248,7 +240,7 @@ module DeclareSchema
|
|
248
240
|
end
|
249
241
|
end
|
250
242
|
|
251
|
-
def
|
243
|
+
def _add_formatting_for_field(name, type)
|
252
244
|
if (type_class = DeclareSchema.to_class(type))
|
253
245
|
if "format".in?(type_class.instance_methods)
|
254
246
|
before_validation do |record|
|
@@ -258,7 +250,7 @@ module DeclareSchema
|
|
258
250
|
end
|
259
251
|
end
|
260
252
|
|
261
|
-
def
|
253
|
+
def _add_index_for_field(name, args, options)
|
262
254
|
if (to_name = options.delete(:index))
|
263
255
|
index_opts =
|
264
256
|
{
|
@@ -287,13 +279,13 @@ module DeclareSchema
|
|
287
279
|
refl
|
288
280
|
end
|
289
281
|
end ||
|
290
|
-
if (col =
|
282
|
+
if (col = _column(name.to_s))
|
291
283
|
DeclareSchema::PLAIN_TYPES[col.type] || col.klass
|
292
284
|
end
|
293
285
|
end
|
294
286
|
|
295
287
|
# Return the entry from #columns for the named column
|
296
|
-
def
|
288
|
+
def _column(name)
|
297
289
|
defined?(@table_exists) or @table_exists = table_exists?
|
298
290
|
if @table_exists
|
299
291
|
columns_hash[name.to_s]
|
@@ -47,9 +47,9 @@ module DeclareSchema
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def initialize(model, name, type, position: 0, **options)
|
50
|
-
|
50
|
+
_defined_primary_key = model._defined_primary_key
|
51
51
|
|
52
|
-
name.to_s ==
|
52
|
+
name.to_s == _defined_primary_key and raise ArgumentError, "you may not provide a field spec for the primary key #{name.inspect}"
|
53
53
|
|
54
54
|
@model = model
|
55
55
|
@name = name.to_sym
|
@@ -285,12 +285,13 @@ module Generators
|
|
285
285
|
end
|
286
286
|
|
287
287
|
def create_table_options(model, disable_auto_increment)
|
288
|
-
|
288
|
+
primary_key = model._defined_primary_key
|
289
|
+
if primary_key.blank? || disable_auto_increment
|
289
290
|
"id: false"
|
290
|
-
elsif
|
291
|
+
elsif primary_key == "id"
|
291
292
|
"id: :bigint"
|
292
293
|
else
|
293
|
-
"primary_key: :#{
|
294
|
+
"primary_key: :#{primary_key}"
|
294
295
|
end
|
295
296
|
end
|
296
297
|
|
@@ -323,18 +324,18 @@ module Generators
|
|
323
324
|
new_table_name = model.table_name
|
324
325
|
|
325
326
|
db_columns = model.connection.columns(current_table_name).index_by(&:name)
|
326
|
-
key_missing = db_columns[model.
|
327
|
-
if model.
|
328
|
-
db_columns.delete(model.
|
327
|
+
key_missing = db_columns[model._defined_primary_key].nil? && model._defined_primary_key.present?
|
328
|
+
if model._defined_primary_key.present?
|
329
|
+
db_columns.delete(model._defined_primary_key)
|
329
330
|
end
|
330
331
|
|
331
332
|
model_column_names = model.field_specs.keys.map(&:to_s)
|
332
333
|
db_column_names = db_columns.keys.map(&:to_s)
|
333
334
|
|
334
335
|
to_add = model_column_names - db_column_names
|
335
|
-
to_add += [model.
|
336
|
+
to_add += [model._defined_primary_key] if key_missing && model._defined_primary_key.present?
|
336
337
|
to_remove = db_column_names - model_column_names
|
337
|
-
to_remove -= [model.
|
338
|
+
to_remove -= [model._defined_primary_key.to_sym] if model._defined_primary_key.present?
|
338
339
|
|
339
340
|
to_rename = extract_column_renames!(to_add, to_remove, new_table_name)
|
340
341
|
|
@@ -6,7 +6,7 @@ rescue LoadError
|
|
6
6
|
end
|
7
7
|
|
8
8
|
RSpec.describe DeclareSchema::Model::FieldSpec do
|
9
|
-
let(:model) { double('model', table_options: {},
|
9
|
+
let(:model) { double('model', table_options: {}, _defined_primary_key: 'id') }
|
10
10
|
let(:col_spec) { double('col_spec', type: :string) }
|
11
11
|
|
12
12
|
before do
|
@@ -85,10 +85,12 @@ RSpec.describe DeclareSchema::Model::FieldSpec do
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
88
|
+
if defined?(Mysql2)
|
89
|
+
describe 'varbinary' do # TODO: :varbinary is an Invoca addition to Rails; make it a configurable option
|
90
|
+
it 'is supported' do
|
91
|
+
subject = described_class.new(model, :binary_dump, :varbinary, limit: 200, null: false, position: 2)
|
92
|
+
expect(subject.schema_attributes(col_spec)).to eq(type: :varbinary, limit: 200, null: false)
|
93
|
+
end
|
92
94
|
end
|
93
95
|
end
|
94
96
|
|
@@ -109,7 +111,7 @@ RSpec.describe DeclareSchema::Model::FieldSpec do
|
|
109
111
|
end
|
110
112
|
end
|
111
113
|
|
112
|
-
[:integer, :bigint, :string, :text, :binary, :
|
114
|
+
[:integer, :bigint, :string, :text, :binary, :datetime, :date, :time, (:varbinary if defined?(Mysql2))].compact.each do |t|
|
113
115
|
describe t.to_s do
|
114
116
|
let(:extra) { t == :string ? { limit: 100 } : {} }
|
115
117
|
|
@@ -19,7 +19,7 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
generate_migrations '-n', '-m'
|
22
|
-
expect(Foo.
|
22
|
+
expect(Foo._defined_primary_key).to eq('foo_id')
|
23
23
|
|
24
24
|
### migrate from
|
25
25
|
# rename from custom primary_key
|
@@ -31,7 +31,7 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
|
|
31
31
|
|
32
32
|
puts "\n\e[45m Please enter 'id' (no quotes) at the next prompt \e[0m"
|
33
33
|
generate_migrations '-n', '-m'
|
34
|
-
expect(Foo.
|
34
|
+
expect(Foo._defined_primary_key).to eq('id')
|
35
35
|
|
36
36
|
nuke_model_class(Foo)
|
37
37
|
|
@@ -47,7 +47,7 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
|
|
47
47
|
|
48
48
|
puts "\n\e[45m Please enter 'drop id' (no quotes) at the next prompt \e[0m"
|
49
49
|
generate_migrations '-n', '-m'
|
50
|
-
expect(Foo.
|
50
|
+
expect(Foo._defined_primary_key).to eq('foo_id')
|
51
51
|
|
52
52
|
### ensure it doesn't cause further migrations
|
53
53
|
|
@@ -88,13 +88,13 @@ RSpec.describe DeclareSchema::Model::HabtmModelShim do
|
|
88
88
|
|
89
89
|
describe '#primary_key' do
|
90
90
|
it 'returns false' do
|
91
|
-
expect(subject.
|
91
|
+
expect(subject._defined_primary_key).to eq(false)
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
-
describe '#
|
95
|
+
describe '#_defined_primary_key' do
|
96
96
|
it 'returns false' do
|
97
|
-
expect(subject.
|
97
|
+
expect(subject._defined_primary_key).to eq(false)
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: declare_schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.0
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Invoca Development adapted from hobo_fields by Tom Locke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-02-
|
11
|
+
date: 2021-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|