Skip to content

Commit 95d3cbf

Browse files
Merge #237
237: Add snake_case support for query parameters r=curquiza a=brunoocasali To evict a breaking change I've added support to any kind of formatting let the meilisearch backend tells us if the code is right or wrong. After some time, we could introduce a deprecation warning and then remove the system that supports this feature. Co-authored-by: Bruno Casali <[email protected]>
2 parents cd1f725 + cb4203f commit 95d3cbf

File tree

6 files changed

+92
-20
lines changed

6 files changed

+92
-20
lines changed

.code-samples.meilisearch.yaml

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ get_one_index_1: |-
88
list_all_indexes_1: |-
99
client.indexes
1010
create_an_index_1: |-
11-
client.create_index('movies', primaryKey: 'movie_id')
11+
client.create_index('movies', primary_key: 'movie_id')
1212
update_an_index_1: |-
13-
client.index('movies').update(primaryKey: 'movie_id')
13+
client.index('movies').update(primary_key: 'movie_id')
1414
delete_an_index_1: |-
1515
client.delete_index('movies')
1616
get_one_document_1: |-
@@ -53,7 +53,7 @@ get_settings_1: |-
5353
client.index('movies').settings
5454
update_settings_1: |-
5555
client.index('movies').update_settings({
56-
rankingRules: [
56+
ranking_rules: [
5757
'words',
5858
'typo',
5959
'proximity',
@@ -63,24 +63,24 @@ update_settings_1: |-
6363
'release_date:desc',
6464
'rank:desc'
6565
],
66-
distinctAttribute: 'movie_id',
67-
searchableAttributes: [
66+
distinct_attribute: 'movie_id',
67+
searchable_attributes: [
6868
'title',
6969
'description',
7070
'genre'
7171
],
72-
displayedAttributes: [
72+
displayed_attributes: [
7373
'title',
7474
'description',
7575
'genre',
7676
'release_date'
7777
],
78-
stopWords: [
78+
stop_words: [
7979
'the',
8080
'a',
8181
'an'
8282
],
83-
sortableAttributes: [
83+
sortable_attributes: [
8484
'title',
8585
'release_date'
8686
],
@@ -176,7 +176,7 @@ field_properties_guide_searchable_1: |-
176176
])
177177
field_properties_guide_displayed_1: |-
178178
client.index('movies').update_settings({
179-
displayedAttributes: [
179+
displayed_attributes: [
180180
'title',
181181
'description',
182182
'genre',
@@ -207,16 +207,16 @@ search_parameter_guide_limit_1: |-
207207
})
208208
search_parameter_guide_retrieve_1: |-
209209
client.index('movies').search('shifu', {
210-
attributesToRetrieve: ['overview', 'title']
210+
attributes_to_retrieve: ['overview', 'title']
211211
})
212212
search_parameter_guide_crop_1: |-
213213
client.index('movies').search('shifu', {
214-
attributesToCrop: ['overview'],
214+
attributes_to_crop: ['overview'],
215215
cropLength: 10
216216
})
217217
search_parameter_guide_highlight_1: |-
218218
client.index('movies').search('winter feast', {
219-
attributesToHighlight: ['overview']
219+
attributes_to_highlight: ['overview']
220220
})
221221
search_parameter_guide_matches_1: |-
222222
client.index('movies').search('winter feast', {
@@ -239,15 +239,15 @@ settings_guide_synonyms_1: |-
239239
})
240240
settings_guide_stop_words_1: |-
241241
client.index('movies').update_settings({
242-
stopWords: [
242+
stop_words: [
243243
'the',
244244
'a',
245245
'an'
246246
]
247247
})
248248
settings_guide_ranking_rules_1: |-
249249
client.index('movies').update_settings({
250-
rankingRules: [
250+
ranking_rules: [
251251
'words',
252252
'typo',
253253
'proximity',
@@ -262,15 +262,15 @@ settings_guide_distinct_1: |-
262262
client.index('jackets').update_distinct_attribute('product_id')
263263
settings_guide_searchable_1: |-
264264
client.index('movies').update_settings({
265-
searchableAttributes: [
265+
searchable_attributes: [
266266
'title',
267267
'description',
268268
'genre'
269269
]
270270
})
271271
settings_guide_displayed_1: |-
272272
client.index('movies').update_settings({
273-
displayedAttributes: [
273+
displayed_attributes: [
274274
'title',
275275
'description',
276276
'genre',
@@ -332,7 +332,7 @@ faceted_search_filter_1: |-
332332
})
333333
faceted_search_facets_distribution_1: |-
334334
client.index('movies').search('Batman', {
335-
facetsDistribution: ['genres']
335+
facets_distribution: ['genres']
336336
})
337337
faceted_search_walkthrough_filterable_attributes_1: |-
338338
client.index('movies').update_filterable_attributes([
@@ -347,7 +347,7 @@ faceted_search_walkthrough_filter_1: |-
347347
})
348348
faceted_search_walkthrough_facets_distribution_1: |-
349349
client.index('movies').search('Batman', {
350-
facetsDistribution: ['genres']
350+
facets_distribution: ['genres']
351351
})
352352
post_dump_1: |-
353353
client.create_dump

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ All the supported options are described in the [search parameters](https://docs.
124124
```ruby
125125
index.search(
126126
'wonder',
127-
attributesToHighlight: ['*']
127+
attributes_to_highlight: ['*']
128128
)
129129
```
130130

lib/meilisearch/http_request.rb

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ def http_delete(relative_path = '')
5454

5555
private
5656

57+
SNAKE_CASE = /[^a-zA-Z0-9]+(.)/.freeze
58+
5759
def send_request(http_method, relative_path, query_params = nil, body = nil)
5860
config = http_config(query_params, body)
5961
begin
@@ -65,7 +67,8 @@ def send_request(http_method, relative_path, query_params = nil, body = nil)
6567
end
6668

6769
def http_config(query_params, body)
68-
body = body.to_json
70+
body = transform_attributes(body).to_json
71+
6972
{
7073
headers: @headers,
7174
query: query_params,
@@ -75,6 +78,25 @@ def http_config(query_params, body)
7578
}.compact
7679
end
7780

81+
def transform_attributes(body)
82+
case body
83+
when Array
84+
body.map { |item| transform_attributes(item) }
85+
when Hash
86+
parse(body)
87+
else
88+
body
89+
end
90+
end
91+
92+
def parse(body)
93+
body
94+
.transform_keys(&:to_s)
95+
.transform_keys do |key|
96+
key.include?('_') ? key.downcase.gsub(SNAKE_CASE, &:upcase).gsub('_', '') : key
97+
end
98+
end
99+
78100
def validate(response)
79101
raise ApiError.new(response.code, response.message, response.body) unless response.success?
80102

spec/meilisearch/client/indexes_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,15 @@
126126
expect(@client.delete_index_if_exists(@uid6)).to eq(false)
127127
expect(@client.indexes.count).to eq(0)
128128
end
129+
130+
context 'with snake_case options' do
131+
it 'creates an index without errors' do
132+
uid = SecureRandom.uuid
133+
134+
expect do
135+
@client.create_index(uid, primary_key: @primary_key)
136+
@client.fetch_index(uid)
137+
end.to_not raise_error
138+
end
139+
end
129140
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe 'MeiliSearch::Client requests' do
4+
let(:key) { SecureRandom.uuid }
5+
6+
before(:each) do
7+
@client = MeiliSearch::Client.new(URL, MASTER_KEY)
8+
9+
expect(MeiliSearch::Client).to receive(:post)
10+
.with(kind_of(String), hash_including(body: "{\"primaryKey\":\"#{key}\",\"uid\":\"#{key}\"}"))
11+
.and_call_original
12+
end
13+
14+
it 'parses options when they are in a snake_case' do
15+
@client.create_index(key, primary_key: key)
16+
end
17+
18+
it 'parses options when they are in a different shape' do
19+
@client.create_index(key, priMARy_kEy: key)
20+
end
21+
end

spec/meilisearch/index/search/multi_params_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,22 @@
9595
expect(response['facetsDistribution']['genre']['fantasy']).to eq(1)
9696
expect(response['exhaustiveFacetsCount']).to be false
9797
end
98+
99+
context 'with snake_case options' do
100+
it 'does a custom search with attributes in a unusual formatting' do
101+
response = @index.search(
102+
'prince',
103+
{
104+
aTTributes_TO_Crop: ['title'],
105+
cropLength: 2,
106+
filter: 'genre = adventure',
107+
attributes_to_highlight: ['title']
108+
}
109+
)
110+
111+
expect(response['hits'].count).to be(1)
112+
expect(response['hits'].first).to have_key('_formatted')
113+
expect(response['hits'].first['_formatted']['title']).to eq('Petit <em>Prince</em>')
114+
end
115+
end
98116
end

0 commit comments

Comments
 (0)