declare_schema 0.11.1 → 0.13.0.pre.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 389da0d9f9e0753e62297aeca33c3c73305d95082a3f50baf6288362011e6f52
4
- data.tar.gz: 7d20d8ef4a085e37ec13273c020b8c3883e96359e9e4c7d173c3beccf5c73dab
3
+ metadata.gz: fef97a705f29e37659ade688c2c64b30f0df1eabc76ab47ceb1272f2eec10845
4
+ data.tar.gz: 3602d932b5bae67c6cfd367750e399d44ab65afa4fd19c4923ff5e447b79ca40
5
5
  SHA512:
6
- metadata.gz: 0e4eb02bc1d989d648095b952e1feff00af9cbbc4ea3dbb7962f15fdbcafce2fac4bc93c467417d29396e6753993874c3c2faf882a620db0d54f3ea905195cf9
7
- data.tar.gz: d504a96bb5f60d7c64b03fd975c9e7c78fe9614f06a0aa73fffe0c0987786a554e3f603a79198f962b13b0b869690b839fb1cd0215196353064360ef81e46e51
6
+ metadata.gz: 770d10d283e399d3ca37537e7ed4c68d0dde1a6ba28e033148ed7ed86d0e0833256d0b2446688538ef34f39cac9c1fe535914824d4bf7e6de17d11554b876ec2
7
+ data.tar.gz: 134add2558ab3374d741e04839913257eb48e8b98d4b80a3bc3c35927369032fd9549d9a1dd2768c702386f44b4265c0379475cd01f8097288cad53b479a4ee9
data/CHANGELOG.md CHANGED
@@ -4,6 +4,21 @@ 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.13.0] - Unreleased
8
+ ### Added
9
+ - Added support for `default_schema =` to apply a default schema to every model, unless disabld for that model with `declare_schema: false`.
10
+
11
+ ## [0.12.1] - 2021-05-10
12
+ ### Fixed
13
+ - When an `enum` type field is declared, there is now enforcement that its `limit:` must be an array of 1 or more Symbols,
14
+ and its `default:`--if given--must be a Symbol or `nil`.
15
+
16
+ ## [0.12.0] - 2021-04-28
17
+ ### Added
18
+ - `belongs_to` now always infers the `limit:` of the foreign key to match that of the primary key it points to.
19
+ Note: this isn't possible for polymorphic foreign keys, so it assumes `limit: 8` there...unless the schema
20
+ was migrated in the past with `limit: 4`.
21
+
7
22
  ## [0.11.1] - 2021-03-26
8
23
  ### Fixed
9
24
  - Fixed a bug where up and down in generated migration would be empty in Rails 4.
@@ -168,6 +183,9 @@ using the appropriate Rails configuration attributes.
168
183
  ### Added
169
184
  - Initial version from https://github.com/Invoca/hobo_fields v4.1.0.
170
185
 
186
+ [0.13.0]: https://github.com/Invoca/declare_schema/compare/v0.12.1...v0.13.0
187
+ [0.12.1]: https://github.com/Invoca/declare_schema/compare/v0.12.0...v0.12.1
188
+ [0.12.0]: https://github.com/Invoca/declare_schema/compare/v0.11.1...v0.12.0
171
189
  [0.11.1]: https://github.com/Invoca/declare_schema/compare/v0.11.0...v0.11.1
172
190
  [0.11.0]: https://github.com/Invoca/declare_schema/compare/v0.10.1...v0.11.0
173
191
  [0.10.1]: https://github.com/Invoca/declare_schema/compare/v0.10.0...v0.10.1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- declare_schema (0.11.1)
4
+ declare_schema (0.13.0.pre.1)
5
5
  rails (>= 4.2)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -4,10 +4,10 @@ Declare your Rails/active_record model schemas and have database migrations gene
4
4
 
5
5
  ## Example
6
6
 
7
- Make a model and declare your schema within a `fields do ... end` block:
7
+ Make a model and declare your schema within a `declare_schema do ... end` block:
8
8
  ```ruby
9
9
  class Company < ActiveRecord::Base
10
- fields do
10
+ declare_schema do
11
11
  company_name :string, limit: 100
12
12
  ticker_symbol :string, limit: 4, null: true, index: true, unique: true
13
13
  employee_count :integer
@@ -62,7 +62,7 @@ trigger the `eager_load!` on the `Rails` application and all `Rails::Engine`s lo
62
62
  into scope. If you need to generate migrations for models that aren't automatically loaded by `eager_load!`,
63
63
  load them in the `before_generating_migration` block.
64
64
 
65
- **Example Configuration**
65
+ For example:
66
66
 
67
67
  ```ruby
68
68
  DeclareSchema::Migration::Migrator.before_generating_migration do
@@ -70,6 +70,26 @@ DeclareSchema::Migration::Migrator.before_generating_migration do
70
70
  end
