declare_schema 0.8.0.pre.6 → 0.10.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/.github/workflows/declare_schema_build.yml +1 -1
- data/CHANGELOG.md +28 -1
- data/Gemfile.lock +1 -1
- data/README.md +91 -13
- data/lib/declare_schema.rb +46 -0
- data/lib/declare_schema/dsl.rb +39 -0
- data/lib/declare_schema/extensions/active_record/fields_declaration.rb +23 -4
- data/lib/declare_schema/model.rb +51 -59
- data/lib/declare_schema/model/field_spec.rb +11 -8
- data/lib/declare_schema/model/foreign_key_definition.rb +4 -8
- data/lib/declare_schema/model/habtm_model_shim.rb +1 -1
- data/lib/declare_schema/model/index_definition.rb +0 -19
- data/lib/declare_schema/schema_change/all.rb +22 -0
- data/lib/declare_schema/schema_change/base.rb +45 -0
- data/lib/declare_schema/schema_change/column_add.rb +27 -0
- data/lib/declare_schema/schema_change/column_change.rb +32 -0
- data/lib/declare_schema/schema_change/column_remove.rb +20 -0
- data/lib/declare_schema/schema_change/column_rename.rb +23 -0
- data/lib/declare_schema/schema_change/foreign_key_add.rb +25 -0
- data/lib/declare_schema/schema_change/foreign_key_remove.rb +20 -0
- data/lib/declare_schema/schema_change/index_add.rb +33 -0
- data/lib/declare_schema/schema_change/index_remove.rb +20 -0
- data/lib/declare_schema/schema_change/primary_key_change.rb +33 -0
- data/lib/declare_schema/schema_change/table_add.rb +37 -0
- data/lib/declare_schema/schema_change/table_change.rb +36 -0
- data/lib/declare_schema/schema_change/table_remove.rb +22 -0
- data/lib/declare_schema/schema_change/table_rename.rb +22 -0
- data/lib/declare_schema/version.rb +1 -1
- data/lib/generators/declare_schema/migration/migrator.rb +189 -202
- data/lib/generators/declare_schema/support/model.rb +4 -4
- data/spec/lib/declare_schema/api_spec.rb +7 -7
- data/spec/lib/declare_schema/field_declaration_dsl_spec.rb +41 -15
- data/spec/lib/declare_schema/field_spec_spec.rb +50 -6
- data/spec/lib/declare_schema/generator_spec.rb +3 -3
- data/spec/lib/declare_schema/interactive_primary_key_spec.rb +116 -26
- data/spec/lib/declare_schema/migration_generator_spec.rb +1891 -845
- data/spec/lib/declare_schema/model/column_spec.rb +47 -17
- data/spec/lib/declare_schema/model/foreign_key_definition_spec.rb +134 -57
- data/spec/lib/declare_schema/model/habtm_model_shim_spec.rb +3 -3
- data/spec/lib/declare_schema/model/index_definition_spec.rb +188 -77
- data/spec/lib/declare_schema/model/table_options_definition_spec.rb +75 -11
- data/spec/lib/declare_schema/schema_change/base_spec.rb +75 -0
- data/spec/lib/declare_schema/schema_change/column_add_spec.rb +30 -0
- data/spec/lib/declare_schema/schema_change/column_change_spec.rb +33 -0
- data/spec/lib/declare_schema/schema_change/column_remove_spec.rb +30 -0
- data/spec/lib/declare_schema/schema_change/column_rename_spec.rb +28 -0
- data/spec/lib/declare_schema/schema_change/foreign_key_add_spec.rb +29 -0
- data/spec/lib/declare_schema/schema_change/foreign_key_remove_spec.rb +29 -0
- data/spec/lib/declare_schema/schema_change/index_add_spec.rb +56 -0
- data/spec/lib/declare_schema/schema_change/index_remove_spec.rb +29 -0
- data/spec/lib/declare_schema/schema_change/primary_key_change_spec.rb +69 -0
- data/spec/lib/declare_schema/schema_change/table_add_spec.rb +50 -0
- data/spec/lib/declare_schema/schema_change/table_change_spec.rb +30 -0
- data/spec/lib/declare_schema/schema_change/table_remove_spec.rb +27 -0
- data/spec/lib/declare_schema/schema_change/table_rename_spec.rb +27 -0
- data/spec/lib/declare_schema_spec.rb +101 -0
- data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +71 -13
- data/spec/support/acceptance_spec_helpers.rb +2 -2
- metadata +33 -3
- data/test_responses.txt +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a529991bad5ab16728f11b3f6c165b62853c3b68713e0ec69d6370d7d3c0e5b
|
4
|
+
data.tar.gz: 6a131f8af82b018b843f639e501371cf0db9a65b91a4acb99aea44d3eb1674d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 655ab291337bf8f11fb249de1b97608e7ff73b14ff543f9248e3f92d9bf1770553b8bc2f962c72e8763d27ae559c35bdff1f12f4b6b460a1d46abfab00e931c0
|
7
|
+
data.tar.gz: b67d3340bb42b91bddd0940e0a9e5a895bd57f2017ef8d4712e1e4331ba46e78b17d9f7e9b0e60de9f921232897c0edeffe37621060632ecb18267db1ce15dc0
|
data/CHANGELOG.md
CHANGED
@@ -4,8 +4,32 @@ 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.
|
7
|
+
## [0.10.1] - 2021-03-18
|
8
|
+
### Fixed
|
9
|
+
- Migration steps are now generated in a defined dependency order, so that--for example--indexes that depend
|
10
|
+
on columns are deleted first, before the columns themselves are deleted (since the latter implicitly does the former, which would break the migration when run).
|
11
|
+
- Related to the above, down migration steps are now always generated in exactly the reverse order of the up migration steps.
|
12
|
+
|
13
|
+
## [0.10.0] - 2021-03-17
|
14
|
+
### Deprecated
|
15
|
+
- Deprecated the `fields` DSL method in favor of `declare_schema`.
|
16
|
+
|
17
|
+
### Added
|
18
|
+
- Added the `declare_schema` method to replace `fields`. We now expect a column's type to come before the name
|
19
|
+
i.e. `declare schema { string :title }`. Otherwise, there is no difference between `fields` and `declare_schema`.
|
20
|
+
|
21
|
+
## [0.9.0] - 2021-03-01
|
22
|
+
### Added
|
23
|
+
- Added configurable default settings for `default_text_limit`, `default_string_limit`, `default_null`,
|
24
|
+
`default_generate_foreign_keys` and `default_generate_indexing` to allow developers to adhere to project conventions.
|
25
|
+
|
26
|
+
### Changed
|
27
|
+
- Moved and deprecated default settings for `default_charset` and `default_collation` from
|
28
|
+
`Generators::DeclareSchema::Migration::Migrator` to `::DeclareSchema`
|
29
|
+
|
30
|
+
## [0.8.0] - 2021-02-22
|
8
31
|
### Removed
|
32
|
+
- Removed assumption that primary key is named 'id'.
|
9
33
|
- Removed `sql_type` that was confusing because it was actually the same as `type` (ex: :string) and not
|
10
34
|
in fact the SQL type (ex: ``varchar(255)'`).
|
11
35
|
|
@@ -130,6 +154,9 @@ using the appropriate Rails configuration attributes.
|
|
130
154
|
### Added
|
131
155
|
- Initial version from https://github.com/Invoca/hobo_fields v4.1.0.
|
132
156
|
|
157
|
+
[0.10.1]: https://github.com/Invoca/declare_schema/compare/v0.10.0...v0.10.1
|
158
|
+
[0.10.0]: https://github.com/Invoca/declare_schema/compare/v0.9.0...v0.10.0
|
159
|
+
[0.9.0]: https://github.com/Invoca/declare_schema/compare/v0.8.0...v0.9.0
|
133
160
|
[0.8.0]: https://github.com/Invoca/declare_schema/compare/v0.7.1...v0.8.0
|
134
161
|
[0.7.1]: https://github.com/Invoca/declare_schema/compare/v0.7.0...v0.7.1
|
135
162
|
[0.7.0]: https://github.com/Invoca/declare_schema/compare/v0.6.3...v0.7.0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -70,18 +70,85 @@ DeclareSchema::Migration::Migrator.before_generating_migration do
|
|
70
70
|
end
|
71
71
|
```
|
72
72
|
|
73
|
-
|
74
|
-
|
73
|
+
### Global Configuration
|
74
|
+
Configurations can be set at the global level to customize default declaration for the following values:
|
75
75
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
tables and columns in the database. With `declare_schema` this can be configured
|
82
|
-
at three separate levels
|
76
|
+
#### Text Limit
|
77
|
+
The default text limit can be set using the `DeclareSchema.default_text_limit=` method.
|
78
|
+
Note that a `nil` default means that there is no default-- so every declaration must be explicit.
|
79
|
+
This will `raise` a `limit: must be provided for field :text...` error when the default value is `nil` and there is no explicit
|
80
|
+
declaration.
|
83
81
|
|
84
|
-
|
82
|
+
For example, adding the following to your `config/initializers` directory will
|
83
|
+
set the default `text limit` value to `0xffff`:
|
84
|
+
|
85
|
+
**declare_schema.rb**
|
86
|
+
```ruby
|
87
|
+
# frozen_string_literal: true
|
88
|
+
|
89
|
+
DeclareSchema.default_text_limit = 0xffff
|
90
|
+
```
|
91
|
+
|
92
|
+
#### String Limit
|
93
|
+
The default string limit can be set using the `DeclareSchema.default_string_limit=` method.
|
94
|
+
Note that a `nil` default means that there is no default-- so every declaration must be explicit.
|
95
|
+
This will `raise` a `limit: must be provided for field :string...` error when the default value is `nil` and there is no explicit
|
96
|
+
declaration.
|
97
|
+
|
98
|
+
For example, adding the following to your `config/initializers` directory will
|
99
|
+
set the default `string limit` value to `255`:
|
100
|
+
|
101
|
+
**declare_schema.rb**
|
102
|
+
```ruby
|
103
|
+
# frozen_string_literal: true
|
104
|
+
|
105
|
+
DeclareSchema.default_string_limit = 255
|
106
|
+
```
|
107
|
+
|
108
|
+
#### Null
|
109
|
+
The default null value can be set using the `DeclareSchema.default_null=` method.
|
110
|
+
Note that a `nil` default means that there is no default-- so every declaration must be explicit.
|
111
|
+
This will `raise` a `null: must be provided for field...` error when the default value is `nil` and there is no explicit
|
112
|
+
declaration.
|
113
|
+
|
114
|
+
For example, adding the following to your `config/initializers` directory will
|
115
|
+
set the default `null` value to `true`:
|
116
|
+
|
117
|
+
**declare_schema.rb**
|
118
|
+
```ruby
|
119
|
+
# frozen_string_literal: true
|
120
|
+
|
121
|
+
DeclareSchema.default_null = true
|
122
|
+
```
|
123
|
+
|
124
|
+
#### Generate Foreign Keys
|
125
|
+
The default value for generate foreign keys can be set using the `DeclareSchema.default_generate_foreign_keys=` method.
|
126
|
+
This value defaults to `true` and can only be set at the global level.
|
127
|
+
|
128
|
+
For example, adding the following to your `config/initializers` directory will set
|
129
|
+
the default `generate foreign keys` value to `false`:
|
130
|
+
|
131
|
+
**declare_schema.rb**
|
132
|
+
```ruby
|
133
|
+
# frozen_string_literal: true
|
134
|
+
|
135
|
+
DeclareSchema.default_generate_foreign_keys = false
|
136
|
+
```
|
137
|
+
|
138
|
+
#### Generate Indexing
|
139
|
+
The default value for generate indexing can be set using the `DeclareSchema.default_generate_indexing=` method.
|
140
|
+
This value defaults to `true` and can only be set at the global level.
|
141
|
+
|
142
|
+
For example, adding the following to your `config/initializers` directory will
|
143
|
+
set the default `generate indexing` value to `false`:
|
144
|
+
|
145
|
+
**declare_schema.rb**
|
146
|
+
```ruby
|
147
|
+
# frozen_string_literal: true
|
148
|
+
|
149
|
+
DeclareSchema.default_generate_indexing = false
|
150
|
+
```
|
151
|
+
#### Character Set and Collation
|
85
152
|
The character set and collation for all tables and fields can be set at the global level
|
86
153
|
using the `Generators::DeclareSchema::Migrator.default_charset=` and
|
87
154
|
`Generators::DeclareSchema::Migrator.default_collation=` configuration methods.
|
@@ -93,10 +160,21 @@ turn all tables into `utf8mb4` supporting tables:
|
|
93
160
|
```ruby
|
94
161
|
# frozen_string_literal: true
|
95
162
|
|
96
|
-
|
97
|
-
|
163
|
+
DeclareSchema.default_charset = "utf8mb4"
|
164
|
+
DeclareSchema.default_collation = "utf8mb4_bin"
|
98
165
|
```
|
99
166
|
|
167
|
+
## Declaring Character Set and Collation
|
168
|
+
_Note: This feature currently only works for MySQL database configurations._
|
169
|
+
|
170
|
+
MySQL originally supported UTF-8 in the range of 1-3 bytes (`mb3` or "multi-byte 3")
|
171
|
+
which covered the full set of Unicode code points at the time: U+0000 - U+FFFF.
|
172
|
+
But later, Unicode was extended beyond U+FFFF to make room for emojis, and with that
|
173
|
+
UTF-8 require 1-4 bytes (`mb4` or "multi-byte 4"). With this addition, there has
|
174
|
+
come a need to dynamically define the character set and collation for individual
|
175
|
+
tables and columns in the database. With `declare_schema` this can be configured
|
176
|
+
at three separate levels
|
177
|
+
|
100
178
|
### Table Configuration
|
101
179
|
In order to configure a table's default character set and collation, the `charset` and
|
102
180
|
`collation` arguments can be added to the `fields` block.
|
@@ -150,5 +228,5 @@ or add it to your `bundler` Gemfile:
|
|
150
228
|
To run tests:
|
151
229
|
```
|
152
230
|
rake test:prepare_testapp[force]
|
153
|
-
rake test:all
|
231
|
+
rake test:all
|
154
232
|
```
|
data/lib/declare_schema.rb
CHANGED
@@ -21,7 +21,18 @@ module DeclareSchema
|
|
21
21
|
text: String
|
22
22
|
}.freeze
|
23
23
|
|
24
|
+
@default_charset = "utf8mb4"
|
25
|
+
@default_collation = "utf8mb4_bin"
|
26
|
+
@default_text_limit = 0xffff_ffff
|
27
|
+
@default_string_limit = nil
|
28
|
+
@default_null = false
|
29
|
+
@default_generate_foreign_keys = true
|
30
|
+
@default_generate_indexing = true
|
31
|
+
|
24
32
|
class << self
|
33
|
+
attr_reader :default_charset, :default_collation, :default_text_limit, :default_string_limit, :default_null,
|
34
|
+
:default_generate_foreign_keys, :default_generate_indexing
|
35
|
+
|
25
36
|
def to_class(type)
|
26
37
|
case type
|
27
38
|
when Class
|
@@ -32,6 +43,41 @@ module DeclareSchema
|
|
32
43
|
raise ArgumentError, "expected Class or Symbol or String: got #{type.inspect}"
|
33
44
|
end
|
34
45
|
end
|
46
|
+
|
47
|
+
def default_charset=(charset)
|
48
|
+
charset.is_a?(String) or raise ArgumentError, "charset must be a string (got #{charset.inspect})"
|
49
|
+
@default_charset = charset
|
50
|
+
end
|
51
|
+
|
52
|
+
def default_collation=(collation)
|
53
|
+
collation.is_a?(String) or raise ArgumentError, "collation must be a string (got #{collation.inspect})"
|
54
|
+
@default_collation = collation
|
55
|
+
end
|
56
|
+
|
57
|
+
def default_text_limit=(text_limit)
|
58
|
+
text_limit.nil? or text_limit.is_a?(Integer) or raise ArgumentError, "text limit must be an integer or nil (got #{text_limit.inspect})"
|
59
|
+
@default_text_limit = text_limit
|
60
|
+
end
|
61
|
+
|
62
|
+
def default_string_limit=(string_limit)
|
63
|
+
string_limit.nil? or string_limit.is_a?(Integer) or raise ArgumentError, "string limit must be an integer or nil (got #{string_limit.inspect})"
|
64
|
+
@default_string_limit = string_limit
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_null=(null)
|
68
|
+
null.in?([true, false, nil]) or raise ArgumentError, "null must be either true, false, or nil (got #{null.inspect})"
|
69
|
+
@default_null = null
|
70
|
+
end
|
71
|
+
|
72
|
+
def default_generate_foreign_keys=(generate_foreign_keys)
|
73
|
+
generate_foreign_keys.in?([true, false]) or raise ArgumentError, "generate_foreign_keys must be either true or false (got #{generate_foreign_keys.inspect})"
|
74
|
+
@default_generate_foreign_keys = generate_foreign_keys
|
75
|
+
end
|
76
|
+
|
77
|
+
def default_generate_indexing=(generate_indexing)
|
78
|
+
generate_indexing.in?([true, false]) or raise ArgumentError, "generate_indexing must be either true or false (got #{generate_indexing.inspect})"
|
79
|
+
@default_generate_indexing = generate_indexing
|
80
|
+
end
|
35
81
|
end
|
36
82
|
end
|
37
83
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/proxy_object'
|
4
|
+
|
5
|
+
module DeclareSchema
|
6
|
+
class Dsl < BasicObject # avoid Object because that gets extended by lots of gems
|
7
|
+
include ::Kernel # but we need the basic class methods
|
8
|
+
|
9
|
+
instance_methods.each do |m|
|
10
|
+
unless m.to_s.starts_with?('__') || m.in?([:object_id, :instance_eval])
|
11
|
+
undef_method(m)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(model, options = {})
|
16
|
+
@model = model
|
17
|
+
@options = options
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :model
|
21
|
+
|
22
|
+
def timestamps
|
23
|
+
field(:created_at, :datetime, null: true)
|
24
|
+
field(:updated_at, :datetime, null: true)
|
25
|
+
end
|
26
|
+
|
27
|
+
def optimistic_lock
|
28
|
+
field(:lock_version, :integer, default: 1, null: false)
|
29
|
+
end
|
30
|
+
|
31
|
+
def field(name, type, *args, **options)
|
32
|
+
@model.declare_field(name, type, *(args + [@options.merge(options)]))
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(type, name, *args)
|
36
|
+
field(name, type, *args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,21 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'active_record'
|
4
|
+
require 'declare_schema/dsl'
|
4
5
|
require 'declare_schema/model'
|
5
6
|
require 'declare_schema/field_declaration_dsl'
|
6
7
|
|
7
8
|
module DeclareSchema
|
8
|
-
module
|
9
|
+
module Macros
|
9
10
|
def fields(table_options = {}, &block)
|
10
11
|
# Any model that calls 'fields' gets DeclareSchema::Model behavior
|
11
12
|
DeclareSchema::Model.mix_in(self)
|
12
13
|
|
13
|
-
# @include_in_migration = false #||= options.fetch(:include_in_migration, true); options.delete(:include_in_migration)
|
14
14
|
@include_in_migration = true
|
15
15
|
@table_options = table_options
|
16
16
|
|
17
17
|
if block
|
18
|
-
dsl = DeclareSchema::FieldDeclarationDsl.new(self
|
18
|
+
dsl = DeclareSchema::FieldDeclarationDsl.new(self)
|
19
|
+
if block.arity == 1
|
20
|
+
yield dsl
|
21
|
+
else
|
22
|
+
dsl.instance_eval(&block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
deprecate :fields, deprecator: ActiveSupport::Deprecation.new('1.0', 'DeclareSchema')
|
27
|
+
|
28
|
+
def declare_schema(table_options = {}, &block)
|
29
|
+
# Any model that calls 'fields' gets DeclareSchema::Model behavior
|
30
|
+
DeclareSchema::Model.mix_in(self)
|
31
|
+
|
32
|
+
# @include_in_migration = false #||= options.fetch(:include_in_migration, true); options.delete(:include_in_migration)
|
33
|
+
@include_in_migration = true # TODO: Add back or delete the include_in_migration feature
|
34
|
+
@table_options = table_options
|
35
|
+
|
36
|
+
if block
|
37
|
+
dsl = DeclareSchema::Dsl.new(self, null: false)
|
19
38
|
if block.arity == 1
|
20
39
|
yield dsl
|
21
40
|
else
|
@@ -26,4 +45,4 @@ module DeclareSchema
|
|
26
45
|
end
|
27
46
|
end
|
28
47
|
|
29
|
-
ActiveRecord::Base.singleton_class.prepend DeclareSchema::
|
48
|
+
ActiveRecord::Base.singleton_class.prepend DeclareSchema::Macros
|
data/lib/declare_schema/model.rb
CHANGED
@@ -38,24 +38,24 @@ 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
|
+
declare_schema do |f|
|
45
45
|
f.field(inheritance_column, :string, limit: 255, null: true)
|
46
46
|
end
|
47
47
|
index(inheritance_column)
|
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]
|