naranya_ecm-sdk 0.0.14 → 0.0.15

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/naranya_ecm/behaviors/localizable.rb +27 -31
  3. data/lib/naranya_ecm/behaviors/mediable.rb +25 -0
  4. data/lib/naranya_ecm/behaviors/timestampable.rb +18 -15
  5. data/lib/naranya_ecm/cache/key.rb +32 -56
  6. data/lib/naranya_ecm/cache/methods.rb +50 -63
  7. data/lib/naranya_ecm/lifecycles/content_lifecycle.rb +39 -16
  8. data/lib/naranya_ecm/models/category.rb +11 -30
  9. data/lib/naranya_ecm/models/content.rb +73 -73
  10. data/lib/naranya_ecm/models/content_version.rb +50 -29
  11. data/lib/naranya_ecm/models/download_authorization.rb +22 -26
  12. data/lib/naranya_ecm/models/media_resource.rb +49 -15
  13. data/lib/naranya_ecm/rest/associations.rb +156 -0
  14. data/lib/naranya_ecm/rest/client.rb +4 -0
  15. data/lib/naranya_ecm/rest/errors.rb +53 -0
  16. data/lib/naranya_ecm/rest/finder_methods.rb +50 -0
  17. data/lib/naranya_ecm/rest/model.rb +215 -0
  18. data/lib/naranya_ecm/rest/persistence.rb +122 -0
  19. data/lib/naranya_ecm/rest/relation.rb +54 -0
  20. data/lib/naranya_ecm/search/hit.rb +19 -14
  21. data/lib/naranya_ecm/search/methods.rb +18 -20
  22. data/lib/naranya_ecm/search/query.rb +229 -230
  23. data/lib/naranya_ecm/search/results.rb +136 -139
  24. data/lib/naranya_ecm-sdk/version.rb +1 -1
  25. data/lib/naranya_ecm-sdk.rb +54 -13
  26. data/naranya_ecm-sdk.gemspec +1 -1
  27. data/spec/models/category_spec.rb +7 -2
  28. data/spec/models/content_spec.rb +11 -2
  29. data/spec/models/media_spec.rb +1 -1
  30. data/spec/spec_helper.rb +1 -1
  31. data/spec/support/naranya_ecms_shared_specs.rb +0 -12
  32. metadata +15 -19
  33. data/lib/naranya_ecm/behaviors/resourceable.rb +0 -22
  34. data/lib/naranya_ecm/behaviors.rb +0 -10
  35. data/lib/naranya_ecm/cache.rb +0 -9
  36. data/lib/naranya_ecm/has_many_patch.rb +0 -105
  37. data/lib/naranya_ecm/lifecycles/lifecycleable.rb +0 -43
  38. data/lib/naranya_ecm/lifecycles/version_lifecycle.rb +0 -75
  39. data/lib/naranya_ecm/lifecycles.rb +0 -10
  40. data/lib/naranya_ecm/models/embedded_hash.rb +0 -10
  41. data/lib/naranya_ecm/models/embedded_localized_hash.rb +0 -38
  42. data/lib/naranya_ecm/models/lifecycle.rb +0 -34
  43. data/lib/naranya_ecm/models.rb +0 -15
  44. data/lib/naranya_ecm/search.rb +0 -14
@@ -1,296 +1,295 @@
1
- module NaranyaEcm
2
- module Search
3
- class Query < Hash
4
- class << self
5
- def build_searchkick_like(term, options = {})
6
- if term.is_a?(Hash)
7
- options = term
8
- term = nil
9
- else
10
- term = term.to_s
11
- end
12
1
 
13
- fields =
14
- if options[:fields]
15
- if options[:autocomplete]
16
- options[:fields].map{|f| "#{f}.autocomplete" }
17
- else
18
- options[:fields].map do |value|
19
- k, v = value.is_a?(Hash) ? value.to_a.first : [value, :word]
20
- "#{k}.#{v == :word ? "analyzed" : v}"
21
- end
22
- end
2
+ module NaranyaEcm::Search
3
+ class Query < Hash
4
+ class << self
5
+ def build_searchkick_like(term, options = {})
6
+ if term.is_a?(Hash)
7
+ options = term
8
+ term = nil
9
+ else
10
+ term = term.to_s
11
+ end
12
+
13
+ fields =
14
+ if options[:fields]
15
+ if options[:autocomplete]
16
+ options[:fields].map{|f| "#{f}.autocomplete" }
23
17
  else