71
71
  ```
72
72
 
73
+ ### default_schema
74
+ If there are default columns you would like in the schema for every model, you can define them in a block that is registered with
75
+ `DeclareSchema.default_schema =`. For example:
76
+
77
+ ```ruby
78
+ DeclareSchema.default_schema = -> do
79
+ timestamps
80
+ optimistic_lock
81
+ end
82
+ ```
83
+ This will add these fields to the schema of each model (if not already there).
84
+ If you have a model where you don't want the defaults applied, that can be set with the `default_schema:` boolean option to `declare_schema` (the default value is true). For example:
85
+ ```ruby
86
+ class User < ActiveRecord::Base
87
+ declare_schema default_schema: false do
88
+ ...
89
+ end
90
+ end
91
+ ```
92
+
73
93
  ### Global Configuration
74
94
  Configurations can be set at the global level to customize default declaration for the following values:
75
95
 
@@ -187,7 +207,7 @@ at three separate levels
187
207
 
188
208
  ### Table Configuration
189
209
  In order to configure a table's default character set and collation, the `charset` and
190
- `collation` arguments can be added to the `fields` block.
210
+ `collation` arguments can be added to the `declare_schema` block.
191
211
 
192
212
  For example, if you have a comments model that needs `utf8mb4` support, it would look
193
213
  like the following:
@@ -197,7 +217,7 @@ like the following:
197
217
  # frozen_string_literal: true
198
218
 
199
219
  class Comment < ActiveRecord::Base
200
- fields charset: "utf8mb4", collation: "utf8mb4_bin" do
220
+ declare_schema charset: "utf8mb4", collation: "utf8mb4_bin" do
201
221
  subject :string, limit: 255
202
222
  content :text, limit: 0xffff_ffff
203
223
  end
@@ -217,7 +237,7 @@ look like the following:
217
237
  # frozen_string_literal: true
218
238
 
219
239
  class Comment < ActiveRecord::Base
220
- fields do
240
+ declare_schema do
221
241
  subject :string, limit: 255
222
242
  context :text, limit: 0xffff_ffff, charset: "utf8mb4", collation: "utf8mb4_bin"
223
243
  end
@@ -37,7 +37,7 @@ module DeclareSchema
37
37
 
38
38
  class << self
39
39
  attr_reader :default_charset, :default_collation, :default_text_limit, :default_string_limit, :default_null,
40
- :default_generate_foreign_keys, :default_generate_indexing, :db_migrate_command
40
+ :default_generate_foreign_keys, :default_generate_indexing, :default_schema, :db_migrate_command
41
41
 
42
42
  def to_class(type)
43
43
  case type
@@ -85,6 +85,11 @@ module DeclareSchema
85
85
  @default_generate_indexing = generate_indexing
86
86
  end
87
87
 
88
+ def default_schema=(default_schema)
89
+ default_schema.nil? || default_schema.respond_to?(:call) or raise "default_schema must be nil or a block that responds to call"
90
+ @default_schema = default_schema
91
+ end
92
+
88
93
  def db_migrate_command=(db_migrate_command)
89
94
  db_migrate_command.is_a?(String) or raise ArgumentError, "db_migrate_command must be a string (got #{db_migrate_command.inspect})"
90
95
  @db_migrate_command = db_migrate_command
@@ -7,7 +7,7 @@ module DeclareSchema
7
7
  include ::Kernel # but we need the basic class methods
8
8
 
9
9
  instance_methods.each do |m|
10
- unless m.to_s.starts_with?('__') || m.in?([:object_id, :instance_eval])
10
+ unless m.to_s.starts_with?('__') || m.in?([:object_id, :instance_eval, :instance_exec])
11
11
  undef_method(m)
12
12
  end
13
13
  end
@@ -32,8 +32,11 @@ module DeclareSchema
32
32
  @model.declare_field(name, type, *(args + [@options.merge(options)]))
33
33
  end
34
34
 
35
- def method_missing(type, name, *args)
36
- field(name, type, *args)
35
+ # TODO: make [:required] just another option. Either 'required: true] or 'optional: false'?
36
+ def method_missing(*args, **options)
37
+ args.count(&:itself) >= 2 or raise ::ArgumentError, "fields in declare_schema block must be declared as: type name, [:required], options (got #{args.inspect}, #{options.inspect})"
38
+ type, name, *required = args
39
+ field(name, type, *required, options)
37
40
  end
38
41
  end
39
42
  end
@@ -7,12 +7,14 @@ require 'declare_schema/field_declaration_dsl'
7
7
 
8
8
  module DeclareSchema
9
9
  module Macros
10
+ attr_reader :_table_options
11
+
10
12
  def fields(table_options = {}, &block)
11
13
  # Any model that calls 'fields' gets DeclareSchema::Model behavior
12
14
  DeclareSchema::Model.mix_in(self)
13
15
 
14
16
  @include_in_migration = true
15
- @table_options = table_options
17
+ @_table_options = table_options
16
18
 
17
19
  if block
18
20
  dsl = DeclareSchema::FieldDeclarationDsl.new(self)
@@ -25,20 +27,19 @@ module DeclareSchema
25
27
  end
26
28
  deprecate :fields, deprecator: ActiveSupport::Deprecation.new('1.0', 'DeclareSchema')
27
29
 
28
- def declare_schema(table_options = {}, &block)
30
+ def declare_schema(default_schema: true, **table_options, &block)
29
31
  # Any model that calls 'fields' gets DeclareSchema::Model behavior
30
32
  DeclareSchema::Model.mix_in(self)
31
33
 
32
34
  # @include_in_migration = false #||= options.fetch(:include_in_migration, true); options.delete(:include_in_migration)
33
35
  @include_in_migration = true # TODO: Add back or delete the include_in_migration feature
34
- @table_options = table_options
36
+ @_table_options = table_options
35
37
 
36
38
  if block
37
39
  dsl = DeclareSchema::Dsl.new(self, null: false)
38
- if block.arity == 1
39
- yield dsl
40
- else
41
- dsl.instance_eval(&block)
40
+ dsl.instance_eval(&block)
41
+ if default_schema && DeclareSchema.default_schema
42
+ dsl.instance_exec(&DeclareSchema.default_schema)
42
43
  end
43
44
  end
44
45
  end
@@ -34,19 +34,16 @@ module DeclareSchema
34
34
  # supported options include :charset and :collation
35
35
  inheriting_cattr_reader table_options: HashWithIndifferentAccess.new
36
36
 
37
- # eval avoids the ruby 1.9.2 "super from singleton method ..." error
38
-
39
- eval <<~EOS
40
- def self.inherited(klass)
41
- unless klass.field_specs.has_key?(inheritance_column)
42
- declare_schema do |f|
43
- f.field(inheritance_column, :string, limit: 255, null: true)
44
- end
45
- index(inheritance_column)
37
+ def self.inherited(klass)
38
+ unless klass.field_specs.has_key?(inheritance_column)
39
+ ic = inheritance_column
40
+ declare_schema do
41
+ field(ic, :string, limit: 255, null: true)
46
42
  end
47
- super
43
+ index(ic)
48
44
  end
49
- EOS
45
+ super
46
+ end
50
47
  end
51
48
  end
52
49
  end
@@ -99,7 +96,10 @@ module DeclareSchema
99
96
  end
100
97
  end
101
98
 
102
- # Extend belongs_to so that it creates a FieldSpec for the foreign key
99
+ # Extend belongs_to so that it
100
+ # 1. creates a FieldSpec for the foreign key
101
+ # 2. declares an index on the foreign key
102
+ # 3. declares a foreign_key constraint
103
103
  def belongs_to(name, scope = nil, **options)
104
104
  column_options = {}
105
105
 
@@ -109,7 +109,10 @@ module DeclareSchema
109
109
  options[:optional] # infer :null from :optional
110
110
  end || false
111
111
  column_options[:default] = options.delete(:default) if options.has_key?(:default)
112
- column_options[:limit] = options.delete(:limit) if options.has_key?(:limit)
112
+ if options.has_key?(:limit)
113
+ options.delete(:limit)
114
+ ActiveSupport::Deprecation.warn("belongs_to limit: is deprecated since it is now inferred")
115
+ end
113
116
 
114
117
  index_options = {}
115
118
  index_options[:name] = options.delete(:index) if options.has_key?(:index)
@@ -136,7 +139,25 @@ module DeclareSchema
136
139
 
137
140
  refl = reflections[name.to_s] or raise "Couldn't find reflection #{name} in #{reflections.keys}"
138
141
  fkey = refl.foreign_key or raise "Couldn't find foreign_key for #{name} in #{refl.inspect}"
139
- declare_field(fkey.to_sym, :integer, column_options)
142
+ fkey_id_column_options = column_options.dup
143
+
144
+ # Note: the foreign key limit: should match the primary key limit:. (If there is a foreign key constraint,
145
+ # those limits _must_ match.) We'd like to call _infer_fk_limit and get the limit right from the PK.
146
+ # But we can't here, because that will mess up the autoloader to follow every belongs_to association right
147
+ # when it is declared. So instead we assume :bigint (integer limit: 8) below, while also registering this
148
+ # pre_migration: callback to double-check that assumption Just In Time--right before we generate a migration.
149
+ #
150
+ # The one downside of this approach is that application code that asks the field_spec for the declared
151
+ # foreign key limit: will always get 8 back even if this is a grandfathered foreign key that points to
152
+ # a limit: 4 primary key. It seems unlikely that any application code would do this.
153
+ fkey_id_column_options[:pre_migration] = ->(field_spec) do
154
+ if (inferred_limit = _infer_fk_limit(fkey, refl))
155
+ field_spec.sql_options[:limit] = inferred_limit
156
+ end
157
+ end
158
+
159
+ declare_field(fkey.to_sym, :bigint, fkey_id_column_options)
160
+
140
161
  if refl.options[:polymorphic]
141
162
  foreign_type = options[:foreign_type] || "#{name}_type"
142
163
  _declare_polymorphic_type_field(foreign_type, column_options)
@@ -147,6 +168,28 @@ module DeclareSchema
147
168
  end
148
169
  end
149
170
 
171
+ def _infer_fk_limit(fkey, refl)
172
+ if refl.options[:polymorphic]
173
+ if (fkey_column = columns_hash[fkey.to_s]) && fkey_column.type == :integer
174
+ fkey_column.limit
175
+ end
176
+ else
177
+ klass = refl.klass or raise "Couldn't find belongs_to klass for #{name} in #{refl.inspect}"
178
+ if (pk_id_type = klass._table_options&.[](:id))
179
+ if pk_id_type == :integer
180
+ 4
181
+ end
182
+ else
183
+ if klass.table_exists? && (pk_column = klass.columns_hash[klass._declared_primary_key])
184
+ pk_id_type = pk_column.type
185
+ if pk_id_type == :integer
186
+ pk_column.limit
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+
150
193
  if ::ActiveSupport::VERSION::MAJOR < 5
151
194
  def primary_key
152
195
  super || 'id'
@@ -155,27 +198,27 @@ module DeclareSchema
155
198
 
156
199
  # returns the primary key (String) as declared with primary_key =
157
200
  # unlike the `primary_key` method, DOES NOT query the database to find the actual primary key in use right now
158
- # if no explicit primary key set, returns the default_defined_primary_key
159
- def _defined_primary_key
201
+ # if no explicit primary key set, returns the _default_declared_primary_key
202
+ def _declared_primary_key
160
203
  if defined?(@primary_key)
161
204
  @primary_key&.to_s
162
- end || _default_defined_primary_key
205
+ end || _default_declared_primary_key
163
206
  end
164
207
 
165
208
  private
166
209
 
167
- # if this is a derived class, returns the base class's _defined_primary_key
210
+ # if this is a derived class, returns the base class's _declared_primary_key
168
211
  # otherwise, returns 'id'
169
- def _default_defined_primary_key
212
+ def _default_declared_primary_key
170
213
  if self == base_class
171
214
  'id'
172
215
  else
173
- base_class._defined_primary_key
216
+ base_class._declared_primary_key
174
217
  end
175
218
  end
176
219
 
177
220
  def _rails_default_primary_key
178
- ::DeclareSchema::Model::IndexDefinition.new(self, [_defined_primary_key.to_sym], unique: true, name: DeclareSchema::Model::IndexDefinition::PRIMARY_KEY_NAME)
221
+ ::DeclareSchema::Model::IndexDefinition.new(self, [_declared_primary_key.to_sym], unique: true, name: DeclareSchema::Model::IndexDefinition::PRIMARY_KEY_NAME)
179
222
  end
180
223
 
181
224
  # Declares the "foo_type" field that accompanies the "foo_id"
@@ -59,7 +59,7 @@ module DeclareSchema
59
59
  # might be getting migrated to a new type. We should be using just type as below. -Colin
60
60
  column.type_cast_from_database(default_value)
61
61
  else
62
- cast_type = ActiveRecord::Base.connection.send(:lookup_cast_type, type) or
62
+ cast_type = ActiveRecord::Base.connection.send(:lookup_cast_type, type.to_s) or
63
63
  raise "cast_type not found for #{type}"
64
64
  cast_type.deserialize(default_value)
65
65
  end
@@ -47,9 +47,9 @@ module DeclareSchema
47
47
  end
48
48
 
49
49
  def initialize(model, name, type, position: 0, **options)
50
- _defined_primary_key = model._defined_primary_key
50
+ _declared_primary_key = model._declared_primary_key
51
51
 
52
- name.to_s == _defined_primary_key and raise ArgumentError, "you may not provide a field spec for the primary key #{name.inspect}"
52
+ name.to_s == _declared_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
@@ -76,12 +76,19 @@ module DeclareSchema
76
76
  when :bigint
77
77
  @type = :integer
78
78
  @options[:limit] = 8
79
+ when :enum
80
+ @options[:default].nil? || @options[:default].is_a?(Symbol) or
81
+ raise ArgumentError, "enum default: must be nil or a Symbol; got #{@options[:default].inspect}"
82
+ @options[:limit].is_a?(Array) && @options[:limit].size >= 1 && @options[:limit].all? { |value| value.is_a?(Symbol) } or
83
+ raise ArgumentError, "enum limit: must be an array of 1 or more Symbols; got #{@options[:limit].inspect}"
79
84
  end
80
85
 
81
86
  Column.native_type?(@type) or raise UnknownTypeError, "#{@type.inspect} not found in #{Column.native_types.inspect} for adapter #{ActiveRecord::Base.connection.class.name}"
82
87
 
83
- if @type.in?([:string, :text, :binary, :varbinary, :integer, :enum])
88
+ if @type.in?([:string, :text, :binary, :varbinary, :integer])
84
89
  @options[:limit] ||= Column.native_types.dig(@type, :limit)
90
+ elsif @type.in?([:enum])
91
+ # nothing to do
85
92
  else
86
93
  @type != :decimal && @options.has_key?(:limit) and warn("unsupported limit: for SQL type #{@type} in field #{model}##{@name}")
87
94
  @options.delete(:limit)
@@ -99,8 +106,8 @@ module DeclareSchema
99
106
 
100
107
  if @type.in?([:text, :string])
101
108
  if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
102
- @options[:charset] ||= model.table_options[:charset] || ::DeclareSchema.default_charset
103
- @options[:collation] ||= model.table_options[:collation] || ::DeclareSchema.default_collation
109
+ @options[:charset] ||= model._table_options&.[](:charset) || ::DeclareSchema.default_charset
110
+ @options[:collation] ||= model._table_options&.[](:collation) || ::DeclareSchema.default_collation
104
111
  else
105
112
  @options.delete(:charset)
106
113
  @options.delete(:collation)
@@ -29,7 +29,7 @@ module DeclareSchema
29
29
  @connection = connection
30
30
  end
31
31
 
32
- def table_options
32
+ def _table_options
33
33
  {}
34
34
  end
35
35
 
@@ -47,7 +47,7 @@ module DeclareSchema
47
47
  false # no single-column primary key in database
48
48
  end
49
49
 
50
- def _defined_primary_key
50
+ def _declared_primary_key
51
51
  false # no single-column primary key declared
52
52
  end
53
53
 
@@ -37,7 +37,7 @@ module DeclareSchema
37
37
  def for_model(model, old_table_name = nil)
38
38
  t = old_table_name || model.table_name
39
39
 
40
- primary_key_columns = Array(model.connection.primary_key(t)).presence || sqlite_compound_primary_key(model, t) or
40
+ primary_key_columns = Array(model.connection.primary_key(t)).presence || fallback_find_primary_key(model, t) or
41
41
  raise "could not find primary key for table #{t} in #{model.connection.columns(t).inspect}"
42
42
 
43
43
  primary_key_found = false
@@ -67,7 +67,7 @@ module DeclareSchema
67
67
  private
68
68
 
69
69
  # This is the old approach which is still needed for MySQL in Rails 4 and SQLite
70
- def sqlite_compound_primary_key(model, table)
70
+ def fallback_find_primary_key(model, table)
71
71
  ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/) || ActiveSupport::VERSION::MAJOR < 5 or return nil
72
72
 
73
73
  connection = model.connection.dup
@@ -83,9 +83,11 @@ module DeclareSchema
83
83
  end
84
84
  end
85
85
 
86
- pk_index = connection.indexes(table).find { |index| index.name.to_s == PRIMARY_KEY_NAME } or return nil
87
-
88
- Array(pk_index.columns)
86
+ if (pk_index = connection.indexes(table).find { |index| index.name.to_s == PRIMARY_KEY_NAME })
87
+ Array(pk_index.columns)
88
+ elsif model.connection.columns(table).any? { |col| col.name == 'id' }
89
+ ['id']
90
+ end
89
91
  end
90
92
  end
91
93
 
@@ -6,9 +6,9 @@ module DeclareSchema
6
6
  module SchemaChange
7
7
  class ColumnAdd < Base
8
8
  def initialize(table_name, column_name, column_type, **column_options)
9
- @table_name = table_name
10
- @column_name = column_name
11
- @column_type = column_type
9
+ @table_name = table_name or raise ArgumentError, "must provide table_name"
10
+ @column_name = column_name or raise ArgumentError, "must provide column_name"
11
+ @column_type = column_type or raise ArgumentError, "must provide column_type"
12
12
  @column_options = column_options
13
13
  end
14
14
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeclareSchema
4
- VERSION = "0.11.1"
4
+ VERSION = "0.13.0.pre.1"
5
5
  end
@@ -187,6 +187,12 @@ module Generators
187
187
  models, db_tables = models_and_tables
188
188
  models_by_table_name = {}
189
189
  models.each do |m|
190
+ m.try(:field_specs)&.each do |_name, field_spec|
191
+ if (pre_migration = field_spec.options.delete(:pre_migration))
192
+ pre_migration.call(field_spec)
193
+ end
194
+ end
195
+
190
196
  if !models_by_table_name.has_key?(m.table_name)
191
197
  models_by_table_name[m.table_name] = m
192
198
  elsif m.superclass == models_by_table_name[m.table_name].superclass.superclass
@@ -203,8 +209,8 @@ module Generators
203
209
 
204
210
  to_create = model_table_names - db_tables
205
211
  to_drop = db_tables - model_table_names - self.class.always_ignore_tables
206
- to_change = model_table_names
207
212
  to_rename = extract_table_renames!(to_create, to_drop)
213
+ to_change = model_table_names
208
214
 
209
215
  renames = to_rename.map do |old_name, new_name|
210
216
  ::DeclareSchema::SchemaChange::TableRename.new(old_name, new_name)
@@ -297,14 +303,14 @@ module Generators
297
303
  end
298
304
 
299
305
  def create_table_options(model, disable_auto_increment)
300
- primary_key = model._defined_primary_key
306
+ primary_key = model._declared_primary_key
301
307
  if primary_key.blank? || disable_auto_increment
302
308
  { id: false }
303
309
  elsif primary_key == "id"
304
310
  { id: :bigint }
305
311
  else
306
312
  { primary_key: primary_key.to_sym }
307
- end
313
+ end.merge(model._table_options)
308
314
  end
309
315
 
310
316
  def table_options_for_model(model)
@@ -312,8 +318,8 @@ module Generators
312
318
  {}
313
319
  else
314
320
  {
315
- charset: model.table_options[:charset] || ::DeclareSchema.default_charset,
316
- collation: model.table_options[:collation] || ::DeclareSchema.default_collation
321
+ charset: model._table_options&.[](:charset) || ::DeclareSchema.default_charset,
322
+ collation: model._table_options&.[](:collation) || ::DeclareSchema.default_collation
317
323
  }
318
324
  end
319
325
  end
@@ -336,18 +342,16 @@ module Generators
336
342
  new_table_name = model.table_name
337
343
 
338
344
  db_columns = model.connection.columns(current_table_name).index_by(&:name)
339
- key_missing = db_columns[model._defined_primary_key].nil? && model._defined_primary_key.present?
340
- if model._defined_primary_key.present?
341
- db_columns.delete(model._defined_primary_key)
345
+ if (pk = model._declared_primary_key.presence)
346
+ pk_was_in_db_columns = db_columns.delete(pk)
342
347
  end
343
348
 
344
349
  model_column_names = model.field_specs.keys.map(&:to_s)
345
350
  db_column_names = db_columns.keys.map(&:to_s)
346
351
 
347
352
  to_add = model_column_names - db_column_names
348
- to_add += [model._defined_primary_key] if key_missing && model._defined_primary_key.present?
353
+ to_add << pk if pk && !pk_was_in_db_columns
349
354
  to_remove = db_column_names - model_column_names
350
- to_remove -= [model._defined_primary_key.to_sym] if model._defined_primary_key.present?
351
355
 
352
356
  to_rename = extract_column_renames!(to_add, to_remove, new_table_name)
353
357
 
@@ -40,16 +40,14 @@ RSpec.describe 'DeclareSchema API' do
40
40
  load_models
41
41
 
42
42
  if ActiveSupport::VERSION::MAJOR == 5
43
- # TODO: get this to work on Travis for Rails 6
44
43
  generate_migrations '-n', '-m'
45
44
  end
46
45
 
47
46
  require 'advert'
47
+ Advert.reset_primary_key
48
48
 
49
49
  ## The Basics
50
50
 
51
- # The main feature of DeclareSchema, aside from the migration generator, is the ability to declare rich types for your fields. For example, you can declare that a field is an email address, and the field will be automatically validated for correct email address syntax.
52
-
53
51
  ### Field Types
54
52
 
55
53
  # Field values are returned as the type you specify.
@@ -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: {}, _defined_primary_key: 'id') }
9
+ let(:model) { double('model', _table_options: {}, _declared_primary_key: 'id') }
10
10
  let(:col_spec) { double('col_spec', type: :string) }
11
11
 
12
12
  before do
@@ -115,6 +115,48 @@ RSpec.describe DeclareSchema::Model::FieldSpec do
115
115
  end
116
116
  end
117
117
 
118
+ describe 'enum' do
119
+ before do
120
+ allow(::DeclareSchema::Model::Column).to receive(:native_types).and_wrap_original do |m, *_args|
121
+ result = m.call
122
+ if result.has_key?(:enum)
123
+ result
124
+ else
125
+ result.merge(enum: { name: "enum" })
126
+ end
127
+ end
128
+ end
129
+
130
+ describe 'default' do
131
+ it 'allows default of nil or a Symbol' do
132
+ [nil, :first].each do |default|
133
+ expect do
134
+ subject = described_class.new(model, :status, :enum, limit: [:first, :second, :third], default: default, null: false, position: 2)
135
+ expect(subject.default).to eq(default)
136
+ end.to_not raise_exception
137
+ end
138
+ end
139
+
140
+ it 'raises ArgumentError if default is not nil or a Symbol' do
141
+ ["first", 1].each do |default|
142
+ expect do
143
+ described_class.new(model, :status, :enum, limit: [:first, :second, :third], default: default, null: false, position: 2)
144
+ end.to raise_exception(ArgumentError, /enum default: must be nil or a Symbol; got #{Regexp.escape(default.inspect)}/)
145
+ end
146
+ end
147
+ end
148
+
149
+ describe 'limit' do
150
+ it 'raises ArgumentError if any of the limit values are not Symbols' do
151
+ [['first', 'second', 'third'], [1, 2, 3], nil, []].each do |limit|
152
+ expect do
153
+ described_class.new(model, :status, :enum, limit: limit, null: false, position: 2)
154
+ end.to raise_exception(ArgumentError, /enum limit: must be an array of 1 or more Symbols; got #{Regexp.escape(limit.inspect)}/)
155
+ end
156
+ end
157
+ end
158
+ end
159
+
118
160
  if defined?(Mysql2)
119
161
  describe 'varbinary' do # TODO: :varbinary is an Invoca addition to Rails; make it a configurable option
120
162
  it 'is supported' do
@@ -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._defined_primary_key).to eq('foo_id')
22
+ expect(Foo._declared_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
  allow_any_instance_of(DeclareSchema::Support::ThorShell).to receive(:ask).with(/one of the rename choices or press enter to keep/) { 'id' }
33
33
  generate_migrations '-n', '-m'
34
- expect(Foo._defined_primary_key).to eq('id')
34
+ expect(Foo._declared_primary_key).to eq('id')
35
35
 
36
36
  nuke_model_class(Foo)
37
37
 
@@ -72,7 +72,7 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
72
72
 
73
73
  allow_any_instance_of(DeclareSchema::Support::ThorShell).to receive(:ask).with(/one of the rename choices or press enter to keep/) { 'drop id' }
74
74
  generate_migrations '-n', '-m'
75
- expect(Foo._defined_primary_key).to eq('foo_id')
75
+ expect(Foo._declared_primary_key).to eq('foo_id')
76
76
  end
77
77
  end
78
78
  end
@@ -80,8 +80,7 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
80
80
  context 'Using declare_schema' do
81
81
  it "allows alternate primary keys" do
82
82
  class Foo < ActiveRecord::Base
83
- declare_schema do
84
- end
83
+ declare_schema { }
85
84
  self.primary_key = "foo_id"
86
85
  end
87
86
 
@@ -91,15 +90,14 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
91
90
  ### migrate from
92
91
  # rename from custom primary_key
93
92
  class Foo < ActiveRecord::Base
94
- declare_schema do
95
- end
93
+ declare_schema { }
96
94
  self.primary_key = "id"
97
95
  end
98
96
 
99
97
  puts "\n\e[45m Please enter 'id' (no quotes) at the next prompt \e[0m"
100
98
  allow_any_instance_of(DeclareSchema::Support::ThorShell).to receive(:ask).with(/one of the rename choices or press enter to keep/) { 'id' }
101
99
  generate_migrations '-n', '-m'
102
- expect(Foo.primary_key).to eq('id')
100
+ expect(Foo._declared_primary_key).to eq('id')
103
101
 
104
102
  nuke_model_class(Foo)
105
103
 
@@ -441,10 +441,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do
441
441
  Advert.field_specs.delete(:category_id)
442
442
  Advert.index_definitions.delete_if { |spec| spec.fields == ["category_id"] }
443
443
 
444
- ### Timestamps and Optimimistic Locking
444
+ ### Timestamps and Optimistic Locking
445
445
 
446
446
  # `updated_at` and `created_at` can be declared with the shorthand `timestamps`.
447
- # Similarly, `lock_version` can be declared with the "shorthand" `optimimistic_lock`.
447
+ # Similarly, `lock_version` can be declared with the "shorthand" `optimistic_lock`.
448
448
 
449
449
  class Advert < ActiveRecord::Base
450
450
  fields do
@@ -1860,6 +1860,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1860
1860
  class SuperFancyAdvert < FancyAdvert
1861
1861
  end
1862
1862
 
1863
+ expect(Generators::DeclareSchema::Migration::Migrator.run.first).to be_present
1864
+
1863
1865
  up, _ = Generators::DeclareSchema::Migration::Migrator.run do |migrations|
1864
1866
  expect(migrations).to(
1865
1867
  migrate_up(<<~EOS.strip)
@@ -2039,7 +2041,6 @@ RSpec.describe 'DeclareSchema Migration Generator' do
2039
2041
  add_foreign_key :affiliates, :categories, column: :category_id, name: :index_affiliates_on_category_id
2040
2042
  EOS
2041
2043
  )
2042
- binding.pry
2043
2044
  migrate
2044
2045
 
2045
2046
  nuke_model_class(Advertiser)
@@ -2242,80 +2243,202 @@ RSpec.describe 'DeclareSchema Migration Generator' do
2242
2243
  let(:optional_flag) { { false => optional_false, true => optional_true } }
2243
2244
 
2244
2245
  describe 'belongs_to' do
2245
- before do
2246
- unless defined?(AdCategory)
2247
- class AdCategory < ActiveRecord::Base
2248
- declare_schema { }
2246
+ context 'with AdCategory and Advert in DB' do
2247
+ before do
2248
+ unless defined?(AdCategory)
2249
+ class AdCategory < ActiveRecord::Base
2250
+ declare_schema { }
2251
+ end
2249
2252
  end
2250
- end
2251
2253
 
2252
- class Advert < ActiveRecord::Base
2253
- declare_schema do
2254
- string :name, limit: 250, null: true
2255
- integer :category_id, limit: 8
2256
- integer :nullable_category_id, limit: 8, null: true
2254
+ class Advert < ActiveRecord::Base
2255
+ declare_schema do
2256
+ string :name, limit: 250, null: true
2257
+ integer :category_id, limit: 8
2258
+ integer :nullable_category_id, limit: 8, null: true
2259
+ end
2257
2260
  end
2261
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2262
+ ActiveRecord::Migration.class_eval(up)
2258
2263
  end
2259
- up = Generators::DeclareSchema::Migration::Migrator.run.first
2260
- ActiveRecord::Migration.class_eval(up)
2261
- end
2262
2264
 
2263
- it 'passes through optional: when given' do
2264
- class AdvertBelongsTo < ActiveRecord::Base
2265
- self.table_name = 'adverts'
2266
- declare_schema { }
2267
- reset_column_information
2268
- belongs_to :ad_category, optional: true
2269
- end
2270
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_true)
2271
- end
2272
-
2273
- describe 'contradictory settings' do # contradictory settings are ok--for example, during migration
2274
- it 'passes through optional: true, null: false' do
2265
+ it 'passes through optional: when given' do
2275
2266
  class AdvertBelongsTo < ActiveRecord::Base
2276
2267
  self.table_name = 'adverts'
2277
2268
  declare_schema { }
2278
2269
  reset_column_information
2279
- belongs_to :ad_category, optional: true, null: false
2270
+ belongs_to :ad_category, optional: true
2280
2271
  end
2281
2272
  expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_true)
2282
- expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(false)
2283
2273
  end
2284
2274
 
2285
- it 'passes through optional: false, null: true' do
2286
- class AdvertBelongsTo < ActiveRecord::Base
2287
- self.table_name = 'adverts'
2288
- declare_schema { }
2289
- reset_column_information
2290
- belongs_to :ad_category, optional: false, null: true
2275
+ describe 'contradictory settings' do # contradictory settings are ok--for example, during migration
2276
+ it 'passes through optional: true, null: false' do
2277
+ class AdvertBelongsTo < ActiveRecord::Base
2278
+ self.table_name = 'adverts'
2279
+ declare_schema { }
2280
+ reset_column_information
2281
+ belongs_to :ad_category, optional: true, null: false
2282
+ end
2283
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_true)
2284
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(false)
2285
+ end
2286
+
2287
+ it 'passes through optional: false, null: true' do
2288
+ class AdvertBelongsTo < ActiveRecord::Base
2289
+ self.table_name = 'adverts'
2290
+ declare_schema { }
2291
+ reset_column_information
2292
+ belongs_to :ad_category, optional: false, null: true
2293
+ end
2294
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_false)
2295
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(true)
2291
2296
  end
2292
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_false)
2293
- expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(true)
2297
+ end
2298
+
2299
+ [false, true].each do |nullable|
2300
+ context "nullable=#{nullable}" do
2301
+ it 'infers optional: from null:' do
2302
+ eval <<~EOS
2303
+ class AdvertBelongsTo < ActiveRecord::Base
2304
+ declare_schema { }
2305
+ belongs_to :ad_category, null: #{nullable}
2306
+ end
2307
+ EOS
2308
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
2309
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
2310
+ end
2311
+
2312
+ it 'infers null: from optional:' do
2313
+ eval <<~EOS
2314
+ class AdvertBelongsTo < ActiveRecord::Base
2315
+ declare_schema { }
2316
+ belongs_to :ad_category, optional: #{nullable}
2317
+ end
2318
+ EOS
2319
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
2320
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
2321
+ end
2322
+ end
2323
+ end
2324
+
2325
+ it 'deprecates limit:' do
2326
+ expect(ActiveSupport::Deprecation).to receive(:warn).with("belongs_to limit: is deprecated since it is now inferred")
2327
+ eval <<~EOS
2328
+ class UsingLimit < ActiveRecord::Base
2329
+ declare_schema { }
2330
+ belongs_to :ad_category, limit: 4
2331
+ end
2332
+ EOS
2294
2333
  end
2295
2334
  end
2296
2335
 
2297
- [false, true].each do |nullable|
2298
- context "nullable=#{nullable}" do
2299
- it 'infers optional: from null:' do
2300
- eval <<~EOS
2301
- class AdvertBelongsTo < ActiveRecord::Base
2302
- declare_schema { }
2303
- belongs_to :ad_category, null: #{nullable}
2304
- end
2305
- EOS
2306
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
2307
- expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
2336
+ context 'when parent object PKs have different limits' do
2337
+ before do
2338
+ class IdDefault < ActiveRecord::Base
2339
+ declare_schema { }
2340
+ end
2341
+ class Id4 < ActiveRecord::Base
2342
+ declare_schema id: :integer do
2343
+ end
2344
+ end
2345
+ class Id8 < ActiveRecord::Base
2346
+ declare_schema id: :bigint do
2347
+ end
2348
+ end
2349
+ class Fk < ActiveRecord::Base
2350
+ declare_schema { }
2351
+ belongs_to :id_default, (ActiveSupport::VERSION::MAJOR < 5 ? { constraint: false } : {})
2352
+ belongs_to :id4, (ActiveSupport::VERSION::MAJOR < 5 ? { constraint: false } : {})
2353
+ belongs_to :id8, (ActiveSupport::VERSION::MAJOR < 5 ? { constraint: false } : {})
2308
2354
  end
2355
+ end
2309
2356
 
2310
- it 'infers null: from optional:' do
2311
- eval <<~EOS
2312
- class AdvertBelongsTo < ActiveRecord::Base
2313
- declare_schema { }
2314
- belongs_to :ad_category, optional: #{nullable}
2315
- end
2316
- EOS
2317
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
2318
- expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
2357
+ it 'creates the proper PKs' do
2358
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2359
+
2360
+ create_id4_defaults = up.split("\n").grep(/create_table :id_defaults/).first
2361
+ expect(create_id4_defaults).to be, up
2362
+ expect(create_id4_defaults).to match(/, id: :bigint/)
2363
+
2364
+ create_id4s = up.split("\n").grep(/create_table :id4s/).first
2365
+ expect(create_id4s).to be, up
2366
+ expect(create_id4s).to match(/, id: :integer/)
2367
+
2368
+ create_id8s = up.split("\n").grep(/create_table :id8s/).first
2369
+ expect(create_id8s).to be, up
2370
+ expect(create_id8s).to match(/, id: :bigint/)
2371
+ end
2372
+
2373
+ it 'infers the correct FK type from the create_table id: type' do
2374
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2375
+
2376
+ create_fks = up.split("\n").grep(/t\.integer /).map { |command| command.gsub(', null: false', '').gsub(/^ +/, '') }
2377
+ if defined?(SQLite3)
2378
+ create_fks.map! { |command| command.gsub(/limit: [a-z0-9]+/, 'limit: X') }
2379
+ expect(create_fks).to eq([
2380
+ 't.integer :id_default_id, limit: X',
2381
+ 't.integer :id4_id, limit: X',
2382
+ 't.integer :id8_id, limit: X'
2383
+ ]), up
2384
+ else
2385
+ expect(create_fks).to eq([
2386
+ 't.integer :id_default_id, limit: 8',
2387
+ 't.integer :id4_id, limit: 4',
2388
+ 't.integer :id8_id, limit: 8'
2389
+ ]), up
2390
+ end
2391
+ end
2392
+
2393
+ context "when parent objects were migrated before and later definitions don't have explicit id:" do
2394
+ before do
2395
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2396
+ ActiveRecord::Migration.class_eval up
2397
+ nuke_model_class(IdDefault)
2398
+ nuke_model_class(Id4)
2399
+ nuke_model_class(Id8)
2400
+ nuke_model_class(Fk)
2401
+ ActiveRecord::Base.connection.schema_cache.clear!
2402
+
2403
+
2404
+ class NewIdDefault < ActiveRecord::Base
2405
+ self.table_name = 'id_defaults'
2406
+ declare_schema { }
2407
+ end
2408
+ class NewId4 < ActiveRecord::Base
2409
+ self.table_name = 'id4s'
2410
+ declare_schema { }
2411
+ end
2412
+ class NewId8 < ActiveRecord::Base
2413
+ self.table_name = 'id8s'
2414
+ declare_schema { }
2415
+ end
2416
+ class NewFk < ActiveRecord::Base
2417
+ declare_schema { }
2418
+ belongs_to :new_id_default
2419
+ belongs_to :new_id4
2420
+ belongs_to :new_id8
2421
+ end
2422
+ end
2423
+
2424
+ it 'infers the correct FK :integer limit: ' do
2425
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2426
+
2427
+ create_fks = up.split("\n").grep(/t\.integer /).map { |command| command.gsub(', null: false', '').gsub(/^ +/, '') }
2428
+ if defined?(SQLite3)
2429
+ create_fks.map! { |command| command.gsub(/limit: [a-z0-9]+/, 'limit: X') }
2430
+ expect(create_fks).to eq([
2431
+ 't.integer :new_id_default_id, limit: X',
2432
+ 't.integer :new_id4_id, limit: X',
2433
+ 't.integer :new_id8_id, limit: X'
2434
+ ]), up
2435
+ else
2436
+ expect(create_fks).to eq([
2437
+ 't.integer :new_id_default_id, limit: 8',
2438
+ 't.integer :new_id4_id, limit: 4',
2439
+ 't.integer :new_id8_id, limit: 8'
2440
+ ]), up
2441
+ end
2319
2442
  end
2320
2443
  end
2321
2444
  end
@@ -2370,5 +2493,78 @@ RSpec.describe 'DeclareSchema Migration Generator' do
2370
2493
  end
2371
2494
  end
2372
2495
  end
2496
+
2497
+ context 'default_schema' do
2498
+ let(:default_schema_block) { nil }
2499
+ let(:declare_model) do
2500
+ -> do
2501
+ class Advert < active_record_base_class.constantize
2502
+ declare_schema do
2503
+ integer :price, limit: 8
2504
+ end
2505
+ end
2506
+ end
2507
+ end
2508
+
2509
+ before do
2510
+ DeclareSchema.default_schema = default_schema_block
2511
+ end
2512
+
2513
+ after do
2514
+ DeclareSchema.default_schema = nil
2515
+ end
2516
+
2517
+ context 'when unset' do
2518
+ it 'adds nothing' do
2519
+ declare_model.call
2520
+
2521
+ expect(Advert.field_specs.keys).to eq(['price'])
2522
+ end
2523
+ end
2524
+
2525
+ context 'when set to a block' do
2526
+ let(:default_schema_block) do
2527
+ -> do
2528
+ timestamps
2529
+ field :lock_version, :integer, default: 1
2530
+ end
2531
+ end
2532
+
2533
+ it 'adds the fields in that block' do
2534
+ declare_model.call
2535
+
2536
+ expect(Advert.field_specs.keys).to eq(['price', 'created_at', 'updated_at', 'lock_version'])
2537
+ end
2538
+
2539
+ context 'and the model sets default_schema: false' do
2540
+ before do
2541
+ class Advert < active_record_base_class.constantize
2542
+ declare_schema default_schema: false do
2543
+ integer :price, limit: 8
2544
+ end
2545
+ end
2546
+ end
2547
+
2548
+ it 'does not add the default schema fields' do
2549
+ expect(Advert.field_specs.keys).to eq(['price'])
2550
+ end
2551
+ end
2552
+
2553
+ context 'and the block has redundant fields' do
2554
+ before do
2555
+ class Advert < active_record_base_class.constantize
2556
+ declare_schema do
2557
+ integer :price, limit: 8
2558
+ timestamps
2559
+ end
2560
+ end
2561
+ end
2562
+
2563
+ it 'is a no-op' do
2564
+ expect(Advert.field_specs.keys).to eq(['price', 'created_at', 'updated_at', 'lock_version'])
2565
+ end
2566
+ end
2567
+ end
2568
+ end
2373
2569
  end
2374
2570
  end
@@ -55,7 +55,7 @@ RSpec.describe DeclareSchema::Model::HabtmModelShim do
55
55
 
56
56
  describe '#table_options' do
57
57
  it 'returns empty hash' do
58
- expect(subject.table_options).to eq({})
58
+ expect(subject._table_options).to eq({})
59
59
  end
60
60
  end
61
61
 
@@ -86,13 +86,13 @@ RSpec.describe DeclareSchema::Model::HabtmModelShim do
86
86
 
87
87
  describe '#primary_key' do
88
88
  it 'returns false' do
89
- expect(subject._defined_primary_key).to eq(false)
89
+ expect(subject._declared_primary_key).to eq(false)
90
90
  end
91
91
  end
92
92
 
93
- describe '#_defined_primary_key' do
93
+ describe '#_declared_primary_key' do
94
94
  it 'returns false' do
95
- expect(subject._defined_primary_key).to eq(false)
95
+ expect(subject._declared_primary_key).to eq(false)
96
96
  end
97
97
  end
98
98
 
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.11.1
4
+ version: 0.13.0.pre.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: 2021-03-26 00:00:00.000000000 Z
11
+ date: 2021-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails