elasticsearch_record 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +22 -8
- data/docs/CHANGELOG.md +20 -1
- data/lib/active_record/connection_adapters/elasticsearch/column.rb +9 -2
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/clone_table_definition.rb +88 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/column_methods.rb +1 -1
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/create_table_definition.rb +29 -27
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb +67 -12
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_mapping_definition.rb +48 -13
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_meta_definition.rb +24 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_setting_definition.rb +9 -4
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/update_table_definition.rb +38 -13
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions.rb +3 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_dumper.rb +41 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_statements.rb +36 -10
- data/lib/active_record/connection_adapters/elasticsearch/table_statements.rb +102 -8
- data/lib/active_record/connection_adapters/elasticsearch_adapter.rb +17 -2
- data/lib/arel/collectors/elasticsearch_query.rb +3 -0
- data/lib/arel/visitors/elasticsearch_query.rb +1 -0
- data/lib/arel/visitors/elasticsearch_schema.rb +48 -7
- data/lib/elasticsearch_record/core.rb +24 -8
- data/lib/elasticsearch_record/gem_version.rb +1 -1
- data/lib/elasticsearch_record/model_schema.rb +26 -2
- data/lib/elasticsearch_record/persistence.rb +45 -34
- data/lib/elasticsearch_record/query.rb +4 -1
- data/lib/elasticsearch_record/schema_migration.rb +49 -0
- data/lib/elasticsearch_record/tasks/elasticsearch_database_tasks.rb +15 -5
- data/lib/elasticsearch_record.rb +1 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c479344b27eac6994fc17c6607f42221b093ddfc5f6db36b88994f25f2a0e56
|
4
|
+
data.tar.gz: 884ba24246d3ab9ef3500546bca84dcb3eaea184ac20bcfde6a2713e0a6def79
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 554ca0302d07210beef1f8bcb4b49f65b9e734122ccbbfb4a44d619d7697d1e5ec4b4164890beacaab4106654e5cdb7c817adf81d5953d46ed9f600b395e8018
|
7
|
+
data.tar.gz: 2a6a3579a00f2734c623f364a1eea5ba9802896a122c74ea4503764c63ad0294f16279b02cf3ce0f6a8d924ef3cb15004c2e2a933e90f22d311f4cbae067597c
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -240,20 +240,24 @@ total = scope.total
|
|
240
240
|
- index_base_name
|
241
241
|
- relay_id_attribute
|
242
242
|
|
243
|
-
### Useful model
|
243
|
+
### Useful model class methods
|
244
|
+
- auto_increment?
|
245
|
+
- max_result_window
|
244
246
|
- source_column_names
|
245
247
|
- searchable_column_names
|
246
248
|
- find_by_query
|
247
249
|
- msearch
|
248
250
|
|
249
|
-
## ActiveRecord ConnectionAdapters
|
251
|
+
## ActiveRecord ConnectionAdapters table-methods
|
250
252
|
Access these methods through the model's connection.
|
253
|
+
|
251
254
|
```ruby
|
252
255
|
# returns mapping of provided table (index)
|
253
256
|
model.connection.table_mappings('table-name')
|
254
257
|
```
|
255
258
|
|
256
259
|
- table_mappings
|
260
|
+
- table_metas
|
257
261
|
- table_settings
|
258
262
|
- table_aliases
|
259
263
|
- table_state
|
@@ -261,12 +265,14 @@ Access these methods through the model's connection.
|
|
261
265
|
- alias_exists?
|
262
266
|
- setting_exists?
|
263
267
|
- mapping_exists?
|
268
|
+
- meta_exists?
|
264
269
|
- max_result_window
|
265
270
|
- cluster_info
|
266
271
|
|
267
272
|
## Active Record Schema migration methods
|
268
273
|
Access these methods through the model's connection or within any `Migration`.
|
269
274
|
|
275
|
+
**cluster actions:**
|
270
276
|
- open_table
|
271
277
|
- open_tables
|
272
278
|
- close_table
|
@@ -274,8 +280,15 @@ Access these methods through the model's connection or within any `Migration`.
|
|
274
280
|
- truncate_table
|
275
281
|
- truncate_tables
|
276
282
|
- drop_table
|
283
|
+
- block_table
|
284
|
+
- unblock_table
|
285
|
+
- clone_table
|
277
286
|
- create_table
|
278
287
|
- change_table
|
288
|
+
|
289
|
+
**table actions:**
|
290
|
+
- change_meta
|
291
|
+
- delete_meta
|
279
292
|
- add_mapping
|
280
293
|
- change_mapping
|
281
294
|
- change_mapping_meta
|
@@ -299,11 +312,15 @@ class AddTests < ActiveRecord::Migration[7.0]
|
|
299
312
|
t.setting :number_of_shards, "1"
|
300
313
|
t.setting :number_of_replicas, 0
|
301
314
|
end
|
315
|
+
|
316
|
+
# changes the auto-increment value
|
317
|
+
change_meta "assignments", :auto_increment, 3625
|
302
318
|
|
303
319
|
create_table "settings", force: true do |t|
|
304
320
|
t.mapping :created_at, :date
|
305
|
-
t.mapping :key, :
|
321
|
+
t.mapping :key, :integer do |m|
|
306
322
|
m.primary_key = true
|
323
|
+
m.auto_increment = 10
|
307
324
|
end
|
308
325
|
t.mapping :status, :keyword
|
309
326
|
t.mapping :updated_at, :date
|
@@ -315,11 +332,11 @@ class AddTests < ActiveRecord::Migration[7.0]
|
|
315
332
|
end
|
316
333
|
|
317
334
|
add_mapping "settings", :active, :boolean do |m|
|
318
|
-
m.comment = "
|
335
|
+
m.comment = "Contains the active state"
|
319
336
|
end
|
320
337
|
|
321
338
|
change_table 'settings', force: true do |t|
|
322
|
-
t.add_setting(
|
339
|
+
t.add_setting("index.search.idle.after", "20s")
|
323
340
|
t.add_setting("index.shard.check_on_startup", true)
|
324
341
|
t.add_alias('supersettings')
|
325
342
|
end
|
@@ -337,9 +354,6 @@ class AddTests < ActiveRecord::Migration[7.0]
|
|
337
354
|
t.timestamps
|
338
355
|
end
|
339
356
|
|
340
|
-
change_mapping_meta "vintage", :number, auto_increment: 'true'
|
341
|
-
change_mapping_meta "vintage", :number, peter: 'hans'
|
342
|
-
|
343
357
|
change_mapping_attributes "vintage", :number, fields: {raw: {type: :keyword}}
|
344
358
|
end
|
345
359
|
|
data/docs/CHANGELOG.md
CHANGED
@@ -1,6 +1,25 @@
|
|
1
1
|
# ElasticsearchRecord - CHANGELOG
|
2
2
|
|
3
|
-
## [1.
|
3
|
+
## [1.2.0] - 2022-12-02
|
4
|
+
* [add] `ElasticsearchRecord::SchemaMigration` to fix connection-related differences (like table_name_prefix, table_name_suffix)
|
5
|
+
* [add] connection (config-related) 'table_name_prefix' & 'table_name_suffix' - now will be forwarded to all related models & schema-tables
|
6
|
+
* [add] `#block_table`, `#unblock_table`, `#clone_table`, `#table_metas`, `#meta_exists?`, `#change_meta`, `#delete_meta` methods for Elasticsearch ConnectionAdapter
|
7
|
+
* [add] `ElasticsearchRecord::Base.auto_increment?`
|
8
|
+
* [add] index 'meta' method to access the `_meta` mapping
|
9
|
+
* [add] `.ElasticsearchRecord::Base.relay_id_attribute` to relay a possible existing 'id'-attribute
|
10
|
+
* [add] new enabled attribute `enabled` - which defines 'searchable attributes & fields' and gets also read from the index-mappings
|
11
|
+
* [ref] insert a new record with primary_key & auto_increment through a wrapper `_insert_with_auto_increment`
|
12
|
+
* [ref] resolve `primary_keys` now from the index `_meta` mapping first (old mapping-related 'meta.primary_key:"true"' is still supported)
|
13
|
+
* [ref] disable 'strict' mode (= validation) of settings, alias, mappings as default (this can be still used with `strict: true`)
|
14
|
+
* [ref] silent unsupported methods 'create/drop' for `ElasticsearchRecord::Tasks::ElasticsearchDatabaseTasks`
|
15
|
+
* [ref] primary_key & auto_increment handling of custom defined mappings - now uses the index `_meta` mapping
|
16
|
+
* [fix] creating a record with different 'primary_key' fails with removed value (value no longer gets dropped)
|
17
|
+
* [fix] some index-settings not being ignored through `#transform_settings!`
|
18
|
+
* [fix] `ActiveRecord::ConnectionAdapters::Elasticsearch::SchemaDumper` dumping environment-related tables in the same database
|
19
|
+
* [fix] `ActiveRecord::ConnectionAdapters::Elasticsearch::TableMappingDefinition` fails with explicit assignable attributes (now uses ASSIGNABLE_ATTRIBUTES)
|
20
|
+
* [fix] tables with provided 'table_name_prefix' or 'table_name_suffix' not being ignored by the SchemaDumper
|
21
|
+
|
22
|
+
## [1.1.0] - 2022-12-01
|
4
23
|
* [add] support for schema dumps & migrations for Elasticsearch
|
5
24
|
* [add] `buckets` query/relation result method to resolve the buckets as key->value hash from aggregations
|
6
25
|
* [add] support for third-party gems (e.g. elasticsearch-dsl)
|
@@ -5,13 +5,14 @@ module ActiveRecord
|
|
5
5
|
module Elasticsearch
|
6
6
|
class Column < ConnectionAdapters::Column # :nodoc:
|
7
7
|
|
8
|
-
attr_reader :virtual, :fields, :properties, :meta
|
8
|
+
attr_reader :virtual, :fields, :properties, :meta, :enabled
|
9
9
|
|
10
|
-
def initialize(name, default, sql_type_metadata = nil, virtual: false, fields: nil, properties: nil, meta: nil, **kwargs)
|
10
|
+
def initialize(name, default, sql_type_metadata = nil, virtual: false, fields: nil, properties: nil, meta: nil, enabled: nil, **kwargs)
|
11
11
|
@virtual = virtual
|
12
12
|
@fields = fields.presence || []
|
13
13
|
@properties = properties.presence || []
|
14
14
|
@meta = meta.presence || {}
|
15
|
+
@enabled = enabled.nil? ? true : enabled
|
15
16
|
|
16
17
|
super(name, default, sql_type_metadata, true, nil, **kwargs)
|
17
18
|
end
|
@@ -21,6 +22,12 @@ module ActiveRecord
|
|
21
22
|
meta? && meta['comment']
|
22
23
|
end
|
23
24
|
|
25
|
+
# returns true if this column is enabled (= searchable by queries)
|
26
|
+
# @return [Boolean]
|
27
|
+
def enabled?
|
28
|
+
!!enabled
|
29
|
+
end
|
30
|
+
|
24
31
|
# returns true if this column is virtual.
|
25
32
|
# Virtual columns cannot be saved.
|
26
33
|
# @return [Boolean]
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_record/connection_adapters/elasticsearch/schema_definitions/table_definition'
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module ConnectionAdapters
|
7
|
+
module Elasticsearch
|
8
|
+
class CloneTableDefinition < TableDefinition
|
9
|
+
|
10
|
+
attr_reader :target
|
11
|
+
|
12
|
+
def initialize(conn, name, target, settings: nil, aliases: nil, **opts)
|
13
|
+
super(conn, name, **opts)
|
14
|
+
|
15
|
+
@target = target
|
16
|
+
@settings = HashWithIndifferentAccess.new
|
17
|
+
@aliases = HashWithIndifferentAccess.new
|
18
|
+
|
19
|
+
transform_settings!(settings) if settings.present?
|
20
|
+
transform_aliases!(aliases) if aliases.present?
|
21
|
+
end
|
22
|
+
|
23
|
+
# returns an array with all +TableSettingDefinition+.
|
24
|
+
# @return [Array]
|
25
|
+
def settings
|
26
|
+
@settings.values
|
27
|
+
end
|
28
|
+
|
29
|
+
# returns an array with all +TableAliasDefinition+.
|
30
|
+
# @return [Array]
|
31
|
+
def aliases
|
32
|
+
@aliases.values
|
33
|
+
end
|
34
|
+
|
35
|
+
######################
|
36
|
+
# DEFINITION METHODS #
|
37
|
+
######################
|
38
|
+
|
39
|
+
def setting(name, value, force: false, **options, &block)
|
40
|
+
raise ArgumentError, "you cannot define an already defined setting '#{name}'!" if @settings.key?(name) && !force?(force)
|
41
|
+
|
42
|
+
@settings[name] = new_setting_definition(name, value, **options, &block)
|
43
|
+
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def remove_setting(name)
|
48
|
+
@settings.delete name
|
49
|
+
end
|
50
|
+
|
51
|
+
# we can use +alias+ here, since the instance method is not a reserved keyword!
|
52
|
+
|
53
|
+
def alias(name, force: false, **options, &block)
|
54
|
+
raise ArgumentError, "you cannot define an already defined alias '#{name}'." if @aliases.key?(name) && !force?(force)
|
55
|
+
|
56
|
+
@aliases[name] = new_alias_definition(name, **options, &block)
|
57
|
+
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def remove_alias(name)
|
62
|
+
@aliases.delete name
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def _before_exec
|
68
|
+
block_table(self.name, :write)
|
69
|
+
end
|
70
|
+
|
71
|
+
def _after_exec
|
72
|
+
unblock_table(self.name, :write)
|
73
|
+
end
|
74
|
+
|
75
|
+
alias :_rescue_exec :_after_exec
|
76
|
+
|
77
|
+
def _exec
|
78
|
+
execute(schema_creation.accept(self), 'CLONE TABLE').dig('acknowledged')
|
79
|
+
end
|
80
|
+
|
81
|
+
# force empty states to prevent "Name is static for an open table" error.
|
82
|
+
def state
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/column_methods.rb
CHANGED
@@ -17,7 +17,7 @@ module ActiveRecord
|
|
17
17
|
# Appends a primary key definition to the table definition.
|
18
18
|
# Can be called multiple times, but this is probably not a good idea.
|
19
19
|
def primary_key(name, type = :primary_key, **options)
|
20
|
-
mapping(name, type, **options.merge(primary_key: true))
|
20
|
+
mapping(name, type, **options.merge(primary_key: true, auto_increment: true))
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -12,6 +12,7 @@ module ActiveRecord
|
|
12
12
|
@settings = HashWithIndifferentAccess.new
|
13
13
|
@mappings = HashWithIndifferentAccess.new
|
14
14
|
@aliases = HashWithIndifferentAccess.new
|
15
|
+
@metas = HashWithIndifferentAccess.new
|
15
16
|
|
16
17
|
transform_settings!(settings) if settings.present?
|
17
18
|
transform_mappings!(mappings) if mappings.present?
|
@@ -30,6 +31,12 @@ module ActiveRecord
|
|
30
31
|
@mappings.values
|
31
32
|
end
|
32
33
|
|
34
|
+
# returns an array with all +TableMetaDefinition+.
|
35
|
+
# @return [Array]
|
36
|
+
def metas
|
37
|
+
@metas.values
|
38
|
+
end
|
39
|
+
|
33
40
|
# provide backwards compatibility to columns
|
34
41
|
alias columns mappings
|
35
42
|
|
@@ -48,11 +55,32 @@ module ActiveRecord
|
|
48
55
|
# DEFINITION METHODS #
|
49
56
|
######################
|
50
57
|
|
58
|
+
# adds a new meta
|
59
|
+
def meta(name, value, force: false, **options)
|
60
|
+
raise ArgumentError, "you cannot define an already defined meta '#{name}'!" if @metas.key?(name) && !force?(force)
|
61
|
+
|
62
|
+
@metas[name] = new_meta_definition(name, value, **options)
|
63
|
+
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def remove_meta(name)
|
68
|
+
@metas.delete(name)
|
69
|
+
end
|
70
|
+
|
51
71
|
# adds a new mapping
|
52
72
|
def mapping(name, type, force: false, **options, &block)
|
53
73
|
raise ArgumentError, "you cannot define an already defined mapping '#{name}'!" if @mappings.key?(name) && !force?(force)
|
54
74
|
|
55
|
-
|
75
|
+
mapping = new_mapping_definition(name, type, **options, &block)
|
76
|
+
@mappings[name] = mapping
|
77
|
+
|
78
|
+
|
79
|
+
# check if the mapping is assigned as primary_key
|
80
|
+
if mapping.primary_key?
|
81
|
+
meta :primary_key, mapping.name
|
82
|
+
meta(:auto_increment, mapping.auto_increment) if mapping.auto_increment?
|
83
|
+
end
|
56
84
|
|
57
85
|
self
|
58
86
|
end
|
@@ -126,32 +154,6 @@ module ActiveRecord
|
|
126
154
|
def state
|
127
155
|
nil
|
128
156
|
end
|
129
|
-
|
130
|
-
def transform_mappings!(mappings)
|
131
|
-
return unless mappings['properties'].present?
|
132
|
-
|
133
|
-
mappings['properties'].each do |name, attributes|
|
134
|
-
self.mapping(name, attributes.delete('type'), **attributes)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def transform_settings!(settings)
|
139
|
-
# exclude settings, that are provided through the API but are not part of the index-settings
|
140
|
-
settings
|
141
|
-
.with_indifferent_access
|
142
|
-
.each { |name, value|
|
143
|
-
# don't transform ignored names
|
144
|
-
next if ActiveRecord::ConnectionAdapters::Elasticsearch::TableSettingDefinition.match_ignore_names?(name)
|
145
|
-
|
146
|
-
self.setting(name, value)
|
147
|
-
}
|
148
|
-
end
|
149
|
-
|
150
|
-
def transform_aliases!(aliases)
|
151
|
-
aliases.each do |name, attributes|
|
152
|
-
self.alias(name, **attributes)
|
153
|
-
end
|
154
|
-
end
|
155
157
|
end
|
156
158
|
end
|
157
159
|
end
|
data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb
CHANGED
@@ -10,16 +10,19 @@ module ActiveRecord
|
|
10
10
|
class TableDefinition
|
11
11
|
include ColumnMethods
|
12
12
|
|
13
|
-
delegate :execute, :schema_creation,
|
13
|
+
delegate :execute, :schema_creation,
|
14
|
+
:column_exists?, :mapping_exists?, :meta_exists?, :setting_exists?, :alias_exists?,
|
15
|
+
:close_table, :open_table, :block_table, :unblock_table,
|
16
|
+
:table_mappings, :table_metas, :table_settings, to: :conn
|
14
17
|
|
15
18
|
attr_reader :conn
|
16
19
|
attr_reader :name
|
17
20
|
attr_reader :opts
|
18
21
|
|
19
22
|
def initialize(conn, name, **opts)
|
20
|
-
@conn
|
21
|
-
@name
|
22
|
-
@opts
|
23
|
+
@conn = conn
|
24
|
+
@name = name
|
25
|
+
@opts = opts
|
23
26
|
@failed = false
|
24
27
|
end
|
25
28
|
|
@@ -33,10 +36,11 @@ module ActiveRecord
|
|
33
36
|
yield self
|
34
37
|
rescue => e
|
35
38
|
@failed = false
|
39
|
+
_rescue_assign
|
36
40
|
raise e
|
37
|
-
ensure
|
38
|
-
_after_assign
|
39
41
|
end
|
42
|
+
|
43
|
+
_after_assign
|
40
44
|
end
|
41
45
|
|
42
46
|
def exec!
|
@@ -47,10 +51,11 @@ module ActiveRecord
|
|
47
51
|
_exec
|
48
52
|
rescue => e
|
49
53
|
@failed = false
|
54
|
+
_rescue_exec
|
50
55
|
raise e
|
51
|
-
ensure
|
52
|
-
_after_exec
|
53
56
|
end
|
57
|
+
|
58
|
+
_after_exec
|
54
59
|
end
|
55
60
|
|
56
61
|
def failed?
|
@@ -67,6 +72,10 @@ module ActiveRecord
|
|
67
72
|
true
|
68
73
|
end
|
69
74
|
|
75
|
+
def _rescue_assign
|
76
|
+
true
|
77
|
+
end
|
78
|
+
|
70
79
|
def _before_exec
|
71
80
|
true
|
72
81
|
end
|
@@ -75,11 +84,23 @@ module ActiveRecord
|
|
75
84
|
true
|
76
85
|
end
|
77
86
|
|
87
|
+
def _rescue_exec
|
88
|
+
true
|
89
|
+
end
|
90
|
+
|
78
91
|
def _exec
|
79
92
|
raise ArgumentError, "you cannot execute a TableDefinition directly - use 'CreateTableDefinition' or 'UpdateTableDefinition' instead!"
|
80
93
|
end
|
81
94
|
|
82
|
-
def
|
95
|
+
def new_meta_definition(name, value, strict: false, **)
|
96
|
+
meta = TableMetaDefinition.new(name, value)
|
97
|
+
|
98
|
+
raise ArgumentError, "you cannot define an invalid meta '#{name}' (#{meta.error_messages})!" if strict?(strict) && !meta.valid?
|
99
|
+
|
100
|
+
meta
|
101
|
+
end
|
102
|
+
|
103
|
+
def new_mapping_definition(name, type, strict: false, **attributes, &block)
|
83
104
|
mapping = TableMappingDefinition.new(name, type, attributes)
|
84
105
|
block.call(mapping) if block_given?
|
85
106
|
|
@@ -90,7 +111,7 @@ module ActiveRecord
|
|
90
111
|
|
91
112
|
alias :new_column_definition :new_mapping_definition
|
92
113
|
|
93
|
-
def new_alias_definition(name, strict:
|
114
|
+
def new_alias_definition(name, strict: false, **attributes, &block)
|
94
115
|
# create new alias
|
95
116
|
tbl_alias = TableAliasDefinition.new(name, attributes)
|
96
117
|
block.call(tbl_alias) if block_given?
|
@@ -100,7 +121,7 @@ module ActiveRecord
|
|
100
121
|
tbl_alias
|
101
122
|
end
|
102
123
|
|
103
|
-
def new_setting_definition(name, value, strict:
|
124
|
+
def new_setting_definition(name, value, strict: false, **, &block)
|
104
125
|
# create new setting
|
105
126
|
setting = TableSettingDefinition.new(name, value).with_state(state)
|
106
127
|
block.call(setting) if block_given?
|
@@ -124,7 +145,41 @@ module ActiveRecord
|
|
124
145
|
end
|
125
146
|
|
126
147
|
def strict?(strict = nil)
|
127
|
-
opts.fetch(:strict,
|
148
|
+
opts.fetch(:strict, false) || strict
|
149
|
+
end
|
150
|
+
|
151
|
+
def transform_mappings!(mappings)
|
152
|
+
# transform +_meta+ mappings
|
153
|
+
if mappings['_meta'].present?
|
154
|
+
mappings['_meta'].each do |name, value|
|
155
|
+
self.meta(name, value)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# transform properties (=columns)
|
160
|
+
if mappings['properties'].present?
|
161
|
+
mappings['properties'].each do |name, attributes|
|
162
|
+
self.mapping(name, attributes.delete('type'), **attributes)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def transform_settings!(settings)
|
168
|
+
# exclude settings, that are provided through the API but are not part of the index-settings
|
169
|
+
settings
|
170
|
+
.with_indifferent_access
|
171
|
+
.each { |name, value|
|
172
|
+
# don't transform ignored names
|
173
|
+
next if ActiveRecord::ConnectionAdapters::Elasticsearch::TableSettingDefinition.match_ignore_names?(name)
|
174
|
+
|
175
|
+
self.setting(name, value)
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
def transform_aliases!(aliases)
|
180
|
+
aliases.each do |name, attributes|
|
181
|
+
self.alias(name, **attributes)
|
182
|
+
end
|
128
183
|
end
|
129
184
|
end
|
130
185
|
end
|
@@ -16,6 +16,9 @@ module ActiveRecord
|
|
16
16
|
:index_prefixes, :index, :meta, :normalizer, :norms, :null_value, :position_increment_gap,
|
17
17
|
:properties, :search_analyzer, :similarity, :subobjects, :store, :term_vector].freeze
|
18
18
|
|
19
|
+
# define virtual attributes, that must be assigned due a special logic
|
20
|
+
ASSIGNABLE_ATTRIBUTES = [:comment, :primary_key, :auto_increment, :meta].freeze
|
21
|
+
|
19
22
|
build_attribute_methods! *ATTRIBUTES
|
20
23
|
|
21
24
|
# attributes
|
@@ -27,10 +30,7 @@ module ActiveRecord
|
|
27
30
|
validates_presence_of :name
|
28
31
|
validates_presence_of :type
|
29
32
|
validates_inclusion_of :__attributes_keys, in: ATTRIBUTES, allow_blank: true
|
30
|
-
|
31
|
-
# disable validation for meta attribute - maybe future updates of Elasticsearch have other restrictions.
|
32
|
-
# To not be hooked on those possible changes we
|
33
|
-
#validate :_validate_meta
|
33
|
+
validate :_validate_meta
|
34
34
|
|
35
35
|
# sets the default value (alias for null_value)
|
36
36
|
alias_method :default=, :null_value=
|
@@ -41,32 +41,62 @@ module ActiveRecord
|
|
41
41
|
####################
|
42
42
|
|
43
43
|
def initialize(name, type, attributes)
|
44
|
-
@name
|
45
|
-
|
44
|
+
@name = name.to_sym
|
45
|
+
|
46
|
+
attributes = attributes.symbolize_keys
|
47
|
+
# directly set attributes, that cannot be assigned
|
48
|
+
@attributes = attributes.except(*ASSIGNABLE_ATTRIBUTES)
|
49
|
+
# assign special attributes
|
50
|
+
__assign(attributes.slice(*ASSIGNABLE_ATTRIBUTES))
|
46
51
|
|
47
52
|
@type = _resolve_type(type)
|
48
53
|
end
|
49
54
|
|
50
|
-
#
|
55
|
+
# returns the +comment+ from 'meta' attribute
|
56
|
+
# @return [String, nil]
|
51
57
|
def comment
|
52
58
|
__get_nested(:meta, :comment)
|
53
59
|
end
|
54
60
|
|
61
|
+
# sets the +comment+ as 'meta' attribute
|
62
|
+
# @param [String] value
|
55
63
|
def comment=(value)
|
56
64
|
# important: meta-values can only be strings!
|
57
65
|
__set_nested(:meta, :comment, value.to_s)
|
58
66
|
end
|
59
67
|
|
68
|
+
# returns true if the +primary_key+ 'attribute' was provided
|
69
|
+
# @return [Boolean]
|
60
70
|
def primary_key
|
61
|
-
|
71
|
+
!!_lazy_attributes[:primary_key]
|
62
72
|
end
|
63
73
|
|
64
74
|
alias_method :primary_key?, :primary_key
|
65
75
|
|
66
|
-
#
|
76
|
+
# sets the +primary_key+ as 'lazy_attribute'
|
77
|
+
# @param [Boolean] value
|
67
78
|
def primary_key=(value)
|
68
|
-
|
69
|
-
|
79
|
+
_lazy_attributes[:primary_key] = value
|
80
|
+
end
|
81
|
+
|
82
|
+
# returns the +auto_increment+ value, if provided
|
83
|
+
# @return [Integer]
|
84
|
+
def auto_increment
|
85
|
+
return nil unless _lazy_attributes[:auto_increment]
|
86
|
+
return 0 if _lazy_attributes[:auto_increment] == true
|
87
|
+
_lazy_attributes[:auto_increment].to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
# returns true if the +auto_increment+ 'attribute' was provided
|
91
|
+
# @return [Boolean]
|
92
|
+
def auto_increment?
|
93
|
+
!!auto_increment
|
94
|
+
end
|
95
|
+
|
96
|
+
# sets the +auto_increment+ as 'lazy_attribute'
|
97
|
+
# @param [Boolean, Integer] value
|
98
|
+
def auto_increment=(value)
|
99
|
+
_lazy_attributes[:auto_increment] = value
|
70
100
|
end
|
71
101
|
|
72
102
|
def meta=(value)
|
@@ -79,6 +109,11 @@ module ActiveRecord
|
|
79
109
|
|
80
110
|
private
|
81
111
|
|
112
|
+
# non persistent attributes
|
113
|
+
def _lazy_attributes
|
114
|
+
@_lazy_attributes ||= {}
|
115
|
+
end
|
116
|
+
|
82
117
|
# resolves the provided type.
|
83
118
|
# prevents to set a nil type (sets +:object+ or +:nested+ - depends on existing properties)
|
84
119
|
# @return [Symbol, nil]
|
@@ -99,8 +134,8 @@ module ActiveRecord
|
|
99
134
|
return invalid!("'meta' is not supported on object or nested types", :attributes) if [:object, :nested].include?(type)
|
100
135
|
|
101
136
|
# allow only strings
|
102
|
-
|
103
|
-
return invalid!("'meta' has a key '#{
|
137
|
+
failed_key = meta.keys.detect { |key| !meta[key].is_a?(String) }
|
138
|
+
return invalid!("'meta' has a key '#{failed_key}' with a none string value", :attributes) if failed_key.present?
|
104
139
|
|
105
140
|
true
|
106
141
|
end
|
data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_meta_definition.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_model/validations'
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module ConnectionAdapters
|
7
|
+
module Elasticsearch
|
8
|
+
class TableMetaDefinition
|
9
|
+
include ActiveModel::Validations
|
10
|
+
|
11
|
+
# attributes
|
12
|
+
attr_accessor :name
|
13
|
+
attr_accessor :value
|
14
|
+
|
15
|
+
validates_presence_of :name
|
16
|
+
|
17
|
+
def initialize(name, value)
|
18
|
+
@name = name.to_sym
|
19
|
+
@value = value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|