24
- ["_all"]
18
+ options[:fields].map do |value|
19
+ k, v = value.is_a?(Hash) ? value.to_a.first : [value, :word]
20
+ "#{k}.#{v == :word ? "analyzed" : v}"
21
+ end
25
22
  end
23
+ else
24
+ ["_all"]
25
+ end
26
26
 
27
- operator = options[:partial] ? "or" : "and"
27
+ operator = options[:partial] ? "or" : "and"
28
28
 
29
- # model and eagar loading
30
- load = options[:load].nil? ? true : options[:load]
31
- load = (options[:include] ? {include: options[:include]} : true) if load
29
+ # model and eagar loading
30
+ load = options[:load].nil? ? true : options[:load]
31
+ load = (options[:include] ? {include: options[:include]} : true) if load
32
32
 
33
- # pagination
34
- page = [options[:page].to_i, 1].max
35
- per_page = (options[:limit] || options[:per_page] || 10).to_i
36
- offset = options[:offset] || (page - 1) * per_page
33
+ # pagination
34
+ page = [options[:page].to_i, 1].max
35
+ per_page = (options[:limit] || options[:per_page] || 10).to_i
36
+ offset = options[:offset] || (page - 1) * per_page
37
37
 
38
- all = term == "*"
38
+ all = term == "*"
39
39
 
