elasticsearch_record 1.8.2 → 3.0.0
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/.rspec +0 -0
- data/.yardopts +0 -0
- data/Gemfile +7 -0
- data/README.md +177 -19
- data/Rakefile +0 -0
- data/docs/CHANGELOG.md +66 -0
- data/docs/CODE_OF_CONDUCT.md +0 -0
- data/docs/LICENSE +0 -0
- data/elasticsearch_record.gemspec +3 -3
- data/lib/active_record/connection_adapters/elasticsearch/column.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/database_statements.rb +19 -17
- data/lib/active_record/connection_adapters/elasticsearch/quoting.rb +16 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_creation.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/attribute_methods.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/clone_table_definition.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/create_table_definition.rb +6 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_alias_definition.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_meta_definition.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_setting_definition.rb +7 -5
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/update_table_definition.rb +3 -1
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_dumper.rb +24 -3
- data/lib/active_record/connection_adapters/elasticsearch/schema_statements.rb +39 -34
- data/lib/active_record/connection_adapters/elasticsearch/table_statements.rb +251 -72
- data/lib/active_record/connection_adapters/elasticsearch/transactions.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/type/format_string.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/type/multicast_value.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/type/nested.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/type/object.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/type/range.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/type.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch/unsupported_implementation.rb +0 -0
- data/lib/active_record/connection_adapters/elasticsearch_adapter.rb +164 -99
- data/lib/arel/collectors/elasticsearch_query.rb +3 -0
- data/lib/arel/nodes/select_agg.rb +0 -0
- data/lib/arel/nodes/select_configure.rb +0 -0
- data/lib/arel/nodes/select_kind.rb +0 -0
- data/lib/arel/nodes/select_query.rb +0 -0
- data/lib/arel/visitors/elasticsearch.rb +0 -0
- data/lib/arel/visitors/elasticsearch_query.rb +51 -9
- data/lib/elasticsearch_record/base.rb +0 -0
- data/lib/elasticsearch_record/core.rb +1 -1
- data/lib/elasticsearch_record/errors.rb +0 -0
- data/lib/elasticsearch_record/extensions/relation.rb +0 -0
- data/lib/elasticsearch_record/gem_version.rb +3 -3
- data/lib/elasticsearch_record/instrumentation/controller_runtime.rb +0 -0
- data/lib/elasticsearch_record/instrumentation/log_subscriber.rb +11 -9
- data/lib/elasticsearch_record/instrumentation/railtie.rb +0 -0
- data/lib/elasticsearch_record/instrumentation.rb +0 -0
- data/lib/elasticsearch_record/internal_metadata.rb +19 -0
- data/lib/elasticsearch_record/model_api.rb +8 -5
- data/lib/elasticsearch_record/model_schema.rb +1 -1
- data/lib/elasticsearch_record/patches/active_record/connection_pool_patch.rb +57 -0
- data/lib/elasticsearch_record/patches/active_record/relation_merger_patch.rb +0 -0
- data/lib/elasticsearch_record/patches/arel/select_core_patch.rb +0 -0
- data/lib/elasticsearch_record/patches/arel/select_manager_patch.rb +0 -0
- data/lib/elasticsearch_record/patches/arel/select_statement_patch.rb +0 -0
- data/lib/elasticsearch_record/patches/arel/update_manager_patch.rb +0 -0
- data/lib/elasticsearch_record/patches/arel/update_statement_patch.rb +0 -0
- data/lib/elasticsearch_record/persistence.rb +39 -21
- data/lib/elasticsearch_record/query.rb +53 -33
- data/lib/elasticsearch_record/querying.rb +43 -21
- data/lib/elasticsearch_record/relation/calculation_methods.rb +38 -2
- data/lib/elasticsearch_record/relation/core_methods.rb +1 -1
- data/lib/elasticsearch_record/relation/query_clause.rb +0 -0
- data/lib/elasticsearch_record/relation/query_clause_tree.rb +2 -1
- data/lib/elasticsearch_record/relation/query_methods.rb +31 -1
- data/lib/elasticsearch_record/relation/result_methods.rb +47 -43
- data/lib/elasticsearch_record/relation/value_methods.rb +4 -4
- data/lib/elasticsearch_record/result.rb +144 -60
- data/lib/elasticsearch_record/schema_migration.rb +5 -2
- data/lib/elasticsearch_record/statement_cache.rb +0 -0
- data/lib/elasticsearch_record/tasks/elasticsearch_database_tasks.rb +0 -0
- data/lib/elasticsearch_record/version.rb +0 -0
- data/lib/elasticsearch_record.rb +17 -0
- metadata +22 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: df21aa38516f4e56830e16ffcff4164b65541a869e3964771771eacdf4e8ad16
|
|
4
|
+
data.tar.gz: 7ba579e28c1a85e7f890654c99c675eb60dd2fddf1b1eb877b0967e17f1d7097
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cb521dc265ec3a517ebda7b8b6e60b5471b1411bd8f04d6be72098e95177e32af06267bc9a2e2881699d0f7f317c3bf1ef77b6613d9657df6ac7347affa80cf9
|
|
7
|
+
data.tar.gz: 981b0955f21d2260d794cc1946ed560fa70d0e429b5c0bc97d2c9c5b29b396af471cd8d6460929fa451913ad44f7d9992c9b8c0d8a6cd6a7035c338147161138
|
data/.rspec
CHANGED
|
File without changes
|
data/.yardopts
CHANGED
|
File without changes
|
data/Gemfile
CHANGED
|
@@ -4,3 +4,10 @@ source "https://rubygems.org"
|
|
|
4
4
|
|
|
5
5
|
# Specify your gem's dependencies in elasticsearch_record.gemspec
|
|
6
6
|
gemspec
|
|
7
|
+
|
|
8
|
+
# Pin the Elasticsearch client to the 8.x line for local development & specs.
|
|
9
|
+
# The gemspec intentionally allows '>= 7.17', but the 9.x client sends an
|
|
10
|
+
# 'Accept: application/vnd.elasticsearch+json; compatible-with=9' header that
|
|
11
|
+
# 8.x servers reject with a media_type_header_exception (HTTP 400).
|
|
12
|
+
# Keep this in sync with the server you develop against.
|
|
13
|
+
gem 'elasticsearch', '~> 8.0'
|
data/README.md
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
[](https://badge.fury.io/rb/elasticsearch_record)
|
|
7
7
|
[](docs/LICENSE)
|
|
8
8
|
|
|
9
|
+
[](https://coveralls.io/github/ruby-smart/elasticsearch_record?branch=main)
|
|
10
|
+
|
|
9
11
|
ActiveRecord adapter for Elasticsearch
|
|
10
12
|
|
|
11
13
|
_ElasticsearchRecord is a ActiveRecord adapter and provides similar functionality for Elasticsearch._
|
|
@@ -14,10 +16,11 @@ _ElasticsearchRecord is a ActiveRecord adapter and provides similar functionalit
|
|
|
14
16
|
|
|
15
17
|
**PLEASE NOTE:**
|
|
16
18
|
|
|
17
|
-
- This is the `main`-branch, which
|
|
18
|
-
- supports ActiveRecord ~> 7.
|
|
19
|
-
- added features up to Elasticsearch `8.
|
|
20
|
-
-
|
|
19
|
+
- This is the `main`-branch, which supports rails **7.2** _(see section 'Rails_Versions' for supported versions)_
|
|
20
|
+
- supports ActiveRecord ~> 7.2 + Elasticsearch >= 7.17
|
|
21
|
+
- added features up to Elasticsearch `8.17.1` _(tested against `8.19.14`)_
|
|
22
|
+
- _ES|QL_ queries _(`TYPE_ESQL` / the `esql.query` gate)_ require **Elasticsearch >= 8.11**, where the feature became
|
|
23
|
+
generally available. All other features remain available from Elasticsearch `7.17`.
|
|
21
24
|
|
|
22
25
|
-----
|
|
23
26
|
|
|
@@ -25,6 +28,13 @@ _ElasticsearchRecord is a ActiveRecord adapter and provides similar functionalit
|
|
|
25
28
|
|
|
26
29
|
Supported rails versions:
|
|
27
30
|
|
|
31
|
+
### Rails 7.2:
|
|
32
|
+
_(since gem version 2.1)_
|
|
33
|
+
|
|
34
|
+
https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-2-stable
|
|
35
|
+
|
|
36
|
+
[](https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-2-stable)
|
|
37
|
+
|
|
28
38
|
### Rails 7.1:
|
|
29
39
|
_(since gem version 1.8)_
|
|
30
40
|
|
|
@@ -46,11 +56,11 @@ https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-0-stable
|
|
|
46
56
|
Add this line to your application's Gemfile:
|
|
47
57
|
|
|
48
58
|
```ruby
|
|
49
|
-
gem 'elasticsearch_record'
|
|
59
|
+
gem 'elasticsearch_record'
|
|
50
60
|
|
|
51
61
|
# alternative
|
|
52
62
|
gem 'elasticsearch_record', git: 'https://github.com/ruby-smart/elasticsearch_record', branch: 'rails-7-1-stable'
|
|
53
|
-
gem 'elasticsearch_record', git: 'https://github.com/ruby-smart/elasticsearch_record', branch: 'rails-
|
|
63
|
+
gem 'elasticsearch_record', git: 'https://github.com/ruby-smart/elasticsearch_record', branch: 'rails-7-0-stable'
|
|
54
64
|
|
|
55
65
|
```
|
|
56
66
|
|
|
@@ -62,6 +72,78 @@ Or install it yourself as:
|
|
|
62
72
|
|
|
63
73
|
$ gem install elasticsearch_record
|
|
64
74
|
|
|
75
|
+
-----
|
|
76
|
+
|
|
77
|
+
## Upgrading to 2.0
|
|
78
|
+
|
|
79
|
+
Version **2.0** contains breaking changes. Coming from **1.8.x**, check the following:
|
|
80
|
+
|
|
81
|
+
### 1. Table (index) names are resolved by default
|
|
82
|
+
|
|
83
|
+
Every table statement now resolves its name through `#_env_table_name`, so the
|
|
84
|
+
`table_name_prefix` / `table_name_suffix` no longer have to be applied by hand in migrations or database statements
|
|
85
|
+
_(which silently wrote into another environment's index)_.
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
# 1.8.x - the prefix / suffix had to be applied manually
|
|
89
|
+
drop_table _env_table_name("settings")
|
|
90
|
+
|
|
91
|
+
# 2.0 - resolved on its own
|
|
92
|
+
drop_table "settings"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Existing migrations keep working - `_env_table_name` is idempotent and still public, so a
|
|
96
|
+
hand-resolved name resolves to the very same index. A new `decorate:`-argument opts out per
|
|
97
|
+
call, and `ElasticsearchRecord.decorate_table_names` acts as a global kill-switch.
|
|
98
|
+
|
|
99
|
+
_see @ [environment-related-table-name](#environment-related-table-name), [opting out with `decorate: false`](#opting-out-with-decorate-false) & [global kill-switch](#global-kill-switch)_
|
|
100
|
+
|
|
101
|
+
### 2. `select` raises on metadata fields
|
|
102
|
+
|
|
103
|
+
Metadata fields _(`_id`, `_score`, `_index`, ...)_ are not part of the `_source` node, so they
|
|
104
|
+
could never be resolved through the `_source`-filter this method builds - providing them
|
|
105
|
+
silently created a filter that never matched.
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
Search.select(:_id)
|
|
109
|
+
# => ActiveRecord::UnknownAttributeReference
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
They are returned anyway and accessible on each record _(`Search.first._id`)_. To resolve the
|
|
113
|
+
metadata **without** transferring the `_source`, use the new `#meta_only!` method.
|
|
114
|
+
|
|
115
|
+
### 3. `restore_table` replaces its `open:`-argument with `unblock:`
|
|
116
|
+
|
|
117
|
+
A restore runs through a `clone`, so the restored table **inherits** the 'write'-block of its
|
|
118
|
+
source - the table was open, but read-only. `unblock:` _(default: `true`)_ releases it again.
|
|
119
|
+
`ModelApi#restore!` follows along.
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
# 1.8.x
|
|
123
|
+
restore_table 'settings', from: 'settings-snapshot-2024', open: true
|
|
124
|
+
|
|
125
|
+
# 2.0
|
|
126
|
+
restore_table 'settings', from: 'settings-snapshot-2024', unblock: true
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 4. The plural table statements no longer skip AR-internal indices
|
|
130
|
+
|
|
131
|
+
`#open_tables`, `#close_tables`, `#refresh_tables` & `#truncate_tables` no longer subtract the
|
|
132
|
+
ActiveRecord-internal indices _(`schema_migrations` & `ar_internal_metadata`)_ - an explicitly
|
|
133
|
+
named index was silently dropped from the list. They now return an `Array` with an entry for
|
|
134
|
+
**every** provided name.
|
|
135
|
+
|
|
136
|
+
### 5. `truncate_table` raises for AR-internal indices
|
|
137
|
+
|
|
138
|
+
The statement runs a `drop` & `create` and would wipe the migration state.
|
|
139
|
+
`#drop_table` stays unguarded by design _(ActiveRecord resets both tables through it)_.
|
|
140
|
+
|
|
141
|
+
### 6. `esql` & `msearch` dropped their `async:`-argument
|
|
142
|
+
|
|
143
|
+
Both dispatch through the public `exec_query` now, since rails 7.1 made `internal_exec_query`
|
|
144
|
+
private - the `async:`-argument was dropped along with it.
|
|
145
|
+
|
|
146
|
+
-----
|
|
65
147
|
|
|
66
148
|
## Features
|
|
67
149
|
* ActiveRecord's `create, read, update & delete` behaviours
|
|
@@ -71,6 +153,8 @@ Or install it yourself as:
|
|
|
71
153
|
* additional relation methods to find records with `filter, must, must_not, should`
|
|
72
154
|
* aggregated queries with Elasticsearch `aggregation` methods
|
|
73
155
|
* resolve search response `hits`, `aggregations`, `buckets`, ... instead of ActiveRecord objects
|
|
156
|
+
* `SQL` & `ES|QL` queries resolve their **tabular** response into records _(`find_by_sql` with a String query, `find_by_esql`)_
|
|
157
|
+
* table (index) names are resolved within the current environment _(`table_name_prefix` / `table_name_suffix`)_
|
|
74
158
|
* Third-party gem support
|
|
75
159
|
* access `elasticsearch-dsl` query builder through `model.search{ ... }`
|
|
76
160
|
* Schema
|
|
@@ -254,6 +338,11 @@ buckets = Search.where(name: 'A nice object').aggregate(:total, {sum: {field: :a
|
|
|
254
338
|
results = Search.where(name: 'A nice object').pit_results
|
|
255
339
|
# > [{ "_id": "abc123", "name": "A nice object", ...
|
|
256
340
|
|
|
341
|
+
# resolves ONLY the metadata nodes of each hit - the '_source' is not transferred at all.
|
|
342
|
+
# (this is the replacement for a - no longer supported - 'select(:_id)')
|
|
343
|
+
metas = Search.where(name: 'A nice object').meta_only!.results
|
|
344
|
+
# > [{ "_id": "abc123", "_index": "search", "_score": 1.0 }, ...
|
|
345
|
+
|
|
257
346
|
# returns the total value of the query without querying again (it uses the total value from the response)
|
|
258
347
|
scope = Search.where(name: 'A nice object').limit(5)
|
|
259
348
|
results_count = scope.count
|
|
@@ -287,10 +376,7 @@ _(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/ma
|
|
|
287
376
|
- must
|
|
288
377
|
- should
|
|
289
378
|
- aggregate
|
|
290
|
-
-
|
|
291
|
-
- hits_only!
|
|
292
|
-
- aggs_only!
|
|
293
|
-
- total_only!
|
|
379
|
+
- select _(raises on metadata fields - see @ [Upgrading to 2.0](#2-select-raises-on-metadata-fields))_
|
|
294
380
|
|
|
295
381
|
_see simple documentation about these methods @ {ElasticsearchRecord::Relation::QueryMethods rubydoc}_
|
|
296
382
|
|
|
@@ -307,7 +393,7 @@ _(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/ma
|
|
|
307
393
|
- boxplot
|
|
308
394
|
- stats
|
|
309
395
|
- string_stats
|
|
310
|
-
- matrix_stats
|
|
396
|
+
- matrix_stats _(requires at least two columns)_
|
|
311
397
|
- median_absolute_deviation
|
|
312
398
|
- calculate
|
|
313
399
|
|
|
@@ -315,6 +401,13 @@ _see simple documentation about these methods @ {ElasticsearchRecord::Relation::
|
|
|
315
401
|
|
|
316
402
|
_(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/main/lib/elasticsearch_record/relation/calculation_methods.rb) )_
|
|
317
403
|
|
|
404
|
+
### Available query configuration methods
|
|
405
|
+
|
|
406
|
+
- hits_only! _(prevents to resolve aggs)_
|
|
407
|
+
- aggs_only! _(prevents to resolve hits / source data)_
|
|
408
|
+
- total_only! _(prevents to resolve aggs, hits / source data)_
|
|
409
|
+
- meta_only! _(resolves the metadata nodes (`_id`, `_score`, ...) of each hit without transferring the `_source`)_
|
|
410
|
+
|
|
318
411
|
### Available result methods
|
|
319
412
|
- aggregations
|
|
320
413
|
- buckets
|
|
@@ -543,7 +636,7 @@ Access these methods through the model's connection or within any `Migration`.
|
|
|
543
636
|
**Example migration:**
|
|
544
637
|
|
|
545
638
|
```ruby
|
|
546
|
-
class AddTests < ActiveRecord::Migration[7.
|
|
639
|
+
class AddTests < ActiveRecord::Migration[7.1]
|
|
547
640
|
def up
|
|
548
641
|
create_table "assignments", if_not_exists: true do |t|
|
|
549
642
|
t.string :key, primary_key: true
|
|
@@ -616,17 +709,29 @@ end
|
|
|
616
709
|
```
|
|
617
710
|
|
|
618
711
|
## environment-related-table-name:
|
|
619
|
-
|
|
620
|
-
|
|
712
|
+
Table (index) names are resolved within the current environment, even if the environments share the
|
|
713
|
+
same cluster ...
|
|
621
714
|
|
|
622
715
|
This can be provided through the `database.yml` by using the `table_name_prefix/suffix` configuration keys.
|
|
623
|
-
|
|
716
|
+
**Every table statement applies them by default**, so a migration only ever names the table (index)
|
|
717
|
+
_base_ name.
|
|
624
718
|
|
|
625
719
|
**Example:**
|
|
626
720
|
Production uses a index suffix with '-pro', development uses '-dev' - they share the same cluster, but different indexes.
|
|
627
721
|
|
|
628
|
-
|
|
722
|
+
```yml
|
|
723
|
+
production:
|
|
724
|
+
elasticsearch:
|
|
725
|
+
# ...
|
|
726
|
+
table_name_suffix: '-pro'
|
|
727
|
+
|
|
728
|
+
development:
|
|
729
|
+
elasticsearch:
|
|
730
|
+
# ...
|
|
731
|
+
table_name_suffix: '-dev'
|
|
732
|
+
```
|
|
629
733
|
|
|
734
|
+
For the **settings** table / index this results in the following names:
|
|
630
735
|
* settings-pro
|
|
631
736
|
* settings-dev
|
|
632
737
|
|
|
@@ -634,9 +739,10 @@ A single migration can be created to be used within each environment:
|
|
|
634
739
|
|
|
635
740
|
```ruby
|
|
636
741
|
# Example migration
|
|
637
|
-
class AddSettings < ActiveRecord::Migration[7.
|
|
742
|
+
class AddSettings < ActiveRecord::Migration[7.1]
|
|
638
743
|
def up
|
|
639
|
-
|
|
744
|
+
# creates 'settings-pro' on production & 'settings-dev' on development
|
|
745
|
+
create_table "settings", force: true do |t|
|
|
640
746
|
t.mapping :created_at, :date
|
|
641
747
|
t.mapping :key, :integer do |m|
|
|
642
748
|
m.primary_key = true
|
|
@@ -653,11 +759,63 @@ class AddSettings < ActiveRecord::Migration[7.0]
|
|
|
653
759
|
end
|
|
654
760
|
|
|
655
761
|
def down
|
|
656
|
-
drop_table
|
|
762
|
+
drop_table "settings"
|
|
657
763
|
end
|
|
658
764
|
end
|
|
659
765
|
```
|
|
660
766
|
|
|
767
|
+
### opting out with `decorate: false`
|
|
768
|
+
|
|
769
|
+
Provide `decorate: false` to address an index by its **literal** name:
|
|
770
|
+
|
|
771
|
+
```ruby
|
|
772
|
+
# addresses 'settings-pro' - even from a '-dev' suffixed connection
|
|
773
|
+
drop_table "settings-pro", decorate: false
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
This is required in two cases:
|
|
777
|
+
|
|
778
|
+
* the name is **already resolved** _(e.g. `Model.table_name`, or a name read back from `#tables`)_
|
|
779
|
+
* the base name itself **starts with the prefix** or **ends with the suffix** - `_env_table_name`
|
|
780
|
+
keeps itself idempotent through a `start_with?` / `end_with?` check and cannot tell such a name
|
|
781
|
+
apart from an already resolved one
|
|
782
|
+
|
|
783
|
+
The flag only ever applies to table (index) names - `alias`, `mapping`, `setting` & `meta` names are
|
|
784
|
+
never touched. Statements taking **two** names _(`clone_table`, `rename_table`, `reindex_table`,
|
|
785
|
+
`restore_table`, `backup_table`, `create_table copy_from:`)_ resolve both.
|
|
786
|
+
|
|
787
|
+
The **schema statements** _(`table_exists?`, `table_schema`, `table_mappings`, `table_settings`,
|
|
788
|
+
`columns`, ...)_ are deliberately **not** decorated - ActiveRecord and the schema dumper call them
|
|
789
|
+
with an already resolved index name.
|
|
790
|
+
|
|
791
|
+
The `_env_table_name`-method itself is still public, so existing migrations keep working - it is now
|
|
792
|
+
redundant, since it resolves the very same name the statement would resolve on its own.
|
|
793
|
+
|
|
794
|
+
### global kill-switch
|
|
795
|
+
|
|
796
|
+
The default of a **not explicitly provided** `decorate:` argument is resolved from a global flag:
|
|
797
|
+
|
|
798
|
+
```ruby
|
|
799
|
+
# e.g. in an initializer
|
|
800
|
+
ElasticsearchRecord.decorate_table_names = false
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
Setting it to `false` restores the former, opt-in behaviour, where the decoration had to be applied
|
|
804
|
+
by hand through `_env_table_name`. A single statement can still opt in or out on its own, so
|
|
805
|
+
`decorate: true` keeps working while the flag is off:
|
|
806
|
+
|
|
807
|
+
```ruby
|
|
808
|
+
ElasticsearchRecord.decorate_table_names = false
|
|
809
|
+
|
|
810
|
+
drop_table "settings" # => drops 'settings'
|
|
811
|
+
drop_table "settings", decorate: true # => drops 'settings-dev'
|
|
812
|
+
drop_table _env_table_name("settings") # => drops 'settings-dev' (the former syntax)
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
The schema dumper follows the flag: while the decoration is globally disabled it dumps the **full**
|
|
816
|
+
index name with an explicit `decorate: false`, so a dumped schema stays correct even if the flag is
|
|
817
|
+
flipped back on before it is loaded.
|
|
818
|
+
|
|
661
819
|
## Docs
|
|
662
820
|
|
|
663
821
|
[CHANGELOG](docs/CHANGELOG.md)
|
data/Rakefile
CHANGED
|
File without changes
|
data/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,63 @@
|
|
|
1
1
|
# ElasticsearchRecord - CHANGELOG
|
|
2
2
|
|
|
3
|
+
## [3.0.0] - 2026-09-08
|
|
4
|
+
* [add] **BREAKING**: requires `activerecord ~> 7.2.0`
|
|
5
|
+
* [add] `Quoting::ClassMethods#quote_column_name` & `#quote_table_name` - identifier quoting is class-level & mandatory now
|
|
6
|
+
* [add] `ElasticsearchRecord::InternalMetadata` - always disabled _(the flag moved from the adapter to the database config)_
|
|
7
|
+
* [add] `patches/active_record/connection_pool_patch` - routes `#migrations_paths`, `#schema_migration` & `#internal_metadata` back to the adapter
|
|
8
|
+
* [add] specs for `ElasticsearchAdapter#translate_exception`
|
|
9
|
+
* [add] specs for `Relation::ValueMethods#limit_value=`
|
|
10
|
+
* [add] specs for `Core#id=`, `#id_was`, `#write_attribute` & `#read_attribute`
|
|
11
|
+
* [add] specs for `TableSettingDefinition`
|
|
12
|
+
* [add] specs for `InternalMetadata#enabled?`
|
|
13
|
+
* [ref] the adapter registers itself through `ActiveRecord::ConnectionAdapters.register` - `ConnectionHandling#elasticsearch_connection` removed
|
|
14
|
+
* [ref] the adapter provides `#internal_metadata` & `#migration_context` again; `#schema_migration` builds from the **pool**
|
|
15
|
+
* [ref] `SchemaMigration#integer_versions` resolves through `pool.with_connection`
|
|
16
|
+
* [ref] `#find_by_sql`, `#find_by_query` & `#find_by_esql` resolve through `with_connection`; `allow_retry:` forwarded down to `#internal_exec_query`
|
|
17
|
+
* [ref] `#_insert_record`, `#_insert_with_auto_increment` & `#cached_find_by_statement` take the connection as first argument
|
|
18
|
+
* [ref] `Arel::Collectors::ElasticsearchQuery#retryable` accessor added _(rails marks idempotent queries as retryable)_
|
|
19
|
+
* [ref] `assert_mutability!` -> `assert_modifiable!` & `ImmutableRelation` -> `UnmodifiableRelation`
|
|
20
|
+
* [ref] `Arel::Nodes::Or` is a nary node now - takes its children as a single `Array`
|
|
21
|
+
* [fix] `Querying::ClassMethods#search` to nest the `Elasticsearch::DSL` block result into the `body` and to only enter the DSL branch **if a block was provided**
|
|
22
|
+
|
|
23
|
+
## [2.0.0] - 2026-08-10
|
|
24
|
+
* [add] `ElasticsearchRecord.decorate_table_names` _(default: `true`)_ as global kill-switch for the table name decoration - only provides the default for an omitted `decorate:`-argument, `#_env_table_name` stays unaffected
|
|
25
|
+
* [add] `TableStatements#truncate_table` raises an `ArgumentError` for AR-internal indices - the statement runs a `drop` & `create` and would wipe the migration state. `#drop_table` stays unguarded by design _(AR resets both tables through it)_
|
|
26
|
+
* [add] `QueryMethods#select` raises on metadata fields _(`_id`, `_score`, ...)_ - they are always returned anyway
|
|
27
|
+
* [add] `ElasticsearchRecord::Result` now resolves **tabular** responses _(`sql`: columns + rows, `esql`: columns + values)_, so `find_by_sql` _(String)_ & `find_by_esql` instantiate records - rows are zipped against the **response** columns
|
|
28
|
+
* [add] `CalculationMethods#matrix_stats` raises an `ArgumentError` for less than two columns - the metric quantifies the relationship **between** fields
|
|
29
|
+
* [add] `ResultMethods#meta_only!` to resolve the metadata nodes _(`_id`, `_score`, ...)_ of each hit without transferring the `_source`
|
|
30
|
+
* [add] `Query::COLUMNS_NONE` constant for the `'!'` projection marker - replaces the bare literal in `visit_Selects` & `meta_only!`
|
|
31
|
+
* [add] specs for `ElasticsearchRecord::Persistence`, `ModelApi`, `SchemaMigration`, `Querying::ClassMethods`, the `Relation` methods _(Core, Query, Calculation & Result)_, the `Elasticsearch::SchemaStatements`, `TableStatements` & `SchemaDumper`, every class of the `Elasticsearch::Type` namespace _(incl. its `TYPE_MAP` registration)_, `Arel::Collectors::ElasticsearchQuery` and all three `Arel::Visitors::Elasticsearch*` visitors - incl. the 1.8.1 "only ten migrations" and 1.8.2 nested-reset regressions and a `TestIndexWithAutoIncrement` support that builds a model against a real `auto_increment` schema _(destructive calls still run through `TestIndex` and its name guard)_. Behaviours pinned as-is:
|
|
32
|
+
* `#or` compiles into a **failed** query _(the visitor fails every `Arel::Nodes::Grouping`)_, and AR's blank-arg stripping silently drops `configure(key, nil)` _(only the Hash form removes a key)_
|
|
33
|
+
* an index **alias** is dumped as a mapping of the elasticsearch 'alias' field type, which makes the `t.alias` branch of the dumper unreachable
|
|
34
|
+
* opposed nil-handling of metas _(deleted)_ and settings _(kept through `:__force__`)_
|
|
35
|
+
* a failed `create` has no `FAILED_BODIES` entry and falls back to an empty body; a multi-column `order` keeps only the last sort
|
|
36
|
+
* `SchemaMigration#count` and `#delete_version` / `#delete_all_versions` cannot be served by elasticsearch
|
|
37
|
+
* `_update_record` / `_delete_record` always return `0` _(a document-API response carries no `total`)_, and an auto-incremented id is only written as document `_id`, never into the mapped primary-key field
|
|
38
|
+
* `meta_only!` **spawns** instead of mutating the receiver _(unlike the other bang methods)_ and pins the `COLUMNS_NONE` projection; `pit_results` pins its infinite-loop guard
|
|
39
|
+
* [ref] **BREAKING**: every table statement resolves its table (index) name through `#_env_table_name` **by default** - the `table_name_prefix` / `table_name_suffix` no longer have to be applied by hand, which silently wrote into another environment's index. A new `decorate:`-argument _(default: `true`)_ switches it off per call for already resolved names. Only TABLE names are decorated; schema statements stay undecorated
|
|
40
|
+
* [ref] `SchemaDumper#table` dumps the **base** name instead of a `_env_table_name(...)` call - if that name would not resolve back, the full name is dumped with an explicit `decorate: false`
|
|
41
|
+
* [ref] **BREAKING**: `#open_tables`, `#close_tables`, `#refresh_tables` & `#truncate_tables` no longer subtract the AR-internal indices _(an explicitly named index was silently dropped)_ - plain loops now, forwarding `decorate:` to their singular statement and returning an `Array` for every provided name
|
|
42
|
+
* [ref] `TableStatements` drops the stale `:rename_table` entry from `define_unsupported_method` - the real implementation overwrote it anyway
|
|
43
|
+
* [ref] `#restore_table` replaces its `open`-argument with `unblock:` _(default: true)_ - a restore clones and inherits the 'write'-block, so the table was open but **read-only**. `ModelApi#restore!` follows along
|
|
44
|
+
* [ref] `ResultMethods#pit_results` resolves through `ElasticsearchRecord::Result` and respects the current projection _(`ids_only` removed in favour of `meta_only!`)_
|
|
45
|
+
* [ref] `TestIndex` spec support to optionally create/drop a second index _(still guarded by the `ALLOWED` name check)_
|
|
46
|
+
* [fix] `#rename_table` to resolve both names **itself** - the `clear_data_source_cache!` and `cluster_health` calls in between were left with the undecorated name
|
|
47
|
+
* [fix] `#backup_table` to build the auto-generated target from the **already resolved** name _(the suffix landed behind the `-snapshot-` part)_
|
|
48
|
+
* [fix] `#_env_table_name` to cast prefix & suffix - an empty `table_name_prefix:` yml entry resolves to `nil` and raised a `TypeError`
|
|
49
|
+
* [fix] `Result#cast_values` to resolve values from the `_source` node, metadata fields from the document level
|
|
50
|
+
* [fix] `visit_Selects` to no longer provide metadata fields to the `_source`-filter _(never matched)_ - projects `_source: false` if only metadata is selected
|
|
51
|
+
* [fix] `Querying::ClassMethods#esql` & `#msearch` to dispatch through the public `exec_query` _(rails 7.1 made `internal_exec_query` private)_ - the `async:`-argument was dropped along with it
|
|
52
|
+
* [fix] `Querying::ClassMethods#find_by_sql` to reference the provided `sql` for `String` queries _(undefined `query_or_sql` raised a `NameError`)_
|
|
53
|
+
* [fix] `SchemaStatements#max_result_window` to resolve the **flat** setting key and cast it to an `Integer` _(always fell back to 10000 and broke the batch_size guards)_
|
|
54
|
+
* [fix] `SchemaStatements#primary_keys` to always return an `Array` _(the `_meta` branch returned a raw String)_
|
|
55
|
+
* [fix] `CalculationMethods#count` to apply the SQL `LIMIT n OFFSET m` semantic on the resolved total - `terminate_after` alone acts **per shard** and never fires on a count query. `#size` on an unloaded relation was affected as well
|
|
56
|
+
* [fix] `UpdateTableDefinition#change_mapping_attributes` to resolve the current mapping type with a **String** key _(fell back to `:object` / `:nested`, so elasticsearch rejected every mapping parameter)_
|
|
57
|
+
* [fix] `#restore_table` to no longer touch the backup after a `drop_backup: true` _(it no longer exists at that point)_
|
|
58
|
+
* [fix] `_insert_with_auto_increment` to write the **plain, integer** id into `_meta.auto_increment` - the block returns an Array of the `returning` values, which was stored as-is and raised on the NEXT insert. Now unwraps Array / Hash / plain and casts to `Integer`
|
|
59
|
+
* [fix] `ResultMethods#pit_delete` to no longer `select('_id')` _(rejected by the new metadata guard)_ - resolves the ids through `meta_only!`
|
|
60
|
+
|
|
3
61
|
## [1.8.2] - 2024-11-26
|
|
4
62
|
* [fix] `ElasticsearchRecord::Relation::QueryMethods#build_query_clause` to raise an exception on `nil` assignments
|
|
5
63
|
* [fix] `Arel::Visitors::ElasticsearchBase#compile` to always reset temporary assignments _(causes missing assignments after a query-build-exception)_
|
|
@@ -18,6 +76,14 @@
|
|
|
18
76
|
* [add] new repository branch `rails-7-1-stable` to support different rails version
|
|
19
77
|
* [ref] gemspec to lock on rails 7.1
|
|
20
78
|
|
|
79
|
+
## [1.7.5] - 2024-11-26 _(no gem release)_
|
|
80
|
+
* [ref] `ElasticsearchRecord::Relation::QueryMethods#build_query_clause` to raise an exception instead of building an empty `QueryClause`
|
|
81
|
+
|
|
82
|
+
## [1.7.4] - 2024-11-25 _(no gem release)_
|
|
83
|
+
* [fix] `Arel::Visitors::ElasticsearchBase#compile` to always reset temporary assignments _(causes missing assignments after a query-build-exception)_
|
|
84
|
+
* [fix] `Arel::Nodes::SelectAgg` to not merge nil-values
|
|
85
|
+
* [fix] `ElasticsearchRecord::Relation::QueryMethods#build_query_clause` to prevent nil-Array assignment _(e.g. `[nil]` causes q query exception)_
|
|
86
|
+
|
|
21
87
|
## [1.7.3] - 2024-05-07 _(no gem release)_
|
|
22
88
|
* [add] new elasticsearch mapping types _(percolator, geo, vector, texts, ...)_
|
|
23
89
|
* [ref] `ElasticsearchRecord::Relation#limit` to detect `Float::INFINITY` to also set the **max_result_window**
|
data/docs/CODE_OF_CONDUCT.md
CHANGED
|
File without changes
|
data/docs/LICENSE
CHANGED
|
File without changes
|
|
@@ -14,7 +14,7 @@ DESC
|
|
|
14
14
|
|
|
15
15
|
spec.homepage = "https://github.com/ruby-smart/elasticsearch_record"
|
|
16
16
|
spec.license = "MIT"
|
|
17
|
-
spec.required_ruby_version = ">=
|
|
17
|
+
spec.required_ruby_version = ">= 3.1.0"
|
|
18
18
|
|
|
19
19
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
|
20
20
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
@@ -32,10 +32,10 @@ DESC
|
|
|
32
32
|
|
|
33
33
|
spec.require_paths = ["lib"]
|
|
34
34
|
|
|
35
|
-
spec.add_dependency 'activerecord', '~> 7.
|
|
35
|
+
spec.add_dependency 'activerecord', '~> 7.2.0'
|
|
36
36
|
spec.add_dependency 'elasticsearch', '>= 7.17'
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
spec.add_development_dependency 'coveralls_reborn', '~> 0.25'
|
|
39
39
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
40
40
|
spec.add_development_dependency 'rake', "~> 13.0"
|
|
41
41
|
spec.add_development_dependency 'yard', '~> 0.9'
|
|
File without changes
|
|
@@ -131,14 +131,30 @@ module ActiveRecord
|
|
|
131
131
|
|
|
132
132
|
private
|
|
133
133
|
|
|
134
|
+
# gets called for all queries - a +ElasticsearchRecord::Query+ must be provided.
|
|
135
|
+
# @param [ElasticsearchRecord::Query] query
|
|
136
|
+
# @param [String (frozen),nil] name
|
|
137
|
+
# @param [Array] binds - not supported on the top-level and therefore ignored!
|
|
138
|
+
# @param [Boolean] prepare - used by the default AbstractAdapter - but not supported and therefore never ignored!
|
|
139
|
+
# @param [Boolean] async
|
|
140
|
+
# @param [Boolean] allow_retry
|
|
141
|
+
# @return [ElasticsearchRecord::Result]
|
|
142
|
+
def internal_exec_query(query, name = "QUERY", binds = [], prepare: false, async: false, allow_retry: false)
|
|
143
|
+
build_result(
|
|
144
|
+
internal_execute(query, name, async: async, allow_retry: allow_retry),
|
|
145
|
+
columns: query.columns
|
|
146
|
+
)
|
|
147
|
+
end
|
|
148
|
+
|
|
134
149
|
# Executes the query object in the context of this connection and returns the raw result
|
|
135
150
|
# from the connection adapter.
|
|
136
151
|
# @param [ElasticsearchRecord::Query] query
|
|
137
152
|
# @param [String (frozen),nil] name
|
|
138
|
-
# @param [Boolean] async (default: false)
|
|
153
|
+
# @param [Boolean] async (default: false) - NOT supported!
|
|
139
154
|
# @param [Boolean] allow_retry (default: false)
|
|
155
|
+
# @param [Boolean] materialize_transactions (default: false) - NOT supported!
|
|
140
156
|
# @return [ElasticsearchRecord::Result]
|
|
141
|
-
def internal_execute(query, name = nil, async: false, allow_retry: false, materialize_transactions:
|
|
157
|
+
def internal_execute(query, name = nil, async: false, allow_retry: false, materialize_transactions: false)
|
|
142
158
|
# validate the query
|
|
143
159
|
raise ActiveRecord::StatementInvalid, 'Unable to execute! Provided query is not a "ElasticsearchRecord::Query".' unless query.is_a?(ElasticsearchRecord::Query)
|
|
144
160
|
raise ActiveRecord::StatementInvalid, 'Unable to execute! Provided query is invalid.' unless query.valid?
|
|
@@ -146,21 +162,7 @@ module ActiveRecord
|
|
|
146
162
|
# checks for write query - raises an exception if connection is locked to readonly ...
|
|
147
163
|
check_if_write_query(query)
|
|
148
164
|
|
|
149
|
-
api(
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
# gets called for all queries - a +ElasticsearchRecord::Query+ must be provided.
|
|
153
|
-
# @param [ElasticsearchRecord::Query] query
|
|
154
|
-
# @param [String (frozen),nil] name
|
|
155
|
-
# @param [Array] binds - not supported on the top-level and therefore ignored!
|
|
156
|
-
# @param [Boolean] prepare - used by the default AbstractAdapter - but not supported and therefore never ignored!
|
|
157
|
-
# @param [Boolean] async
|
|
158
|
-
# @return [ElasticsearchRecord::Result]
|
|
159
|
-
def internal_exec_query(query, name = "QUERY", binds = [], prepare: false, async: false)
|
|
160
|
-
build_result(
|
|
161
|
-
internal_execute(query, name, async: async),
|
|
162
|
-
columns: query.columns
|
|
163
|
-
)
|
|
165
|
+
api(query.gate, query.query_arguments, name, async: async, allow_retry: allow_retry, materialize_transactions: materialize_transactions)
|
|
164
166
|
end
|
|
165
167
|
end
|
|
166
168
|
end
|
|
@@ -4,6 +4,22 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module Elasticsearch
|
|
6
6
|
module Quoting # :nodoc:
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
module ClassMethods # :nodoc:
|
|
10
|
+
# since rails 7.2 identifier quoting is class-level & mandatory (the abstract
|
|
11
|
+
# implementation raises a +NotImplementedError+). Elasticsearch fields & indices are
|
|
12
|
+
# plain JSON keys - so they pass through unquoted.
|
|
13
|
+
def quote_column_name(column_name)
|
|
14
|
+
column_name.to_s
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Quotes the table (index) name. Defaults to column name quoting.
|
|
18
|
+
def quote_table_name(table_name)
|
|
19
|
+
quote_column_name(table_name)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
7
23
|
def quoted_true
|
|
8
24
|
'true'
|
|
9
25
|
end
|
|
File without changes
|
data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/attribute_methods.rb
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -14,6 +14,12 @@ module ActiveRecord
|
|
|
14
14
|
@aliases = HashWithIndifferentAccess.new
|
|
15
15
|
@metas = HashWithIndifferentAccess.new
|
|
16
16
|
|
|
17
|
+
# HINT: Currently there is only one attribute, that cannot be assigned to any of the top hash kind, and also not opts:
|
|
18
|
+
# * dynamic
|
|
19
|
+
# This attribute must be assigned below the *mappings* node but as sibling to *properties*.
|
|
20
|
+
# This can only be done to create a special kind of options (@flags ???) and assign & fetch them within the required arel.
|
|
21
|
+
# Since this only setting can also be assigned to each individual mapping, there is currently no need to build this ...
|
|
22
|
+
|
|
17
23
|
transform_settings!(settings) if settings.present?
|
|
18
24
|
transform_mappings!(mappings) if mappings.present?
|
|
19
25
|
transform_aliases!(aliases) if aliases.present?
|
|
File without changes
|
data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb
CHANGED
|
File without changes
|
data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_meta_definition.rb
CHANGED
|
File without changes
|
|
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
|
10
10
|
include ActiveModel::Validations
|
|
11
11
|
|
|
12
12
|
# exclude settings, that are provided through the API but are not part of the index-settings API
|
|
13
|
-
IGNORE_NAMES = ['provided_name', 'creation_date', 'uuid', 'version','routing.allocation.initial_recovery','resize'].freeze
|
|
13
|
+
IGNORE_NAMES = ['provided_name', 'creation_date', 'uuid', 'version', 'routing.allocation.initial_recovery', 'resize'].freeze
|
|
14
14
|
|
|
15
15
|
# available setting names
|
|
16
16
|
# - see @ https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#index-modules-settings
|
|
@@ -19,13 +19,12 @@ module ActiveRecord
|
|
|
19
19
|
FINAL_NAMES = ['number_of_shards', 'routing_partition_size', 'soft_deletes.enabled'].freeze
|
|
20
20
|
|
|
21
21
|
# static names can only be set during index creation or closed
|
|
22
|
-
STATIC_NAMES = ['number_of_routing_shards', 'codec',
|
|
22
|
+
STATIC_NAMES = ['number_of_routing_shards', 'codec', 'mode',
|
|
23
23
|
'soft_deletes.retention_lease.period',
|
|
24
24
|
'load_fixed_bitset_filters_eagerly', 'shard.check_on_startup',
|
|
25
25
|
|
|
26
26
|
# modules
|
|
27
|
-
'analysis', 'routing', 'unassigned', 'merge', 'similarity', 'search', 'store', '
|
|
28
|
-
'indexing_pressure'].freeze
|
|
27
|
+
'analysis', 'routing', 'unassigned', 'merge', 'similarity', 'search', 'store', 'indexing_pressure'].freeze
|
|
29
28
|
|
|
30
29
|
# dynamic names can always be changed
|
|
31
30
|
DYNAMIC_NAMES = ['number_of_replicas', 'auto_expand_replicas', "search.idle.after", 'refresh_interval',
|
|
@@ -34,7 +33,10 @@ module ActiveRecord
|
|
|
34
33
|
'max_refresh_listeners', 'analyze.max_token_count', 'highlight.max_analyzed_offset',
|
|
35
34
|
'max_terms_count', 'max_regex_length', 'query.default_field', 'routing.allocation.enable',
|
|
36
35
|
'routing.rebalance.enable', 'gc_deletes', 'default_pipeline', 'final_pipeline',
|
|
37
|
-
'hidden', 'blocks'
|
|
36
|
+
'hidden', 'blocks',
|
|
37
|
+
|
|
38
|
+
# modules
|
|
39
|
+
'translog'].freeze
|
|
38
40
|
|
|
39
41
|
VALID_NAMES = (FINAL_NAMES + STATIC_NAMES + DYNAMIC_NAMES).freeze
|
|
40
42
|
|
|
@@ -66,7 +66,9 @@ module ActiveRecord
|
|
|
66
66
|
raise ArgumentError, "you cannot change an unknown mapping '#{name}'" if current_mapping.blank?
|
|
67
67
|
|
|
68
68
|
# build new mapping
|
|
69
|
-
mapping
|
|
69
|
+
# IMPORTANT: the received mapping is a String-keyed Hash - a symbol access would resolve
|
|
70
|
+
# nil here, which +TableMappingDefinition+ then falls back to :object / :nested
|
|
71
|
+
mapping = new_mapping_definition(name, current_mapping['type'], **options, &block)
|
|
70
72
|
define! ChangeMappingDefinition, mapping
|
|
71
73
|
|
|
72
74
|
# check if the mapping is assigned as new primary_key
|
|
File without changes
|