stub_solr 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rubocop.yml +27 -0
- data/.travis.yml +12 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +79 -0
- data/Rakefile +37 -0
- data/dev_tasks/release.rake +4 -0
- data/dev_tasks/spec.rake +107 -0
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails-5.0.0.1 +22 -0
- data/lib/stub_solr/sunspot_rails_stub_session_proxy.rb +363 -0
- data/lib/stub_solr/version.rb +3 -0
- data/lib/stub_solr.rb +9 -0
- data/stub_solr.gemspec +32 -0
- metadata +171 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0dfd9c8199e4ab5c50789791f3149ed9e2c89aac
|
4
|
+
data.tar.gz: e9ac7ef59532089aabee78d66df601068287b42c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: edcf6aaa16e0bbdca4f64e9ee76a3c1599d320461214d67c17063f682b9a392ee9df14dcd14709d3900294b023a8171e9515896fffeea9b515d298cf6c8d50dd
|
7
|
+
data.tar.gz: 13badb963b7b8303ea4476d99e379622e1b9b22c0be94ef345cfd0b011637eea64b09974702b67a23ff55d3a9600238d16f4fe5252dd62284aaea3b57bff9af0
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
AllCops:
|
3
|
+
Exclude:
|
4
|
+
- bin/**/*
|
5
|
+
- dev_tasks/*
|
6
|
+
- gemfiels/*
|
7
|
+
- test/**/*
|
8
|
+
- tmp/**/*
|
9
|
+
TargetRubyVersion: 2.3
|
10
|
+
|
11
|
+
Rails:
|
12
|
+
Enabled: true
|
13
|
+
|
14
|
+
DotPosition:
|
15
|
+
EnforcedStyle: trailing
|
16
|
+
|
17
|
+
Style/EmptyLinesAroundBlockBody:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
Style/EmptyLinesAroundModuleBody:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Style/EmptyLinesAroundClassBody:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
Style/EmptyLinesAroundMethodBody:
|
27
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Jaigouk Kim
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# StubSolr
|
2
|
+
|
3
|
+
`Sunspot.session = Sunspot::Rails::StubSessionProxy.new(Sunspot.session)` is enough for most of cases but if you want more than `allow_any_instance_of(Sunspot::Rails::StubSessionProxy::Search).to receive(:results).and_return(myExpectedResults)` this gem can be helpful. `kaminari` for pagination and plain AR to mimic resutls.
|
4
|
+
|
5
|
+
this gem depends on `2.2.6` version of sunspot, sunspot_rails.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'stub_solr'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install stub_solr
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
`test_helper` file should have `require 'stub_solr'`. In your test file, add setup and teardown like this
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
class ActivitiesControllerTest < ActionDispatch::IntegrationTest
|
29
|
+
def setup
|
30
|
+
Sunspot.session = Sunspot::Rails::StubSessionProxy.new(
|
31
|
+
Sunspot.session, Activity.all.to_a.concat(Excercise.all.to_a)
|
32
|
+
)
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def teardown
|
37
|
+
Sunspot.session = ::Sunspot.session.original_session
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
test 'search with filter' do
|
42
|
+
get search_activities_url(params: { visible: true, search: 'beer' })
|
43
|
+
expected = Activity.where(visible: true).where("title LIKE ?", "%beer%")
|
44
|
+
res = ActiveSupport::JSON.decode(response.body)["activities"]
|
45
|
+
res.size.must_equal expected.size
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
For searching, it finds all string / text fields for given classes and use them.
|
51
|
+
|
52
|
+
For range search like `greater_than`, it uses array to check an attribute is for range search. by default, it's `%w[time month created_at start end]` but you can change that.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
def setup
|
56
|
+
Sunspot.session = Sunspot::Rails::StubSessionProxy.new(
|
57
|
+
Sunspot.session, Activity.all.to_a.concat(Excercise.all.to_a)
|
58
|
+
)
|
59
|
+
Sunspot.session.set_range_fields(%w[time month created_at departure arrival])
|
60
|
+
super
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
|
65
|
+
## Development
|
66
|
+
|
67
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
68
|
+
|
69
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/jaigouk/stub_solr.
|
74
|
+
|
75
|
+
|
76
|
+
## License
|
77
|
+
|
78
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
79
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/file_list'
|
4
|
+
|
5
|
+
TO_CLEAN = Rake::FileList.new do |fl|
|
6
|
+
fl.include 'tmp/**/*'
|
7
|
+
fl.include '**/.bundle'
|
8
|
+
fl.exclude 'tmp/.gitkeep'
|
9
|
+
end
|
10
|
+
|
11
|
+
CLEAN.include TO_CLEAN
|
12
|
+
|
13
|
+
task :environment do
|
14
|
+
end
|
15
|
+
|
16
|
+
FileList['dev_tasks/*.rake'].each { |file| load(file) }
|
17
|
+
task :default => [:spec]
|
18
|
+
|
19
|
+
desc 'Install bleeding edge gems locally'
|
20
|
+
task :install do
|
21
|
+
system "rm *.gem"
|
22
|
+
system "gem build *.gemspec"
|
23
|
+
system "gem install *.gem"
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'Release to Rubygems.org'
|
27
|
+
task :release do
|
28
|
+
require File.expand_path('../lib/stub_solr/version', __FILE__)
|
29
|
+
|
30
|
+
version_tag = "v#{StubSolr::VERSION}"
|
31
|
+
system "git tag -am 'Release version #{StubSolr::VERSION}' '#{version_tag}'"
|
32
|
+
system "git push origin #{version_tag}:#{version_tag}"
|
33
|
+
|
34
|
+
system "gem build stub_solr.gemspec"
|
35
|
+
system "gem push stub_solr-#{StubSolr::VERSION}.gem"
|
36
|
+
FileUtils.rm("stub_solr-#{StubSolr::VERSION}.gem")
|
37
|
+
end
|
data/dev_tasks/spec.rake
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
desc 'Run spec suite in all Rails versions'
|
5
|
+
task :spec do
|
6
|
+
puts "Running default task"
|
7
|
+
versions = if ENV['RAILS']
|
8
|
+
ENV['RAILS'].split(",")
|
9
|
+
else
|
10
|
+
rails_all_versions
|
11
|
+
end
|
12
|
+
|
13
|
+
versions.each do |version|
|
14
|
+
puts "Running specs against Rails #{version}..."
|
15
|
+
|
16
|
+
ENV['VERSION'] = version
|
17
|
+
reenable_spec_tasks
|
18
|
+
Rake::Task['spec:run_with_rails'].invoke
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
namespace :spec do
|
24
|
+
def rails_app_path(version)
|
25
|
+
File.join(File.dirname(__FILE__), "..", "tmp", "rails_#{version.gsub(".", "_")}_app")
|
26
|
+
end
|
27
|
+
|
28
|
+
def gemfile_path(version)
|
29
|
+
File.join(File.dirname(__FILE__), "..", "gemfiles", "rails-#{version}")
|
30
|
+
end
|
31
|
+
|
32
|
+
def vendor_path(version)
|
33
|
+
File.expand_path("vendor/bundle", rails_app_path(version))
|
34
|
+
end
|
35
|
+
|
36
|
+
def rails_template_path
|
37
|
+
File.join(File.dirname(__FILE__), "..", "test", "rails_template")
|
38
|
+
end
|
39
|
+
|
40
|
+
def version
|
41
|
+
ENV['VERSION']
|
42
|
+
end
|
43
|
+
|
44
|
+
task :run_with_rails => [:set_gemfile, :generate_rails_app, :initialize_database, :setup_rails_app, :run]
|
45
|
+
|
46
|
+
task :set_gemfile do
|
47
|
+
ENV['BUNDLE_PATH'] = vendor_path(version)
|
48
|
+
ENV['BUNDLE_GEMFILE'] = gemfile_path(version)
|
49
|
+
unless File.exist?(ENV['BUNDLE_PATH'])
|
50
|
+
puts "Installing gems for Rails #{version} (this will only be done once)..."
|
51
|
+
sh("bundle install #{ENV['BUNDLE_ARGS']}") || exit(1)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
task :generate_rails_app do
|
56
|
+
app_path = rails_app_path(version)
|
57
|
+
|
58
|
+
unless File.exist?(File.expand_path("config/environment.rb", app_path))
|
59
|
+
puts "Generating Rails #{version} application..."
|
60
|
+
sh("bundle exec rails _#{version}_ new \"#{app_path}\" --force --skip-git --skip-javascript --skip-gemfile --skip-sprockets") || exit(1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
task :initialize_database do
|
65
|
+
if ENV['DB'] == 'postgres'
|
66
|
+
sh "bundle exec rake db:test:prepare"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
task :setup_rails_app do
|
71
|
+
FileUtils.cp_r File.join(rails_template_path, "."), rails_app_path(version)
|
72
|
+
end
|
73
|
+
|
74
|
+
# task :load_fixtures do
|
75
|
+
# puts "loading fixtures..."
|
76
|
+
# sh "bundle exec rake db:fixtures:load RAILS_ENV=test FIXTURES_DIR='test/fixtures'"
|
77
|
+
# end
|
78
|
+
|
79
|
+
task :run do
|
80
|
+
ENV['BUNDLE_GEMFILE'] = gemfile_path(version)
|
81
|
+
ENV['RAILS_ROOT'] = rails_app_path(version)
|
82
|
+
|
83
|
+
sh "bundle exec ruby -I test #{ENV['SPEC'] || 'test/*_spec.rb'}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
def rails_all_versions
|
89
|
+
versions = []
|
90
|
+
puts "getting rails versions to test"
|
91
|
+
Dir.glob(File.join(File.dirname(__FILE__), "..", "gemfiles", "rails-*")).each do |gemfile|
|
92
|
+
if !gemfile.end_with?(".lock") && gemfile =~ /rails-([0-9.]+)/
|
93
|
+
versions << $1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
puts versions.to_s
|
98
|
+
versions
|
99
|
+
end
|
100
|
+
|
101
|
+
def reenable_spec_tasks
|
102
|
+
Rake::Task.tasks.each do |task|
|
103
|
+
if task.name =~ /spec:/
|
104
|
+
task.reenable
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gem 'rails', '~> 5.0.0.1'
|
3
|
+
gem 'sunspot', '2.2.6'
|
4
|
+
gem 'sunspot_solr', '2.2.6'
|
5
|
+
gem 'sunspot_rails', '2.2.6'
|
6
|
+
gem 'kaminari'
|
7
|
+
gem 'rake', '11.2.0'
|
8
|
+
|
9
|
+
group :test do
|
10
|
+
gem 'minitest-rails'
|
11
|
+
gem 'minitest-reporters'
|
12
|
+
gem 'byebug'
|
13
|
+
gem 'stub_solr', :path => File.expand_path('../..', __FILE__)
|
14
|
+
end
|
15
|
+
|
16
|
+
group :postgres do
|
17
|
+
gem 'pg'
|
18
|
+
end
|
19
|
+
|
20
|
+
group :sqlite do
|
21
|
+
gem 'sqlite3'
|
22
|
+
end
|
@@ -0,0 +1,363 @@
|
|
1
|
+
|
2
|
+
# stub solr with "dara" array for testing.
|
3
|
+
# if there is no data then it will behave like default blank search
|
4
|
+
# this stub uses Kaminari for pagination
|
5
|
+
# once the data is given, solr search block will call search
|
6
|
+
# and that will create a new Search with arguments.
|
7
|
+
# With the search, it passes the given data as @operation_context.
|
8
|
+
# And "run_proc_block" method will go through each search conditions
|
9
|
+
# in the block. while going through the block, it will change @operation_context
|
10
|
+
#
|
11
|
+
class Sunspot::Rails::StubSessionProxy
|
12
|
+
attr_reader :block, :data, :range_fields
|
13
|
+
|
14
|
+
def initialize(original_session, data = [])
|
15
|
+
@original_session = original_session
|
16
|
+
@data = data
|
17
|
+
@range_fields = %w[time month created_at start end]
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_range_fields(arr)
|
21
|
+
@range_fields = arr
|
22
|
+
end
|
23
|
+
|
24
|
+
def search(*types, &block)
|
25
|
+
Search.new(@data, types, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
# with and fulltext can be called multiple times
|
29
|
+
# based on the block. that's why i am mutating @results
|
30
|
+
#
|
31
|
+
# for all and any block, we need to consult sunspot/lib/sunspot/dsl/standard_query.rb
|
32
|
+
#
|
33
|
+
class Search
|
34
|
+
attr_reader :block, :types, :page, :per_page, :grouped_results
|
35
|
+
def initialize(results = [], types = [], &block)
|
36
|
+
@facets = {}
|
37
|
+
@search_data = results
|
38
|
+
@block = block
|
39
|
+
@types = types
|
40
|
+
@page = 1
|
41
|
+
@per_page = 30
|
42
|
+
@grouped_results = {}
|
43
|
+
@group_key = ""
|
44
|
+
@range_search_field = nil
|
45
|
+
@operation_context = [{operation: "all", result: @search_data}]
|
46
|
+
@current_context_index = 0
|
47
|
+
@order_key = nil
|
48
|
+
@order_direction = nil
|
49
|
+
@textsearch_priorities = {}
|
50
|
+
@search_term = ""
|
51
|
+
run_proc_block
|
52
|
+
end
|
53
|
+
|
54
|
+
def final_results
|
55
|
+
@operation_context.last[:result]
|
56
|
+
end
|
57
|
+
|
58
|
+
def results
|
59
|
+
return PaginatedCollection.new if sorted_temp_result.empty?
|
60
|
+
return sorted_temp_result if final_results.is_a? Kaminari::PaginatableArray
|
61
|
+
Kaminari.paginate_array(sorted_temp_result).page(@page).per(@per_page)
|
62
|
+
end
|
63
|
+
|
64
|
+
def any_of(&bl)
|
65
|
+
previous_result = result_for_current_context
|
66
|
+
@operation_context.push({operation: "any", result: previous_result, temp_result: []})
|
67
|
+
@current_context_index += 1
|
68
|
+
|
69
|
+
Sunspot::Util::ContextBoundDelegate.instance_eval_with_context(self, &bl)
|
70
|
+
after_results = @operation_context[@current_context_index][:temp_result]
|
71
|
+
|
72
|
+
parent_temp_result = @operation_context[@current_context_index - 1][:temp_result]
|
73
|
+
|
74
|
+
|
75
|
+
unless @current_context_index == 0
|
76
|
+
@current_context_index -= 1
|
77
|
+
@operation_context.pop
|
78
|
+
end
|
79
|
+
# parent is now current context
|
80
|
+
if parent_temp_result
|
81
|
+
@operation_context[@current_context_index][:temp_result] = parent_temp_result.concat(after_results)
|
82
|
+
else
|
83
|
+
@operation_context[@current_context_index][:result] = after_results
|
84
|
+
end
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
def all_of(&bl)
|
89
|
+
previous_result = result_for_current_context
|
90
|
+
@operation_context.push({operation: "all", result: previous_result})
|
91
|
+
@current_context_index += 1
|
92
|
+
|
93
|
+
Sunspot::Util::ContextBoundDelegate.instance_eval_with_context(self, &bl)
|
94
|
+
after_results = result_for_current_context
|
95
|
+
parent_temp_result = @operation_context[@current_context_index - 1][:temp_result]
|
96
|
+
|
97
|
+
unless @current_context_index == 0
|
98
|
+
@current_context_index -= 1
|
99
|
+
@operation_context.pop
|
100
|
+
end
|
101
|
+
|
102
|
+
# parent is now current context
|
103
|
+
if parent_temp_result
|
104
|
+
@operation_context[@current_context_index][:temp_result] = parent_temp_result.concat(after_results)
|
105
|
+
else
|
106
|
+
@operation_context[@current_context_index][:result] = (previous_result & after_results).uniq
|
107
|
+
end
|
108
|
+
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
def with(attribute, value = "no_value")
|
113
|
+
skip_no_value(attribute, value)
|
114
|
+
|
115
|
+
if attribute == :search_class
|
116
|
+
matches = result_for_current_context.select {|x| x.class.name == value }
|
117
|
+
operation_context_result(matches)
|
118
|
+
return self
|
119
|
+
end
|
120
|
+
|
121
|
+
if value == nil && attribute_is_about_range?(attribute)
|
122
|
+
matches = result_for_current_context.select {|x| x.has_attribute?(attribute) && (x.read_attribute(attribute) == value)}
|
123
|
+
operation_context_result(matches)
|
124
|
+
return self
|
125
|
+
end
|
126
|
+
|
127
|
+
return self if value == "no_value" || attribute == :location
|
128
|
+
|
129
|
+
matches = if value.class.name == "Array"
|
130
|
+
result_for_current_context.select {|x| value.include?(x.send(attribute)) }
|
131
|
+
elsif @types.map{|x| x.has_attribute?(attribute)}.include?(true)
|
132
|
+
result_for_current_context.select {|x| x.read_attribute(attribute) == value }
|
133
|
+
else
|
134
|
+
result_for_current_context.select {|x| x.send(attribute) == value }
|
135
|
+
end
|
136
|
+
operation_context_result(matches)
|
137
|
+
self
|
138
|
+
end
|
139
|
+
|
140
|
+
def without(attribute, value = "no_value")
|
141
|
+
skip_no_value(attribute, value)
|
142
|
+
if value == nil && attribute_is_about_range?(attribute)
|
143
|
+
matches = result_for_current_context.select {|x| x.has_attribute?(attribute) && !(x.read_attribute(attribute) == value)}
|
144
|
+
operation_context_result(matches)
|
145
|
+
return self
|
146
|
+
end
|
147
|
+
|
148
|
+
return self if value == "no_value" || attribute == :location
|
149
|
+
matches = if value.class.name == "Array"
|
150
|
+
result_for_current_context.select {|x| x.has_attribute?(attribute) && !value.include?(x.send(attribute)) }
|
151
|
+
else
|
152
|
+
result_for_current_context.select {|x| x.has_attribute?(attribute) && !x.read_attribute(attribute).nil? && (x.read_attribute(attribute) != value) }
|
153
|
+
end
|
154
|
+
operation_context_result(matches)
|
155
|
+
self
|
156
|
+
end
|
157
|
+
|
158
|
+
def hits
|
159
|
+
self
|
160
|
+
end
|
161
|
+
|
162
|
+
# Added to pass .group_by
|
163
|
+
# Idea is save grouped hash result seperately and then
|
164
|
+
# access it with [] method.
|
165
|
+
#
|
166
|
+
# initial_grouped_hits = initial.hits.group_by(&:class_name)
|
167
|
+
# initial_grouped_hits["Activity"]
|
168
|
+
def [](key)
|
169
|
+
return if @grouped_results.empty? || @grouped_results[key].nil?
|
170
|
+
@group_key = key
|
171
|
+
self
|
172
|
+
end
|
173
|
+
|
174
|
+
# possible situation
|
175
|
+
#
|
176
|
+
# initial_grouped_hits = initial.hits.group_by(&:class_name)
|
177
|
+
# initial_grouped_hits["Activity"].map(&:primary_key)
|
178
|
+
def map(&pr)
|
179
|
+
return unless @grouped_results[@group_key]
|
180
|
+
@grouped_results[@group_key].map{|x| x.id}
|
181
|
+
end
|
182
|
+
|
183
|
+
# possible situation
|
184
|
+
#
|
185
|
+
# initial_grouped_hits = initial.hits.group_by(&:class_name)
|
186
|
+
def group_by(class_name = nil)
|
187
|
+
return self if final_results.empty?
|
188
|
+
@types.each do |type|
|
189
|
+
@grouped_results[type.name] = sorted_temp_result.group_by{|i| i.class.name == type.name }[true]
|
190
|
+
end
|
191
|
+
self
|
192
|
+
end
|
193
|
+
|
194
|
+
def phrase_fields(arg)
|
195
|
+
@textsearch_priorities = arg
|
196
|
+
return self if @search_term.empty?
|
197
|
+
fulltext(@search_term)
|
198
|
+
end
|
199
|
+
|
200
|
+
def query_phrase_slop(*args)
|
201
|
+
fulltext(@search_term)
|
202
|
+
end
|
203
|
+
|
204
|
+
# with default `StubSessionProxy`, the results is blank whatever
|
205
|
+
# argument or options you put in the search block
|
206
|
+
def fulltext(term, opt={}, &bl)
|
207
|
+
matches = []
|
208
|
+
@search_term = term
|
209
|
+
Sunspot::Util::ContextBoundDelegate.instance_eval_with_context(self, &bl) if !bl.nil?
|
210
|
+
# if there is phrase_fields option then we only search for the field
|
211
|
+
# to mimic the priority search. #string_text_fields
|
212
|
+
@types.each do |type|
|
213
|
+
string_text_fields(type).each do |field|
|
214
|
+
if type.has_attribute?(field.to_sym)
|
215
|
+
matches << type.where(type.arel_table[field.to_sym].matches("%#{term}%")).to_a
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
calculated = (result_for_current_context & matches.flatten.uniq)
|
220
|
+
operation_context_result(calculated)
|
221
|
+
self
|
222
|
+
end
|
223
|
+
|
224
|
+
def order_by(attribute, direction)
|
225
|
+
@order_key = attribute
|
226
|
+
@order_direction = direction
|
227
|
+
self
|
228
|
+
end
|
229
|
+
|
230
|
+
def in_radius(*args)
|
231
|
+
calculated = result_for_current_context.select do |r|
|
232
|
+
distance = r&.location&.distance_from([args[0], args[1]])
|
233
|
+
distance && distance < args[2].to_i
|
234
|
+
end
|
235
|
+
operation_context_result(calculated)
|
236
|
+
self
|
237
|
+
end
|
238
|
+
|
239
|
+
def greater_than(time)
|
240
|
+
calculated = result_for_current_context.select do |x|
|
241
|
+
has_attribute_and_not_nil(x) &&
|
242
|
+
x.read_attribute(@range_search_field) > time
|
243
|
+
end.uniq
|
244
|
+
operation_context_result(calculated)
|
245
|
+
self
|
246
|
+
end
|
247
|
+
|
248
|
+
def greater_than_or_equal_to(time)
|
249
|
+
calculated = result_for_current_context.select do |x|
|
250
|
+
has_attribute_and_not_nil(x) &&
|
251
|
+
x.read_attribute(@range_search_field) >= time
|
252
|
+
end.uniq
|
253
|
+
operation_context_result(calculated)
|
254
|
+
self
|
255
|
+
end
|
256
|
+
|
257
|
+
def less_than(time)
|
258
|
+
calculated = result_for_current_context.select do |x|
|
259
|
+
has_attribute_and_not_nil(x) &&
|
260
|
+
x.read_attribute(@range_search_field) < time
|
261
|
+
end.uniq
|
262
|
+
operation_context_result(calculated)
|
263
|
+
self
|
264
|
+
end
|
265
|
+
|
266
|
+
def less_than_or_equal_to(time)
|
267
|
+
calculated = result_for_current_context.select do |x|
|
268
|
+
has_attribute_and_not_nil(x) &&
|
269
|
+
x.read_attribute(@range_search_field) <= time
|
270
|
+
end.uniq
|
271
|
+
operation_context_result(calculated)
|
272
|
+
self
|
273
|
+
end
|
274
|
+
|
275
|
+
def paginate(args={})
|
276
|
+
@page = args[:page]
|
277
|
+
@per_page = args[:per_page]
|
278
|
+
self
|
279
|
+
end
|
280
|
+
|
281
|
+
def total
|
282
|
+
@operation_context.last[:result].size
|
283
|
+
end
|
284
|
+
|
285
|
+
private
|
286
|
+
|
287
|
+
# iterate the given block and change @operation_context
|
288
|
+
# block may cotain with, without, fulltext, paginate, in_raius, order_by
|
289
|
+
def run_proc_block
|
290
|
+
result = @operation_context.last[:result]
|
291
|
+
return PaginatedCollection.new if result.empty?
|
292
|
+
|
293
|
+
Sunspot::Util::ContextBoundDelegate.instance_eval_with_context(self, &@block)
|
294
|
+
# @operation_context.last[:result] = @operation_context.last[:result].uniq
|
295
|
+
self
|
296
|
+
end
|
297
|
+
|
298
|
+
def current_operation
|
299
|
+
@operation_context[@current_context_index][:operation]
|
300
|
+
end
|
301
|
+
|
302
|
+
def result_for_current_context
|
303
|
+
@operation_context[@current_context_index][:result]
|
304
|
+
end
|
305
|
+
|
306
|
+
def temp_result_for_current_context
|
307
|
+
@operation_context[@current_context_index][:temp_result]
|
308
|
+
end
|
309
|
+
|
310
|
+
def operation_context_result(after_results)
|
311
|
+
previous_result = result_for_current_context
|
312
|
+
# parent_result = @operation_context[@current_context_index -1][:result]
|
313
|
+
temp_result = @operation_context[@current_context_index][:temp_result]
|
314
|
+
if current_operation == "any"
|
315
|
+
@operation_context[@current_context_index][:result] = previous_result.concat(after_results).uniq
|
316
|
+
if temp_result
|
317
|
+
@operation_context[@current_context_index][:temp_result] = temp_result.concat(after_results)
|
318
|
+
end
|
319
|
+
else
|
320
|
+
@operation_context[@current_context_index][:result] = (previous_result & after_results).uniq
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def skip_no_value(attribute, value)
|
325
|
+
if value == "no_value" && attribute_is_about_range?(attribute)
|
326
|
+
matches = result_for_current_context.select {|x| x.has_attribute?(attribute)}
|
327
|
+
operation_context_result(matches)
|
328
|
+
return self
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
def has_attribute_and_not_nil(x)
|
333
|
+
x.read_attribute(@range_search_field) &&
|
334
|
+
!x.read_attribute(@range_search_field).nil?
|
335
|
+
end
|
336
|
+
|
337
|
+
def string_text_fields(type)
|
338
|
+
return @textsearch_priorities.keys unless @textsearch_priorities.keys.empty?
|
339
|
+
type.columns.collect { |c| {"#{c.type}":"#{c.name}"} }
|
340
|
+
.map{|hash| hash.select{|k,v| [:string, :text].include? k} }.uniq
|
341
|
+
.map{|x| x.values}.flatten
|
342
|
+
end
|
343
|
+
|
344
|
+
def attribute_is_about_range?(attribute)
|
345
|
+
matched = nil
|
346
|
+
Sunspot.session.range_fields.each do |x|
|
347
|
+
if attribute.to_s.include? x
|
348
|
+
matched = true
|
349
|
+
@range_search_field = attribute
|
350
|
+
break
|
351
|
+
end
|
352
|
+
end
|
353
|
+
matched
|
354
|
+
end
|
355
|
+
|
356
|
+
def sorted_temp_result
|
357
|
+
return final_results unless @order_direction
|
358
|
+
asc = final_results.sort_by{|x| x[@order_key]}
|
359
|
+
return asc if @order_direction.to_s.downcase.include?("asc")
|
360
|
+
asc.reverse
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
data/lib/stub_solr.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'kaminari'
|
2
|
+
module Kaminari::PageScopeMethods
|
3
|
+
alias_method :previous_page, :prev_page
|
4
|
+
end
|
5
|
+
require 'sunspot'
|
6
|
+
require 'sunspot_rails'
|
7
|
+
require 'rails'
|
8
|
+
require "stub_solr/version"
|
9
|
+
require File.expand_path('stub_solr/sunspot_rails_stub_session_proxy', File.dirname(__FILE__))
|
data/stub_solr.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path('../lib/stub_solr/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = 'stub_solr'
|
7
|
+
gem.version = StubSolr::VERSION
|
8
|
+
gem.authors = ['Jaigouk Kim']
|
9
|
+
gem.email = ['ping@jaigouk.kim']
|
10
|
+
|
11
|
+
gem.summary = %q{stub sunspot to test }
|
12
|
+
gem.description = %q{overrided StubSessionProxy with AR queries to mimic sunspot }
|
13
|
+
gem.homepage = 'https://github.com/jaigouk/stub_solr'
|
14
|
+
gem.license = 'MIT'
|
15
|
+
|
16
|
+
gem.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
gem.bindir = 'bin'
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
gem.require_paths = ['lib']
|
20
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
21
|
+
|
22
|
+
gem.add_dependency 'kaminari', '~> 0.17.0'
|
23
|
+
gem.add_dependency 'sunspot', '~> 2.2.6'
|
24
|
+
gem.add_dependency 'sunspot_solr', '~> 2.2.6'
|
25
|
+
gem.add_dependency 'sunspot_rails', '~> 2.2.6'
|
26
|
+
gem.add_dependency 'rails', '>= 4'
|
27
|
+
|
28
|
+
# gem.add_development_dependency 'simplecov', '~> 0.12.0'
|
29
|
+
gem.add_development_dependency 'bundler', '~> 1.12'
|
30
|
+
gem.add_development_dependency 'minitest', '~> 5.0'
|
31
|
+
gem.add_development_dependency 'minitest-reporters', '~> 1.1.11'
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: stub_solr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jaigouk Kim
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: kaminari
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.17.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.17.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sunspot
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.2.6
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.2.6
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sunspot_solr
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.2.6
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.2.6
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sunspot_rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.2.6
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.2.6
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rails
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.12'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.12'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '5.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '5.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: minitest-reporters
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.1.11
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.1.11
|
125
|
+
description: 'overrided StubSessionProxy with AR queries to mimic sunspot '
|
126
|
+
email:
|
127
|
+
- ping@jaigouk.kim
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rubocop.yml"
|
134
|
+
- ".travis.yml"
|
135
|
+
- Gemfile
|
136
|
+
- LICENSE.txt
|
137
|
+
- README.md
|
138
|
+
- Rakefile
|
139
|
+
- dev_tasks/release.rake
|
140
|
+
- dev_tasks/spec.rake
|
141
|
+
- gemfiles/.bundle/config
|
142
|
+
- gemfiles/rails-5.0.0.1
|
143
|
+
- lib/stub_solr.rb
|
144
|
+
- lib/stub_solr/sunspot_rails_stub_session_proxy.rb
|
145
|
+
- lib/stub_solr/version.rb
|
146
|
+
- stub_solr.gemspec
|
147
|
+
homepage: https://github.com/jaigouk/stub_solr
|
148
|
+
licenses:
|
149
|
+
- MIT
|
150
|
+
metadata: {}
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
requirements: []
|
166
|
+
rubyforge_project:
|
167
|
+
rubygems_version: 2.5.1
|
168
|
+
signing_key:
|
169
|
+
specification_version: 4
|
170
|
+
summary: stub sunspot to test
|
171
|
+
test_files: []
|