40
- if options[:query]
41
- payload = options[:query]
42
- elsif options[:similar]
40
+ if options[:query]
41
+ payload = options[:query]
42
+ elsif options[:similar]
43
+ payload = {
44
+ more_like_this: {
45
+ fields: fields,
46
+ like_text: term,
47
+ min_doc_freq: 1,
48
+ min_term_freq: 1,
49
+ analyzer: "searchkick_search2"
50
+ }
51
+ }
52
+ elsif all
53
+ payload = {
54
+ match_all: {}
55
+ }
56
+ else
57
+ if options[:autocomplete]
43
58
  payload = {
44
- more_like_this: {
59
+ multi_match: {
45
60
  fields: fields,
46
- like_text: term,
47
- min_doc_freq: 1,
48
- min_term_freq: 1,
49
- analyzer: "searchkick_search2"
61
+ query: term,
62
+ analyzer: "searchkick_autocomplete_search"
50
63
  }
51
64
  }
52
- elsif all
53
- payload = {
54
- match_all: {}
55
- }
56
65
  else
57
- if options[:autocomplete]
58
- payload = {
59
- multi_match: {
60
- fields: fields,
66
+ queries = []
67
+ fields.each do |field|
68
+ if field == "_all" or field.end_with?(".analyzed")
69
+ shared_options = {
70
+ fields: [field],
61
71
  query: term,
62
- analyzer: "searchkick_autocomplete_search"
72
+ use_dis_max: false,
73
+ operator: operator,
74
+ cutoff_frequency: 0.001
63
75
  }
64
- }
65
- else
66
- queries = []
67
- fields.each do |field|
68
- if field == "_all" or field.end_with?(".analyzed")
69
- shared_options = {
70
- fields: [field],
71
- query: term,
72
- use_dis_max: false,
73
- operator: operator,
74
- cutoff_frequency: 0.001
75
- }
76
+ queries.concat [
77
+ {multi_match: shared_options.merge(boost: 10, analyzer: "searchkick_search")},
78
+ {multi_match: shared_options.merge(boost: 10, analyzer: "searchkick_search2")}
79
+ ]
80
+ if options[:misspellings] != false
81
+ distance = (options[:misspellings].is_a?(Hash) && options[:misspellings][:distance]) || 1
76
82
  queries.concat [
77
- {multi_match: shared_options.merge(boost: 10, analyzer: "searchkick_search")},
78
- {multi_match: shared_options.merge(boost: 10, analyzer: "searchkick_search2")}
83
+ {multi_match: shared_options.merge(fuzziness: distance, max_expansions: 3, analyzer: "searchkick_search")},
84
+ {multi_match: shared_options.merge(fuzziness: distance, max_expansions: 3, analyzer: "searchkick_search2")}
79
85
  ]
80
- if options[:misspellings] != false
81
- distance = (options[:misspellings].is_a?(Hash) && options[:misspellings][:distance]) || 1
82
- queries.concat [
83
- {multi_match: shared_options.merge(fuzziness: distance, max_expansions: 3, analyzer: "searchkick_search")},
84
- {multi_match: shared_options.merge(fuzziness: distance, max_expansions: 3, analyzer: "searchkick_search2")}
85
- ]
86
- end
87
- else
88
- queries << {
89
- multi_match: {
90
- fields: [field],
91
- query: term,
92
- analyzer: "searchkick_autocomplete_search"
93
- }
94
- }
95
86
  end
96
- end
97
-
98
- payload = {
99
- dis_max: {
100
- queries: queries
87
+ else
88
+ queries << {
89
+ multi_match: {
90
+ fields: [field],
91
+ query: term,
92
+ analyzer: "searchkick_autocomplete_search"
93
+ }
101
94
  }
102
- }
95
+ end
103
96
  end
104
97
 
98
+ payload = {
99
+ dis_max: {
100
+ queries: queries
101
+ }
102
+ }
105
103
  end
106
104
 
107
- custom_filters = []
105
+ end
108
106
 
109
- if options[:boost]
110
- custom_filters << {
111
- filter: {
112
- exists: {
113
- field: options[:boost]
114
- }
115
- },
116
- script: "log(doc['#{options[:boost]}'].value + 2.718281828)"
117
- }
118
- end
107
+ custom_filters = []
119
108
 
120
- if custom_filters.any?
121
- payload = {
122
- custom_filters_score: {
123
- query: payload,
124
- filters: custom_filters,
125
- score_mode: "total"
109
+ if options[:boost]
110
+ custom_filters << {
111
+ filter: {
112
+ exists: {
113
+ field: options[:boost]
126
114
  }
127
- }
128
- end
115
+ },
116
+ script: "log(doc['#{options[:boost]}'].value + 2.718281828)"
117
+ }
118
+ end
129
119
 
120
+ if custom_filters.any?
130
121
  payload = {
131
- query: payload,
132
- size: per_page,
133
- from: offset
122
+ custom_filters_score: {
123
+ query: payload,
124
+ filters: custom_filters,
125
+ score_mode: "total"
126
+ }
134
127
  }
135
- payload[:explain] = options[:explain] if options[:explain]
128
+ end
136
129
 
137
- # order
138
- if options[:order]
139
- order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc}
140
- payload[:sort] = Hash[ order.map{|k, v| [k.to_s == "id" ? :_id : k, v] } ]
141
- end
130
+ payload = {
131
+ query: payload,
132
+ size: per_page,
133
+ from: offset
134
+ }
135
+ payload[:explain] = options[:explain] if options[:explain]
142
136
 
143
- term_filters =
144
- proc do |field, value|
145
- if value.is_a?(Array) # in query
146
- if value.any?
147
- {or: value.map{|v| term_filters.call(field, v) }}
148
- else
149
- {terms: {field => value}} # match nothing
150
- end
151
- elsif value.nil?
152
- {missing: {"field" => field, existence: true, null_value: true}}
137
+ # order
138
+ if options[:order]
139
+ order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc}
140
+ payload[:sort] = Hash[ order.map{|k, v| [k.to_s == "id" ? :_id : k, v] } ]
141
+ end
142
+
143
+ term_filters =
144
+ proc do |field, value|
145
+ if value.is_a?(Array) # in query
146
+ if value.any?
147
+ {or: value.map{|v| term_filters.call(field, v) }}
153
148
  else
154
- {term: {field => value}}
149
+ {terms: {field => value}} # match nothing
155
150
  end
151
+ elsif value.nil?
152
+ {missing: {"field" => field, existence: true, null_value: true}}
153
+ else
154
+ {term: {field => value}}
156
155
  end
156
+ end
157
157
 
158
- # where
159
- where_filters =
160
- proc do |where|
161
- filters = []
162
- (where || {}).each do |field, value|
163
- field = :_id if field.to_s == "id"
158
+ # where
159
+ where_filters =
160
+ proc do |where|
161
+ filters = []
162
+ (where || {}).each do |field, value|
163
+ field = :_id if field.to_s == "id"
164
164
 
165
- if field == :or
166
- value.each do |or_clause|
167
- filters << {or: or_clause.map{|or_statement| {and: where_filters.call(or_statement)} }}
168
- end
169
- else
170
- # expand ranges
171
- if value.is_a?(Range)
172
- value = {gte: value.first, (value.exclude_end? ? :lt : :lte) => value.last}
173
- end
165
+ if field == :or
166
+ value.each do |or_clause|
167
+ filters << {or: or_clause.map{|or_statement| {and: where_filters.call(or_statement)} }}
168
+ end
169
+ else
170
+ # expand ranges
171
+ if value.is_a?(Range)
172
+ value = {gte: value.first, (value.exclude_end? ? :lt : :lte) => value.last}
173
+ end
174
174
 
175
- if value.is_a?(Hash)
176
- if value[:near]
177
- filters << {
178
- geo_distance: {
179
- field => value.delete(:near).map(&:to_f).reverse,
180
- distance: value.delete(:within) || "50mi"
181
- }
175
+ if value.is_a?(Hash)
176
+ if value[:near]
177
+ filters << {
178
+ geo_distance: {
179
+ field => value.delete(:near).map(&:to_f).reverse,
180
+ distance: value.delete(:within) || "50mi"
182
181
  }
183
- end
182
+ }
183
+ end
184
184
 
185
- if value[:top_left]
186
- filters << {
187
- geo_bounding_box: {
188
- field => {
189
- top_left: value.delete(:top_left).map(&:to_f).reverse,
190
- bottom_right: value.delete(:bottom_right).map(&:to_f).reverse
191
- }
185
+ if value[:top_left]
186
+ filters << {
187
+ geo_bounding_box: {
188
+ field => {
189
+ top_left: value.delete(:top_left).map(&:to_f).reverse,
190
+ bottom_right: value.delete(:bottom_right).map(&:to_f).reverse
192
191
  }
193
192
  }
194
- end
193
+ }
194
+ end
195
195
 
196
- value.each do |op, op_value|
197
- if op == :not # not equal
198
- filters << {not: term_filters.call(field, op_value)}
199
- elsif op == :all
200
- filters << {terms: {field => op_value, execution: "and"}}
201
- else
202
- range_query =
203
- case op
204
- when :gt
205
- {from: op_value, include_lower: false}
206
- when :gte
207
- {from: op_value, include_lower: true}
208
- when :lt
209
- {to: op_value, include_upper: false}
210
- when :lte
211
- {to: op_value, include_upper: true}
212
- else
213
- raise "Unknown where operator"
214
- end
215
- filters << {range: {field => range_query}}
216
- end
196
+ value.each do |op, op_value|
197
+ if op == :not # not equal
198
+ filters << {not: term_filters.call(field, op_value)}
199
+ elsif op == :all
200
+ filters << {terms: {field => op_value, execution: "and"}}
201
+ else
202
+ range_query =
203
+ case op
204
+ when :gt
205
+ {from: op_value, include_lower: false}
206
+ when :gte
207
+ {from: op_value, include_lower: true}
208
+ when :lt
209
+ {to: op_value, include_upper: false}
210
+ when :lte
211
+ {to: op_value, include_upper: true}
212
+ else
213
+ raise "Unknown where operator"
214
+ end
215
+ filters << {range: {field => range_query}}
217
216
  end
218
- else
219
- filters << term_filters.call(field, value)
220
217
  end
218
+ else
219
+ filters << term_filters.call(field, value)
221
220
  end
222
221
  end
223
- filters
224
222
  end
225
-
226
- # filters
227
- filters = where_filters.call(options[:where])
228
- if filters.any?
229
- payload[:filter] = {
230
- and: filters
231
- }
223
+ filters
232
224
  end
233
225
 
234
- # facets
235
- facet_limits = {}
236
- if options[:facets]
237
- facets = options[:facets] || {}
238
- if facets.is_a?(Array) # convert to more advanced syntax
239
- facets = Hash[ facets.map{|f| [f, {}] } ]
240
- end
226
+ # filters
227
+ filters = where_filters.call(options[:where])
228
+ if filters.any?
229
+ payload[:filter] = {
230
+ and: filters
231
+ }
232
+ end
241
233
 
242
- payload[:facets] = {}
243
- facets.each do |field, facet_options|
244
- # ask for extra facets due to
245
- # https://github.com/elasticsearch/elasticsearch/issues/1305
234
+ # facets
235
+ facet_limits = {}
236
+ if options[:facets]
237
+ facets = options[:facets] || {}
238
+ if facets.is_a?(Array) # convert to more advanced syntax
239
+ facets = Hash[ facets.map{|f| [f, {}] } ]
240
+ end
246
241
 
247
- if facet_options[:ranges]
248
- payload[:facets][field] = {
249
- range: {
250
- field.to_sym => facet_options[:ranges]
251
- }
242
+ payload[:facets] = {}
243
+ facets.each do |field, facet_options|
244
+ # ask for extra facets due to
245
+ # https://github.com/elasticsearch/elasticsearch/issues/1305
246
+
247
+ if facet_options[:ranges]
248
+ payload[:facets][field] = {
249
+ range: {
250
+ field.to_sym => facet_options[:ranges]
252
251
  }
253
- else
254
- payload[:facets][field] = {
255
- terms: {
256
- field: field,
257
- size: facet_options[:limit] ? facet_options[:limit] + 150 : 100000
258
- }
252
+ }
253
+ else
254
+ payload[:facets][field] = {
255
+ terms: {
256
+ field: field,
257
+ size: facet_options[:limit] ? facet_options[:limit] + 150 : 100000
259
258
  }
260
- end
259
+ }
260
+ end
261
261
 
262
- facet_limits[field] = facet_options[:limit] if facet_options[:limit]
262
+ facet_limits[field] = facet_options[:limit] if facet_options[:limit]
263
263
 
264
- # offset is not possible
265
- # http://elasticsearch-users.115913.n3.nabble.com/Is-pagination-possible-in-termsStatsFacet-td3422943.html
264
+ # offset is not possible
265
+ # http://elasticsearch-users.115913.n3.nabble.com/Is-pagination-possible-in-termsStatsFacet-td3422943.html
266
266
 
267
- facet_filters = where_filters.call(facet_options[:where])
268
- if facet_filters.any?
269
- payload[:facets][field][:facet_filter] = {
270
- and: {
271
- filters: facet_filters
272
- }
267
+ facet_filters = where_filters.call(facet_options[:where])
268
+ if facet_filters.any?
269
+ payload[:facets][field][:facet_filter] = {
270
+ and: {
271
+ filters: facet_filters
273
272
  }
274
- end
273
+ }
275
274
  end
276
275
  end
276
+ end
277
277
 
278
- # highlight
279
- if options[:highlight]
280
- payload[:highlight] = {
281
- fields: Hash[ fields.map{|f| [f, {}] } ]
282
- }
283
- if options[:highlight].is_a?(Hash) and tag = options[:highlight][:tag]
284
- payload[:highlight][:pre_tags] = [tag]
285
- payload[:highlight][:post_tags] = [tag.to_s.gsub(/\A</, "</")]
286
- end
278
+ # highlight
279
+ if options[:highlight]
280
+ payload[:highlight] = {
281
+ fields: Hash[ fields.map{|f| [f, {}] } ]
282
+ }
283
+ if options[:highlight].is_a?(Hash) and tag = options[:highlight][:tag]
284
+ payload[:highlight][:pre_tags] = [tag]
285
+ payload[:highlight][:post_tags] = [tag.to_s.gsub(/\A</, "</")]
287
286
  end
287
+ end
288
288
 
289
- payload[:_source] = 'updated_at'
289
+ payload[:_source] = 'updated_at'
290
290
 
291
- self.new.merge payload
292
- end
291
+ self.new.merge payload
293
292
  end
294
293
  end
295
294
  end
296
- end
295
+ end