sunspot 2.4.0 → 2.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 385375ab001841dcd220a07df21307f581e5ed8d4c41c6907e4d2f05783259e5
4
- data.tar.gz: 0cd9f3eb2a5225b46429988a7a9d10f2ecbd488fd2c824448831a5f908a69c75
3
+ metadata.gz: 179de5f5261bdb69d21038a0b2e36fbd2812e1fc71ef4c1efd77979a03e58179
4
+ data.tar.gz: 1f7f40d9737400cf61c23515c61ebde70140b1c1bf9df800d7e19ce27c3cbd0d
5
5
  SHA512:
6
- metadata.gz: 97c5760b633b1ab3cbfb8a04a3dd49e9c0bd40485151c94b5c8196104a2b0fc47f1fdd97ff2d85b738c4d225820316dc1e42cceb5a19ea8c7f084a9b82e224f0
7
- data.tar.gz: 6ca3b17c3c28f89f56160ebdbaf2c924103976eb939df6832f0755d30a368c757dd912b5491b9a84caf38498e8320252ad14d59cd86ca4e8d071e3b2d95518e1
6
+ metadata.gz: ad59d5868f3461648d29c77b6368d7c5145ef6247ecca38878bf4f03bb3d2ab73fea2decf629936d58282b8067345198f6bff82be1347bb0cc92cb4537722d28
7
+ data.tar.gz: 3c4fd67940331fbdacffd665ca624119038bf12da2aa2b041adbd8260aef3921660b83803a912cf81384c7269f6b46d3b7fad1c883c34e1a1ba2ccbade2fd6dc
@@ -63,7 +63,10 @@ module Sunspot
63
63
  # String:: ID for use in Solr
64
64
  #
65
65
  def index_id #:nodoc:
66
- InstanceAdapter.index_id_for(@instance.class.name, id)
66
+ setup = Sunspot::Setup.for(@instance.class)
67
+ id_prefix = setup ? setup.id_prefix_for(@instance) : nil
68
+
69
+ InstanceAdapter.index_id_for("#{id_prefix}#{@instance.class.name}", id)
67
70
  end
68
71
 
69
72
  class <<self
@@ -55,6 +55,22 @@ module Sunspot
55
55
  @setup.add_document_boost(attr_name, &block)
56
56
  end
57
57
 
58
+ #
59
+ # If you use the compositeId router for shards, you can send documents
60
+ # with a prefix in the document ID which will be used to calculate the
61
+ # hash Solr uses to determine the shard a document is sent to for indexing.
62
+ # The prefix can be anything you’d like it to be (it doesn’t have to be
63
+ # the shard name, for example), but it must be consistent so Solr
64
+ # behaves consistently.
65
+ #
66
+ # ==== Parameters
67
+ #
68
+ # attr_name<Symbol,String>:: Attribute name to call or a string constant
69
+ #
70
+ def id_prefix(attr_name = nil, &block)
71
+ @setup.add_id_prefix(attr_name, &block)
72
+ end
73
+
58
74
  # method_missing is used to provide access to typed fields, because
59
75
  # developers should be able to add new Sunspot::Type implementations
60
76
  # dynamically and have them recognized inside the Fields DSL. Like #text,
@@ -17,6 +17,10 @@ module Sunspot
17
17
  # Class name of object associated with this hit, as string.
18
18
  #
19
19
  attr_reader :class_name
20
+ #
21
+ # ID prefix used for compositeId shard router
22
+ #
23
+ attr_reader :id_prefix
20
24
  #
21
25
  # Keyword relevance score associated with this result. Nil if this hit
22
26
  # is not from a keyword search.
@@ -27,7 +31,8 @@ module Sunspot
27
31
  attr_writer :result #:nodoc:
28
32
 
29
33
  def initialize(raw_hit, highlights, search) #:nodoc:
30
- @class_name, @primary_key = *raw_hit['id'].match(/([^ ]+) (.+)/)[1..2]
34
+ @id_prefix, @class_name, @primary_key =
35
+ *raw_hit['id'].match(/((?:[^!]+!)+)*([^\s]+)\s(.+)/)[1..3]
31
36
  @score = raw_hit['score']
32
37
  @search = search
33
38
  @stored_values = raw_hit
@@ -259,7 +259,7 @@ module Sunspot
259
259
  read_timeout: config.solr.read_timeout,
