declare_schema 2.3.3.pre.1 → 3.1.0.colin.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -2
- data/Gemfile.lock +1 -1
- data/lib/declare_schema/extensions/active_record/fields_declaration.rb +0 -1
- data/lib/declare_schema/model/field_spec.rb +4 -4
- data/lib/declare_schema/model/habtm_model_shim.rb +18 -11
- data/lib/declare_schema/model.rb +38 -36
- data/lib/declare_schema/version.rb +1 -1
- data/lib/declare_schema.rb +2 -3
- data/lib/generators/declare_schema/migration/migrator.rb +18 -17
- metadata +3 -5
- data/lib/declare_schema/field_declaration_dsl.rb +0 -37
- data/spec/lib/declare_schema/field_declaration_dsl_spec.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c6d94bcff3ece2896188d31c3e5cf4d66474ab4ef5082537037b9c037bfe364
|
4
|
+
data.tar.gz: fea64238065955c2a3b6a16f5d5f3ee1da5b65d09da8a808b5f11c66b575b602
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 675ddf024002056463139774a6cdca78f7b157f8de5e07978b945552858d462e3ba59284a42fe169f4395adb793ce4027207e272d721085c638987c49819a6cd
|
7
|
+
data.tar.gz: 667e85cc287311fa014a0729da207ec763749196b07a0692a746aaa5348e3f48d23fb18860b7ee0ce7a8b50b151a9003f0fb7f460e9b39ce5d14a72838adc0cd
|
data/CHANGELOG.md
CHANGED
@@ -4,13 +4,17 @@ 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
|
-
## [
|
7
|
+
## [3.1.0] - Unreleased
|
8
|
+
### Added
|
9
|
+
- Add HABTM support for arbitrary primary key in the referenced table (rather than just :bigint).
|
10
|
+
|
11
|
+
## [3.0.0] - 2025-04-08
|
8
12
|
### Changed
|
9
13
|
- The `timestamps` DSL method to create `created_at` and `updated_at` columns now defaults to `null: false` for `datetime` columns
|
10
14
|
- The `timestamps` DSL method to allow additional options to be passed to the `datetime` fields
|
11
15
|
|
12
16
|
### Fixed
|
13
|
-
- Fixed a bug where `#validate` methods on core object classes with required arguments
|
17
|
+
- Fixed a bug where `#validate` methods on core object classes with required arguments was causing model validations to fail
|
14
18
|
|
15
19
|
## [2.3.2] - 2025-02-21
|
16
20
|
### Fixed
|
data/Gemfile.lock
CHANGED
@@ -47,10 +47,6 @@ module DeclareSchema
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def initialize(model, name, type, position: 0, **options)
|
50
|
-
_declared_primary_key = model._declared_primary_key
|
51
|
-
|
52
|
-
name.to_s == _declared_primary_key and raise ArgumentError, "you may not provide a field spec for the primary key #{name.inspect}"
|
53
|
-
|
54
50
|
@model = model
|
55
51
|
@name = name.to_sym
|
56
52
|
type.is_a?(Symbol) or raise ArgumentError, "type must be a Symbol; got #{type.inspect}"
|
@@ -124,6 +120,10 @@ module DeclareSchema
|
|
124
120
|
@sql_options = @options.slice(*SQL_OPTIONS)
|
125
121
|
end
|
126
122
|
|
123
|
+
def foreign_key_field_spec(model, name, position: 0, null: nil)
|
124
|
+
self.class.new(model, name, @type, position:, **@options.merge(null.nil? ? {} : { null: }))
|
125
|
+
end
|
126
|
+
|
127
127
|
# returns the attributes for schema migrations as a Hash
|
128
128
|
# omits name and position since those are meta-data above the schema
|
129
129
|
# omits keys with nil values
|
@@ -6,22 +6,28 @@ module DeclareSchema
|
|
6
6
|
class << self
|
7
7
|
def from_reflection(reflection)
|
8
8
|
new(reflection.join_table,
|
9
|
-
[
|
10
|
-
|
9
|
+
[
|
10
|
+
[reflection.foreign_key, reflection.active_record],
|
11
|
+
[reflection.association_foreign_key, reflection.klass]
|
12
|
+
],
|
11
13
|
connection: reflection.active_record.connection)
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
|
-
attr_reader :join_table, :foreign_keys, :parent_table_names, :connection
|
17
|
+
attr_reader :join_table, :foreign_keys, :parent_models, :parent_table_names, :connection
|
16
18
|
|
17
|
-
def initialize(join_table,
|
18
|
-
foreign_keys.is_a?(Array) && foreign_keys.size == 2 or
|
19
|
-
raise ArgumentError, "foreign_keys must be <Array[2]>; got #{foreign_keys.inspect}"
|
20
|
-
parent_table_names.is_a?(Array) && parent_table_names.size == 2 or
|
21
|
-
raise ArgumentError, "parent_table_names must be <Array[2]>; got #{parent_table_names.inspect}"
|
19
|
+
def initialize(join_table, parents, connection:)
|
22
20
|
@join_table = join_table
|
23
|
-
|
24
|
-
|
21
|
+
|
22
|
+
parents.is_a?(Array) && parents.size == 2 or
|
23
|
+
raise ArgumentError, "parents must be <Array[2]>; got #{parents.inspect}"
|
24
|
+
|
25
|
+
# Rails requires HABTM foreign keys to be in alphabetical order, so we start by sorting by those
|
26
|
+
parents.sort_by!(&:first)
|
27
|
+
@foreign_keys = parents.map(&:first)
|
28
|
+
@parent_models = parents.map(&:last)
|
29
|
+
@parent_table_names = parent_models.map(&:table_name)
|
30
|
+
|
25
31
|
@connection = connection
|
26
32
|
end
|
27
33
|
|
@@ -35,11 +41,12 @@ module DeclareSchema
|
|
35
41
|
|
36
42
|
def field_specs
|
37
43
|
foreign_keys.each_with_index.each_with_object({}) do |(foreign_key, i), result|
|
38
|
-
result[foreign_key] =
|
44
|
+
result[foreign_key] = parent_models[i]._foreign_key_field_spec(self, foreign_key, position: i, null: false)
|
39
45
|
end
|
40
46
|
end
|
41
47
|
|
42
48
|
def primary_key
|
49
|
+
# TODO: ActiveRecord now supports composite primary keys, so we could return that here.
|
43
50
|
false # no single-column primary key in database
|
44
51
|
end
|
45
52
|
|
data/lib/declare_schema/model.rb
CHANGED
@@ -100,6 +100,7 @@ module DeclareSchema
|
|
100
100
|
_add_validations_for_field(name, type, args, options)
|
101
101
|
_add_index_for_field(name, args, **options)
|
102
102
|
_add_scopes_for_field(name, type, **options)
|
103
|
+
name.to_s == _declared_primary_key and raise ArgumentError, "no need to declare a field spec for the primary key #{name.inspect}"
|
103
104
|
field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, position: field_specs.size, **options)
|
104
105
|
attr_order << name unless attr_order.include?(name)
|
105
106
|
end
|
@@ -201,62 +202,44 @@ module DeclareSchema
|
|
201
202
|
super
|
202
203
|
|
203
204
|
reflection = reflections[name.to_s] or raise "Couldn't find reflection #{name} in #{reflections.keys}"
|
204
|
-
|
205
|
-
foreign_key_column_options = column_options.dup
|
206
|
-
|
207
|
-
# Note: the foreign key limit: should match the primary key limit:. (If there is a foreign key constraint,
|
208
|
-
# those limits _must_ match.) We'd like to call _infer_fk_limit and get the limit right from the PK.
|
209
|
-
# But we can't here, because that will mess up the autoloader to follow every belongs_to association right
|
210
|
-
# when it is declared. So instead we assume :bigint (integer limit: 8) below, while also registering this
|
211
|
-
# pre_migration: callback to double-check that assumption Just In Time--right before we generate a migration.
|
212
|
-
#
|
213
|
-
# The one downside of this approach is that application code that asks the field_spec for the declared
|
214
|
-
# foreign key limit: will always get 8 back even if this is a grandfathered foreign key that points to
|
215
|
-
# a limit: 4 primary key. It seems unlikely that any application code would do this.
|
216
|
-
foreign_key_column_options[:pre_migration] = ->(field_spec) do
|
217
|
-
if (inferred_limit = _infer_fk_limit(foreign_key_column, reflection))
|
218
|
-
field_spec.sql_options[:limit] = inferred_limit
|
219
|
-
end
|
220
|
-
end
|
205
|
+
foreign_key_column_name = reflection.foreign_key or raise "Couldn't find foreign_key for #{name} in #{reflection.inspect}"
|
221
206
|
|
222
|
-
|
207
|
+
field_specs[foreign_key_column_name] = _infer_foreign_key_field_spec(foreign_key_column_name, reflection, column_options)
|
223
208
|
|
224
209
|
if reflection.options[:polymorphic]
|
225
210
|
foreign_type = options[:foreign_type] || "#{name}_type"
|
226
211
|
_declare_polymorphic_type_field(foreign_type, column_options)
|
227
212
|
if ::DeclareSchema.default_generate_indexing && index_options
|
228
|
-
index([foreign_type,
|
213
|
+
index([foreign_type, foreign_key_column_name], **index_options)
|
229
214
|
end
|
230
215
|
else
|
231
216
|
if ::DeclareSchema.default_generate_indexing && index_options
|
232
|
-
index([
|
217
|
+
index([foreign_key_column_name], **index_options)
|
233
218
|
end
|
234
219
|
|
235
220
|
if ::DeclareSchema.default_generate_foreign_keys && constraint_name != false
|
236
|
-
constraint(
|
221
|
+
constraint(foreign_key_column_name,
|
222
|
+
constraint_name: constraint_name || index_options&.[](:name),
|
223
|
+
parent_class_name: reflection.class_name,
|
224
|
+
dependent: dependent_delete)
|
237
225
|
end
|
238
226
|
end
|
239
227
|
end
|
240
228
|
|
241
|
-
|
229
|
+
# Returns a FieldSpec for the foreign key column of a belongs_to association.
|
230
|
+
# If the association is polymorphic, the foreign key column is a bigint, or possibly a 4-byte integer
|
231
|
+
# if the foreign key column is already defined that way in the database.
|
232
|
+
# If the association is not polymorphic, the foreign key column matches the primary key type of the associated model.
|
233
|
+
def _infer_foreign_key_field_spec(foreign_key_column_name, reflection, column_options)
|
242
234
|
if reflection.options[:polymorphic]
|
243
|
-
if (foreign_key_column = _column(
|
244
|
-
|
235
|
+
if (foreign_key_column = _column(foreign_key_column_name)) && foreign_key_column.type == :integer
|
236
|
+
# grandfather foreign key column to match what's in the database
|
237
|
+
column_options = column_options.merge(limit: foreign_key_column.limit)
|
245
238
|
end
|
239
|
+
FieldSpec.new(self, foreign_key_column_name, :bigint, position: field_specs.size, **column_options)
|
246
240
|
else
|
247
241
|
klass = reflection.klass or raise "Couldn't find belongs_to klass for #{name} in #{reflection.inspect}"
|
248
|
-
|
249
|
-
if pk_id_type == :integer
|
250
|
-
4
|
251
|
-
end
|
252
|
-
else
|
253
|
-
if klass.table_exists? && (pk_column = klass.columns_hash[klass._declared_primary_key])
|
254
|
-
pk_id_type = pk_column.type
|
255
|
-
if pk_id_type == :integer
|
256
|
-
pk_column.limit
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end
|
242
|
+
klass._foreign_key_field_spec(self, foreign_key_column_name, position: field_specs.size, **column_options)
|
260
243
|
end
|
261
244
|
end
|
262
245
|
|
@@ -273,6 +256,25 @@ module DeclareSchema
|
|
273
256
|
end
|
274
257
|
end
|
275
258
|
|
259
|
+
# Returns a FieldSpec for a foreign key pointing to the primary key of this model.
|
260
|
+
# Exactly matches the primary key type.
|
261
|
+
def _foreign_key_field_spec(model, foreign_key, position:, null:)
|
262
|
+
_primary_key_field_spec.foreign_key_field_spec(model, foreign_key, position:, null:)
|
263
|
+
end
|
264
|
+
|
265
|
+
def _primary_key_field_spec
|
266
|
+
declared_primary_key = _declared_primary_key
|
267
|
+
field_specs[declared_primary_key] || _primary_key_field_spec_from_table_options(declared_primary_key) or
|
268
|
+
raise "Declared primary key #{declared_primary_key.inspect} not found in field_specs or _table_options #{_table_options.inspect} for #{name}"
|
269
|
+
end
|
270
|
+
|
271
|
+
def _primary_key_field_spec_from_table_options(declared_primary_key)
|
272
|
+
primary_key_options = _table_options[declared_primary_key.to_sym] || _table_options[declared_primary_key]
|
273
|
+
options = primary_key_options.is_a?(Hash) ? primary_key_options.dup : {}
|
274
|
+
type = options.delete(:type) || Rails.application.config.generators.options.dig(:active_record, :primary_key_type) || :bigint
|
275
|
+
FieldSpec.new(self, declared_primary_key, type, **options)
|
276
|
+
end
|
277
|
+
|
276
278
|
private
|
277
279
|
|
278
280
|
# if this is a derived class, returns the base class's _declared_primary_key
|
data/lib/declare_schema.rb
CHANGED
@@ -65,7 +65,7 @@ module DeclareSchema
|
|
65
65
|
if mysql_version && mysql_version >= SEMVER_8 && charset == 'utf8'
|
66
66
|
'utf8mb3'
|
67
67
|
else
|
68
|
-
charset
|
68
|
+
charset.downcase
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -74,7 +74,7 @@ module DeclareSchema
|
|
74
74
|
collation.sub(/\Autf8_/, 'utf8mb3_')
|
75
75
|
else
|
76
76
|
collation
|
77
|
-
end
|
77
|
+
end.downcase
|
78
78
|
end
|
79
79
|
|
80
80
|
def default_charset=(charset)
|
@@ -172,7 +172,6 @@ module DeclareSchema
|
|
172
172
|
end
|
173
173
|
|
174
174
|
require 'declare_schema/extensions/active_record/fields_declaration'
|
175
|
-
require 'declare_schema/field_declaration_dsl'
|
176
175
|
require 'declare_schema/model'
|
177
176
|
require 'declare_schema/model/field_spec'
|
178
177
|
require 'declare_schema/model/index_definition'
|
@@ -80,15 +80,13 @@ module Generators
|
|
80
80
|
self.class.native_types
|
81
81
|
end
|
82
82
|
|
83
|
-
#
|
83
|
+
# return habtm reflections keyed by join table name (so that habtm from each side has just one entry)
|
84
84
|
def habtm_tables
|
85
|
-
|
86
|
-
ActiveRecord::Base.send(:descendants).map do |c|
|
85
|
+
ActiveRecord::Base.send(:descendants).each_with_object({}) do |c, result|
|
87
86
|
c.reflect_on_all_associations(:has_and_belongs_to_many).each do |a|
|
88
|
-
|
87
|
+
result[a.join_table] ||= a
|
89
88
|
end
|
90
89
|
end
|
91
|
-
reflections
|
92
90
|
end
|
93
91
|
|
94
92
|
# Returns an array of model classes and an array of table names
|
@@ -204,8 +202,8 @@ module Generators
|
|
204
202
|
end
|
205
203
|
end
|
206
204
|
# generate shims for HABTM models
|
207
|
-
habtm_tables.each do |name,
|
208
|
-
models_by_table_name[name] = ::DeclareSchema::Model::HabtmModelShim.from_reflection(
|
205
|
+
habtm_tables.each do |name, reflection|
|
206
|
+
models_by_table_name[name] = ::DeclareSchema::Model::HabtmModelShim.from_reflection(reflection)
|
209
207
|
end
|
210
208
|
model_table_names = models_by_table_name.keys
|
211
209
|
|
@@ -376,21 +374,21 @@ module Generators
|
|
376
374
|
::DeclareSchema::SchemaChange::ColumnRename.new(new_table_name, old_name, new_name)
|
377
375
|
end
|
378
376
|
|
379
|
-
to_add.sort_by! {
|
377
|
+
to_add.sort_by! { model.field_specs[_1]&.position || 0 }
|
380
378
|
|
381
|
-
adds = to_add.map do |
|
379
|
+
adds = to_add.map do |col_name_to_add|
|
382
380
|
type, options =
|
383
|
-
if (spec = model.field_specs[
|
384
|
-
[spec.type, spec.sql_options.merge(fk_field_options(model,
|
381
|
+
if (spec = model.field_specs[col_name_to_add])
|
382
|
+
[spec.type, spec.sql_options.merge(fk_field_options(model, col_name_to_add)).compact]
|
385
383
|
else
|
386
384
|
[:integer, {}]
|
387
385
|
end
|
388
|
-
::DeclareSchema::SchemaChange::ColumnAdd.new(new_table_name,
|
386
|
+
::DeclareSchema::SchemaChange::ColumnAdd.new(new_table_name, col_name_to_add, type, **options)
|
389
387
|
end
|
390
388
|
|
391
|
-
removes = to_remove.map do |
|
392
|
-
old_type, old_options = add_column_back(model, current_table_name,
|
393
|
-
::DeclareSchema::SchemaChange::ColumnRemove.new(new_table_name,
|
389
|
+
removes = to_remove.map do |col_name_to_remove|
|
390
|
+
old_type, old_options = add_column_back(model, current_table_name, col_name_to_remove)
|
391
|
+
::DeclareSchema::SchemaChange::ColumnRemove.new(new_table_name, col_name_to_remove, old_type, **old_options)
|
394
392
|
end
|
395
393
|
|
396
394
|
old_names = to_rename.invert
|
@@ -546,11 +544,14 @@ module Generators
|
|
546
544
|
end
|
547
545
|
end
|
548
546
|
|
547
|
+
# TODO: switch this to depend on _infer_foreign_key_field_spec instead
|
549
548
|
def fk_field_options(model, field_name)
|
550
|
-
|
549
|
+
# check if the field_name is a foreign key
|
550
|
+
if (foreign_key = model.constraint_definitions.find { field_name == _1.foreign_key_column })
|
551
|
+
# if so, look up the target table's primary key column to get its limit (note: this is looking in the DB, not the spec)
|
551
552
|
parent_columns = connection.columns(foreign_key.parent_table_name) rescue []
|
552
553
|
pk_limit =
|
553
|
-
if (pk_column = parent_columns.find {
|
554
|
+
if (pk_column = parent_columns.find { _1.name.to_s == "id" }) # right now foreign keys assume id is the target
|
554
555
|
pk_column.limit
|
555
556
|
else
|
556
557
|
8
|
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:
|
4
|
+
version: 3.1.0.colin.1
|
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: 2025-
|
11
|
+
date: 2025-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -66,7 +66,6 @@ files:
|
|
66
66
|
- lib/declare_schema/dsl.rb
|
67
67
|
- lib/declare_schema/extensions/active_record/fields_declaration.rb
|
68
68
|
- lib/declare_schema/extensions/module.rb
|
69
|
-
- lib/declare_schema/field_declaration_dsl.rb
|
70
69
|
- lib/declare_schema/model.rb
|
71
70
|
- lib/declare_schema/model/column.rb
|
72
71
|
- lib/declare_schema/model/field_spec.rb
|
@@ -108,7 +107,6 @@ files:
|
|
108
107
|
- spec/fixtures/migrations/sqlite3/will_generate_unique_constraint_names_rails_6.txt
|
109
108
|
- spec/fixtures/migrations/sqlite3/will_generate_unique_constraint_names_rails_7.txt
|
110
109
|
- spec/lib/declare_schema/api_spec.rb
|
111
|
-
- spec/lib/declare_schema/field_declaration_dsl_spec.rb
|
112
110
|
- spec/lib/declare_schema/field_spec_spec.rb
|
113
111
|
- spec/lib/declare_schema/generator_spec.rb
|
114
112
|
- spec/lib/declare_schema/interactive_primary_key_spec.rb
|
@@ -158,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
156
|
- !ruby/object:Gem::Version
|
159
157
|
version: 1.3.6
|
160
158
|
requirements: []
|
161
|
-
rubygems_version: 3.4.
|
159
|
+
rubygems_version: 3.4.10
|
162
160
|
signing_key:
|
163
161
|
specification_version: 4
|
164
162
|
summary: Database schema declaration and migration generator for Rails
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DeclareSchema
|
4
|
-
class FieldDeclarationDsl < BasicObject # avoid Object because that gets extended by lots of gems
|
5
|
-
include ::Kernel # but we need the basic class methods
|
6
|
-
|
7
|
-
instance_methods.each do |m|
|
8
|
-
unless m.to_s.starts_with?('__') || m.in?([:object_id, :instance_eval])
|
9
|
-
undef_method(m)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize(model, **options)
|
14
|
-
@model = model
|
15
|
-
@options = options
|
16
|
-
end
|
17
|
-
|
18
|
-
attr_reader :model
|
19
|
-
|
20
|
-
def timestamps
|
21
|
-
field(:created_at, :datetime, null: true)
|
22
|
-
field(:updated_at, :datetime, null: true)
|
23
|
-
end
|
24
|
-
|
25
|
-
def optimistic_lock
|
26
|
-
field(:lock_version, :integer, default: 1, null: false)
|
27
|
-
end
|
28
|
-
|
29
|
-
def field(name, type, *args, **options)
|
30
|
-
@model.declare_field(name, type, *args, **@options.merge(options))
|
31
|
-
end
|
32
|
-
|
33
|
-
def method_missing(name, *args, **options)
|
34
|
-
field(name, *args, **options)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../../../lib/declare_schema/field_declaration_dsl'
|
4
|
-
|
5
|
-
RSpec.describe DeclareSchema::FieldDeclarationDsl do
|
6
|
-
include_context 'prepare test app'
|
7
|
-
|
8
|
-
let(:model) { TestModel.new }
|
9
|
-
subject { declared_class.new(model) }
|
10
|
-
|
11
|
-
context 'Using declare_schema' do
|
12
|
-
before do
|
13
|
-
class TestModel < ActiveRecord::Base # rubocop:disable Lint/ConstantDefinitionInBlock
|
14
|
-
declare_schema do
|
15
|
-
string :name, limit: 127
|
16
|
-
|
17
|
-
timestamps
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'has fields' do
|
23
|
-
expect(TestModel.field_specs).to be_kind_of(Hash)
|
24
|
-
expect(TestModel.field_specs.keys).to eq(['name', 'created_at', 'updated_at'])
|
25
|
-
expect(TestModel.field_specs.values.map(&:type)).to eq([:string, :datetime, :datetime])
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'stores limits' do
|
29
|
-
expect(TestModel.field_specs['name'].limit).to eq(127), TestModel.field_specs['name'].inspect
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# TODO: fill out remaining tests
|
34
|
-
end
|