Skip to content

Commit f188c65

Browse files
authored
[MODEL] Add warning and documentation about STI support being deprecated (#898)
* [MODEL] Add warning and documentation about STI support being deprecated (#895) * [MODEL] Add warning and documentation about STI support being deprecated * [MODEL] Minor change to STI deprecation warning * [MODEL] Freeze string constant depreaction warning * [MODEL] Update Readme text about STI deprecation * [Model] Fix naming with inheritance when using Proxy (#887) * Add naming inheritance tests when using a proxy * Skip circular call to index_name/document_type when Proxy is used and inheritance is enabled * [MODEL] Adjust previous cherry-picked commit for 6.x branch * [MODEL] Only warn if inheritance_enabled is set to true
1 parent 03c4085 commit f188c65

File tree

5 files changed

+201
-81
lines changed

5 files changed

+201
-81
lines changed

elasticsearch-model/README.md

+12-7
Original file line numberDiff line numberDiff line change
@@ -724,13 +724,8 @@ module and its submodules for technical information.
724724

725725
The module provides a common `settings` method to customize various features.
726726

727-
At the moment, the only supported setting is `:inheritance_enabled`, which makes the class receiving the module
728-
respect index names and document types of a super-class, eg. in case you're using "single table inheritance" (STI)
729-
in Rails:
730-
731-
```ruby
732-
Elasticsearch::Model.settings[:inheritance_enabled] = true
733-
```
727+
Before version 7.0.0 of the gem, the only supported setting was `:inheritance_enabled`. This setting has been deprecated
728+
and removed.
734729

735730
## Development and Community
736731

@@ -748,6 +743,16 @@ curl -# https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticse
748743
SERVER=start TEST_CLUSTER_COMMAND=$PWD/tmp/elasticsearch-1.0.0.RC1/bin/elasticsearch bundle exec rake test:all
749744
```
750745

746+
### Single Table Inheritance deprecation
747+
748+
`Single Table Inheritance` has been supported until the 6.x series of this gem. With this feature,
749+
settings on a parent model could be inherited by a child model leading to different model documents being indexed
750+
into the same Elasticsearch index. This feature depended on the ability to set a `type` for a document in Elasticsearch.
751+
The Elasticsearch team has deprecated support for `types`, as is described [here](https://www.elastic.co/guide/en/elasticsearch/reference/current/removal-of-types.html)
752+
This gem will also remove support for types and Single Table Inheritance in version 7.0 as it encourages an anti-pattern.
753+
Please save different model documents in separate indices or implement an artificial `type` field manually in each
754+
document.
755+
751756
## License
752757

753758
This software is licensed under the Apache 2 license, quoted below.

elasticsearch-model/lib/elasticsearch/model.rb

+15-8
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,6 @@ class << self
131131
end
132132
end
133133

134-
# Access the module settings
135-
#
136-
def self.settings
137-
@settings ||= {}
138-
end
139-
140134
module ClassMethods
141135
# Get the client common for all models
142136
#
@@ -193,7 +187,7 @@ def search(query_or_payload, models=[], options={})
193187
# @note Inheritance is disabled by default.
194188
#
195189
def inheritance_enabled
196-
@inheritance_enabled ||= false
190+
@settings[:inheritance_enabled] ||= false
197191
end
198192

199193
# Enable inheritance of index_name and document_type
@@ -203,8 +197,21 @@ def inheritance_enabled
203197
# Elasticsearch::Model.inheritance_enabled = true
204198
#
205199
def inheritance_enabled=(inheritance_enabled)
206-
@inheritance_enabled = inheritance_enabled
200+
warn STI_DEPRECATION_WARNING if inheritance_enabled
201+
@settings[:inheritance_enabled] = inheritance_enabled
202+
end
203+
204+
# Access the module settings
205+
#
206+
def settings
207+
@settings ||= {}
207208
end
209+
210+
private
211+
212+
STI_DEPRECATION_WARNING = "DEPRECATION WARNING: Support for Single Table Inheritance (STI) is deprecated " +
213+
"and will be removed in version 7.0.0.\nPlease save different model documents in separate indices and refer " +
214+
"to the Elasticsearch documentation for more information.".freeze
208215
end
209216
extend ClassMethods
210217

elasticsearch-model/lib/elasticsearch/model/naming.rb

+6-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,12 @@ def implicit(prop)
7979

8080
if Elasticsearch::Model.settings[:inheritance_enabled]
8181
self.ancestors.each do |klass|
82-
next if klass == self
82+
# When Naming is included in Proxy::ClassMethods the actual model
83+
# is among its ancestors. We don't want to call the actual model
84+
# since it will result in the same call to the same instance of
85+
# Proxy::ClassMethods. To prevent this we also skip the ancestor
86+
# that is the target.
87+
next if klass == self || self.respond_to?(:target) && klass == self.target
8388
break if value = klass.respond_to?(prop) && klass.send(prop)
8489
end
8590
end

elasticsearch-model/spec/elasticsearch/model/module_spec.rb

+25
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,30 @@ def self.search(query, options={})
7272
expect(Elasticsearch::Model.settings[:foo]).to eq('bar')
7373
end
7474
end
75+
76+
context 'when \'inheritance_enabled\' is set' do
77+
78+
around do |example|
79+
original_value = Elasticsearch::Model.settings[:inheritance_enabled]
80+
example.run
81+
Elasticsearch::Model.settings[:inheritance_enabled] = original_value
82+
end
83+
84+
context 'when \'inheritance_enabled\' is true' do
85+
86+
it 'warns with a deprecation message' do
87+
expect(Elasticsearch::Model).to receive(:warn)
88+
Elasticsearch::Model.inheritance_enabled = true
89+
end
90+
end
91+
92+
context 'when \'inheritance_enabled\' is false' do
93+
94+
it 'does not warn' do
95+
expect(Elasticsearch::Model).not_to receive(:warn)
96+
Elasticsearch::Model.inheritance_enabled = false
97+
end
98+
end
99+
end
75100
end
76101
end

elasticsearch-model/spec/elasticsearch/model/naming_inheritance_spec.rb

+143-65
Original file line numberDiff line numberDiff line change
@@ -2,105 +2,183 @@
22

33
describe 'naming inheritance' do
44

5-
before(:all) do
6-
class ::TestBase
7-
extend ActiveModel::Naming
5+
context 'without using proxy' do
6+
before(:all) do
7+
TestBase = Class.new do
8+
extend ActiveModel::Naming
89

9-
extend Elasticsearch::Model::Naming::ClassMethods
10-
include Elasticsearch::Model::Naming::InstanceMethods
11-
end
10+
extend Elasticsearch::Model::Naming::ClassMethods
11+
include Elasticsearch::Model::Naming::InstanceMethods
12+
end
1213

13-
class ::Animal < ::TestBase
14-
extend ActiveModel::Naming
14+
Animal = Class.new TestBase do
15+
extend ActiveModel::Naming
1516

16-
extend Elasticsearch::Model::Naming::ClassMethods
17-
include Elasticsearch::Model::Naming::InstanceMethods
17+
extend Elasticsearch::Model::Naming::ClassMethods
18+
include Elasticsearch::Model::Naming::InstanceMethods
19+
20+
index_name "mammals"
21+
document_type "mammal"
22+
end
23+
24+
Dog = Class.new Animal
25+
26+
module ::MyNamespace
27+
Dog = Class.new Animal
28+
end
29+
30+
Cat = Class.new Animal do
31+
extend ActiveModel::Naming
32+
33+
extend Elasticsearch::Model::Naming::ClassMethods
34+
include Elasticsearch::Model::Naming::InstanceMethods
35+
36+
index_name "cats"
37+
document_type "cat"
38+
end
1839

19-
index_name "mammals"
20-
document_type "mammal"
2140
end
2241

23-
class ::Dog < ::Animal
42+
after(:all) do
43+
remove_classes(TestBase, Animal, MyNamespace, Cat)
2444
end
2545

26-
module ::MyNamespace
27-
class Dog < ::Animal
28-
end
46+
around(:all) do |example|
47+
original_value = Elasticsearch::Model.inheritance_enabled
48+
Elasticsearch::Model.inheritance_enabled = true
49+
example.run
50+
Elasticsearch::Model.inheritance_enabled = original_value
2951
end
3052

31-
class ::Cat < ::Animal
32-
extend ActiveModel::Naming
53+
describe '#index_name' do
54+
55+
it 'returns the default index name' do
56+
expect(TestBase.index_name).to eq('test_bases')
57+
expect(TestBase.new.index_name).to eq('test_bases')
58+
end
59+
60+
it 'returns the explicit index name' do
61+
expect(Animal.index_name).to eq('mammals')
62+
expect(Animal.new.index_name).to eq('mammals')
3363

34-
extend Elasticsearch::Model::Naming::ClassMethods
35-
include Elasticsearch::Model::Naming::InstanceMethods
64+
expect(Cat.index_name).to eq('cats')
65+
expect(Cat.new.index_name).to eq('cats')
66+
end
3667

37-
index_name "cats"
38-
document_type "cat"
68+
it 'returns the ancestor index name' do
69+
expect(Dog.index_name).to eq('mammals')
70+
expect(Dog.new.index_name).to eq('mammals')
71+
end
72+
73+
it 'returns the ancestor index name for namespaced models' do
74+
expect(::MyNamespace::Dog.index_name).to eq('mammals')
75+
expect(::MyNamespace::Dog.new.index_name).to eq('mammals')
76+
end
3977
end
4078

41-
end
79+
describe '#document_type' do
4280

43-
after(:all) do
44-
remove_classes(TestBase, Animal, MyNamespace, Cat)
45-
end
81+
it 'returns nil' do
82+
expect(TestBase.document_type).to eq('_doc')
83+
expect(TestBase.new.document_type).to eq('_doc')
84+
end
4685

47-
around(:all) do |example|
48-
original_value = Elasticsearch::Model.settings[:inheritance_enabled]
49-
Elasticsearch::Model.settings[:inheritance_enabled] = true
50-
example.run
51-
Elasticsearch::Model.settings[:inheritance_enabled] = original_value
52-
end
86+
it 'returns the explicit document type' do
87+
expect(Animal.document_type).to eq('mammal')
88+
expect(Animal.new.document_type).to eq('mammal')
5389

90+
expect(Cat.document_type).to eq('cat')
91+
expect(Cat.new.document_type).to eq('cat')
92+
end
5493

55-
describe '#index_name' do
94+
it 'returns the ancestor document type' do
95+
expect(Dog.document_type).to eq('mammal')
96+
expect(Dog.new.document_type).to eq('mammal')
97+
end
5698

57-
it 'returns the default index name' do
58-
expect(TestBase.index_name).to eq('test_bases')
59-
expect(TestBase.new.index_name).to eq('test_bases')
99+
it 'returns the ancestor document type for namespaced models' do
100+
expect(::MyNamespace::Dog.document_type).to eq('mammal')
101+
expect(::MyNamespace::Dog.new.document_type).to eq('mammal')
102+
end
60103
end
104+
end
105+
106+
context 'when using proxy' do
107+
before(:all) do
108+
TestBase = Class.new do
109+
extend ActiveModel::Naming
61110

62-
it 'returns the explicit index name' do
63-
expect(Animal.index_name).to eq('mammals')
64-
expect(Animal.new.index_name).to eq('mammals')
111+
include Elasticsearch::Model
112+
end
65113

66-
expect(Cat.index_name).to eq('cats')
67-
expect(Cat.new.index_name).to eq('cats')
114+
Animal = Class.new TestBase do
115+
index_name "mammals"
116+
document_type "mammal"
117+
end
118+
119+
Dog = Class.new Animal
120+
121+
module MyNamespace
122+
Dog = Class.new Animal
123+
end
124+
125+
Cat = Class.new Animal do
126+
index_name "cats"
127+
document_type "cat"
128+
end
68129
end
69130

70-
it 'returns the ancestor index name' do
71-
expect(Dog.index_name).to eq('mammals')
72-
expect(Dog.new.index_name).to eq('mammals')
131+
after(:all) do
132+
remove_classes(TestBase, Animal, MyNamespace, Cat)
73133
end
74134

75-
it 'returns the ancestor index name for namespaced models' do
76-
expect(::MyNamespace::Dog.index_name).to eq('mammals')
77-
expect(::MyNamespace::Dog.new.index_name).to eq('mammals')
135+
around(:all) do |example|
136+
original_value = Elasticsearch::Model.settings[:inheritance_enabled]
137+
Elasticsearch::Model.settings[:inheritance_enabled] = true
138+
example.run
139+
Elasticsearch::Model.settings[:inheritance_enabled] = original_value
78140
end
79-
end
80141

81-
describe '#document_type' do
142+
describe '#index_name' do
82143

83-
it 'returns the default document type' do
84-
expect(TestBase.document_type).to eq('_doc')
85-
expect(TestBase.new.document_type).to eq('_doc')
86-
end
144+
it 'returns the default index name' do
145+
expect(TestBase.index_name).to eq('test_bases')
146+
end
87147

88-
it 'returns the explicit document type' do
89-
expect(Animal.document_type).to eq('mammal')
90-
expect(Animal.new.document_type).to eq('mammal')
148+
it 'returns the explicit index name' do
149+
expect(Animal.index_name).to eq('mammals')
91150

92-
expect(Cat.document_type).to eq('cat')
93-
expect(Cat.new.document_type).to eq('cat')
94-
end
151+
expect(Cat.index_name).to eq('cats')
152+
end
153+
154+
it 'returns the ancestor index name' do
155+
expect(Dog.index_name).to eq('mammals')
156+
end
95157

96-
it 'returns the ancestor document type' do
97-
expect(Dog.document_type).to eq('mammal')
98-
expect(Dog.new.document_type).to eq('mammal')
158+
it 'returns the ancestor index name for namespaced models' do
159+
expect(::MyNamespace::Dog.index_name).to eq('mammals')
160+
end
99161
end
100162

101-
it 'returns the ancestor document type for namespaced models' do
102-
expect(::MyNamespace::Dog.document_type).to eq('mammal')
103-
expect(::MyNamespace::Dog.new.document_type).to eq('mammal')
163+
describe '#document_type' do
164+
165+
it 'returns nil' do
166+
expect(TestBase.document_type).to eq('_doc')
167+
end
168+
169+
it 'returns the explicit document type' do
170+
expect(Animal.document_type).to eq('mammal')
171+
172+
expect(Cat.document_type).to eq('cat')
173+
end
174+
175+
it 'returns the ancestor document type' do
176+
expect(Dog.document_type).to eq('mammal')
177+
end
178+
179+
it 'returns the ancestor document type for namespaced models' do
180+
expect(::MyNamespace::Dog.document_type).to eq('mammal')
181+
end
104182
end
105183
end
106184
end

0 commit comments

Comments
 (0)