260
260
  open_timeout: config.solr.open_timeout,
261
261
  proxy: config.solr.proxy,
262
- update_format: config.solr.update_format || :xml
262
+ update_format: update_format_generator
263
263
  )
264
264
  end
265
265
 
@@ -277,5 +277,11 @@ module Sunspot
277
277
  CompositeSetup.for(types)
278
278
  end
279
279
  end
280
+
281
+ def update_format_generator
282
+ if config.solr.update_format && RSolr.version.to_i > 1
283
+ config.solr.update_format.downcase.to_sym == :json ? RSolr::JSON::Generator : RSolr::Xml::Generator
284
+ end
285
+ end
280
286
  end
281
287
  end
@@ -15,6 +15,7 @@ module Sunspot
15
15
  @more_like_this_field_factories_cache = Hash.new { |h, k| h[k] = [] }
16
16
  @dsl = DSL::Fields.new(self)
17
17
  @document_boost_extractor = nil
18
+ @id_prefix_extractor = nil
18
19
  add_field_factory(:class, Type::ClassType.instance)
19
20
  end
20
21
 
@@ -61,6 +62,7 @@ module Sunspot
61
62
  field_factory = FieldFactory::Static.new(name, Type::TextType.instance, options, &block)
62
63
  @text_field_factories[name] = field_factory
63
64
  @text_field_factories_cache[field_factory.name] = field_factory
65
+ @field_factories_cache[field_factory.name] = field_factory
64
66
  if stored
65
67
  @stored_field_factories_cache[field_factory.name] << field_factory
66
68
  end
@@ -81,6 +83,7 @@ module Sunspot
81
83
  field_factory = FieldFactory::Dynamic.new(name, type, options, &block)
82
84
  @dynamic_field_factories[field_factory.signature] = field_factory
83
85
  @dynamic_field_factories_cache[field_factory.name] = field_factory
86
+ @field_factories_cache[field_factory.name] = field_factory
84
87
  if stored
85
88
  @stored_field_factories_cache[field_factory.name] << field_factory
86
89
  end
@@ -107,6 +110,24 @@ module Sunspot
107
110
  end
108
111
  end
109
112
 
113
+ #
114
+ # Add id prefix for compositeId router
115
+ #
116
+ def add_id_prefix(attr_name, &block)
117
+ @id_prefix_extractor =
118
+ case attr_name
119
+ when Symbol
120
+ DataExtractor::AttributeExtractor.new(attr_name)
121
+ when String
122
+ DataExtractor::Constant.new(attr_name)
123
+ when nil
124
+ DataExtractor::BlockExtractor.new(&block) if block_given?
125
+ else
126
+ raise ArgumentError,
127
+ "The ID prefix has to be either a Symbol, a String or a Proc"
128
+ end
129
+ end
130
+
110
131
  #
111
132
  # Builder method for evaluating the setup DSL
112
133
  #
@@ -271,6 +292,16 @@ module Sunspot
271
292
  end
272
293
  end
273
294
 
295
+ def id_prefix_for(model)
296
+ if @id_prefix_extractor
297
+ value = @id_prefix_extractor.value_for(model)
298
+
299
+ if value.is_a?(String) and value.size > 0
300
+ value[-1] == "!" ? value : "#{value}!"
301
+ end
302
+ end
303
+ end
304
+
274
305
  protected
275
306
 
276
307
  #
@@ -1,3 +1,3 @@
1
1
  module Sunspot
2
- VERSION = '2.4.0'
2
+ VERSION = '2.5.0'
3
3
  end
@@ -20,6 +20,19 @@ describe Sunspot::Adapters::InstanceAdapter do
20
20
  Sunspot::Adapters::InstanceAdapter::for(UnseenModel)
21
21
  expect(Sunspot::Adapters::InstanceAdapter::registered_adapter_for(UnseenModel)).to be(AbstractModelInstanceAdapter)
22
22
  end
23
+
24
+ it "appends ID prefix when configured" do
25
+ expect(AbstractModelInstanceAdapter.new(ModelWithPrefixId.new).index_id).to eq "USERDATA!ModelWithPrefixId 1"
26
+ end
27
+
28
+ it "supports nested ID prefixes" do
29
+ expect(AbstractModelInstanceAdapter.
30
+ new(ModelWithNestedPrefixId.new).index_id).to eq "USER!USERDATA!ModelWithNestedPrefixId 1"
31
+ end
32
+
33
+ it "doesn't appends ID prefix when not configured" do
34
+ expect(AbstractModelInstanceAdapter.new(ModelWithoutPrefixId.new).index_id).to eq "ModelWithoutPrefixId 1"
35
+ end
23
36
  end
24
37
 
25
38
  describe Sunspot::Adapters::DataAccessor do
@@ -12,6 +12,20 @@ describe 'hits', :type => :search do
12
12
  end).to eq([['Post', post_1.id.to_s], ['Post', post_2.id.to_s]])
13
13
  end
14
14
 
15
+ it "should return ID prefix when used with compositeId shard router" do
16
+ Sunspot.index!(ModelWithPrefixId.new)
17
+
18
+ expect(Sunspot.search(ModelWithPrefixId).
19
+ hits.map { |h| h.id_prefix }.uniq).to eq ["USERDATA!"]
20
+ end
21
+
22
+ it "should parse nested ID prefixes" do
23
+ Sunspot.index!(ModelWithNestedPrefixId.new)
24
+
25
+ expect(Sunspot.search(ModelWithNestedPrefixId).
26
+ hits.map { |h| h.id_prefix }.uniq).to eq ["USER!USERDATA!"]
27
+ end
28
+
15
29
  it 'returns search total as attribute of hits' do
16
30
  stub_results(Post.new, 4)
17
31
  expect(session.search(Post) do
@@ -24,6 +24,9 @@ describe Sunspot do
24
24
  config_before_reset = Sunspot.config
25
25
  Sunspot.reset!(true)
26
26
  expect(Sunspot.config).to eq(config_before_reset)
27
+
28
+ # Restore sunspot config after test
29
+ Sunspot.reset!(false)
27
30
  end
28
31
  end
29
32
  end
@@ -31,6 +31,22 @@ describe 'fields lists' do
31
31
  end
32
32
  end
33
33
 
34
+ it 'does not raise Sunspot::UnrecognizedFieldError when listing existing text fields' do
35
+ expect do
36
+ Sunspot.search(Post) {
37
+ field_list(:body)
38
+ }
39
+ end.to_not raise_error
40
+ end
41
+
42
+ it 'does raise Sunspot::UnrecognizedFieldError when listing a non-existent text fields' do
43
+ expect do
44
+ Sunspot.search(Post) {
45
+ field_list(:bogus_body)
46
+ }
47
+ end.to raise_error(Sunspot::UnrecognizedFieldError)
48
+ end
49
+
34
50
  it 'does not load any stored fields' do
35
51
  hit = Sunspot.search(Post) { without_stored_fields }.hits.first
36
52
 
@@ -7,7 +7,40 @@ end
7
7
  class UnseenModel < AbstractModel
8
8
  end
9
9
 
10
+ class ModelWithPrefixId < AbstractModel
11
+ def id
12
+ 1
13
+ end
14
+ end
15
+
16
+ Sunspot.setup(ModelWithPrefixId) do
17
+ id_prefix { "USERDATA!" }
18
+ end
19
+
20
+ class ModelWithNestedPrefixId < AbstractModel
21
+ def id
22
+ 1
23
+ end
24
+ end
25
+
26
+ Sunspot.setup(ModelWithNestedPrefixId) do
27
+ id_prefix { "USER!USERDATA!" }
28
+ end
29
+
30
+ class ModelWithoutPrefixId < AbstractModel
31
+ def id
32
+ 1
33
+ end
34
+ end
35
+
36
+ Sunspot.setup(ModelWithoutPrefixId) do
37
+ end
38
+
39
+
10
40
  class AbstractModelInstanceAdapter < Sunspot::Adapters::InstanceAdapter
41
+ def id
42
+ @instance.id
43
+ end
11
44
  end
12
45
 
13
46
  class AbstractModelDataAccessor < Sunspot::Adapters::DataAccessor
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sunspot
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mat Brown
@@ -30,7 +30,7 @@ authors:
30
30
  autorequire:
31
31
  bindir: bin
32
32
  cert_chain: []
33
- date: 2019-07-05 00:00:00.000000000 Z
33
+ date: 2019-07-12 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rsolr