inquisitio 0.0.12 → 0.0.13

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
  SHA1:
3
- metadata.gz: 7fd33b4a7884125f5845e35aab4c28c9ce7e17d4
4
- data.tar.gz: 8008f740c7dc2bbdc91cf9decde94df3c1bd73e8
3
+ metadata.gz: 1f2af1e5aecac2a3ead9c317f23f4855b8c45454
4
+ data.tar.gz: 1cb0c84e66432226a168aae714f798bf9ba79f92
5
5
  SHA512:
6
- metadata.gz: 61bdc0964f9dbaffc6590de6b6013519ceba2cafe8cc36a52463db1f3e082a47d51e55b7234c5767880e4aa6516fb5ccd1e50eb3f6bbbbcb0fed74e77ca1d170
7
- data.tar.gz: b933134ee24f80390eb6a76c98ebcf68a29061943da85a2b1bd4d54df330526416d13f6246a0295c7bf9e7eec81fb634951fdf6126e20acd2387b62cbad4fe27
6
+ metadata.gz: ba252a11d4d71945cdca5fa5e086920388c607deb866a26233e1318f51840c9f25fcbcb23addc26c0457a683e2f20d02b44d1d0806e8166d3c785a0ce47e64ae
7
+ data.tar.gz: c44469a09d9e054993b28ecaf778c760c4fa24177bf44aa77fd2882a5abddc8b7e2537b64e0c9959d7bb0b641a89f177b3cb138384c287d0f6602f4e46921f4d
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ script:
5
+ - bundle exec rake test
6
+ #addons:
7
+ # code_climate:
8
+ # repo_token: 88dd239bc2e0010742a42a4e0234b4decd19b46d0e9d3408d8b1fe0f96dd8fc1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ 0.0.13 / 2013-10-28
2
+
3
+ [FEATURE] Implement Searcher#records
4
+ [FEATURE] Implement Searcher#ids
5
+ [FEATURE] Allow for Array-style method iteration
6
+ [FEATURE] Changed syntax to match ActiveRecord style.
7
+
1
8
  0.0.12 / 2013-10-24
2
9
 
3
10
  [FEATURE] Allow filter values to be arrays.
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Inquisitio
2
2
 
3
- TODO: Write a gem description
3
+ [![Build Status](https://travis-ci.org/meducation/inquisitio.png)](https://travis-ci.org/meducation/inquisitio)
4
+ [![Dependencies](https://gemnasium.com/meducation/inquisitio.png?travis)](https://gemnasium.com/meducation/inquisitio)
5
+ [![Code Climate](https://codeclimate.com/github/meducation/inquisitio.png)](https://codeclimate.com/github/meducation/inquisitio)
6
+
7
+ Inquisitio is a ruby wrapper around Amazon Cloud Search. It is currently under active development.
4
8
 
5
9
  ## Installation
6
10
 
@@ -12,30 +16,32 @@ And then execute:
12
16
 
13
17
  $ bundle
14
18
 
15
- Or install it yourself as:
16
-
17
- $ gem install inquisitio
18
-
19
19
  ## Usage
20
20
 
21
- TODO: Write usage instructions here
21
+ This gem allows you to build and execute queries to run against Amazon Cloud Search.
22
+
23
+ ```
24
+ results = Inquisitio.where("foobar").per(10).page(2).with(facet: 'thingy')
25
+ results.each do |result|
26
+ # ...
27
+ end
28
+ ```
22
29
 
23
30
  ## Contributing
24
31
 
25
- 1. Fork it
26
- 2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
32
+ Firstly, thank you!! :heart::sparkling_heart::heart:
30
33
 
34
+ We'd love to have you involved. Please read our [contributing guide](https://github.com/meducation/inquisitio/tree/master/CONTRIBUTING.md) for information on how to get stuck in.
31
35
 
32
- ### Contributors
36
+ ### Contributors
33
37
 
34
38
  This project is managed by the [Meducation team](http://company.meducation.net/about#team).
35
39
 
36
40
  These individuals have come up with the ideas and written the code that made this possible:
37
41
 
38
42
  - [Jeremy Walker](http://github.com/iHID)
43
+ - [Malcolm Landon](http://github.com/malcyL)
44
+ - [Charles Care](http://github.com/ccare)
39
45
 
40
46
  ## Licence
41
47
 
@@ -51,5 +57,5 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
51
57
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52
58
  GNU Affero General Public License for more details.
53
59
 
54
- A copy of the GNU Affero General Public License is available in [Licence.md](https://github.com/meducation/propono/blob/master/LICENCE.md)
60
+ A copy of the GNU Affero General Public License is available in [Licence.md](https://github.com/meducation/inquisitio/blob/master/LICENCE.md)
55
61
  along with this program. If not, see <http://www.gnu.org/licenses/>.
data/inquisitio.gemspec CHANGED
@@ -6,8 +6,8 @@ require 'inquisitio/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "inquisitio"
8
8
  spec.version = Inquisitio::VERSION
9
- spec.authors = ["Jeremy Walker"]
10
- spec.email = ["jeremy@meducation.net"]
9
+ spec.authors = ["Jeremy Walker", "Charles Care", "Malcolm Landon"]
10
+ spec.email = ["jeremy@meducation.net", "charles@meducation.net", "malcolm@meducation.net"]
11
11
  spec.description = %q{A Ruby Gem that wraps search for CloudSearch}
12
12
  spec.summary = %q{This wraps AWS CloudSearch in a Ruby Gem}
13
13
  spec.homepage = "https://github.com/meducation/inquisition"
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "excon", "~> 0.25.0"
22
+ spec.add_dependency "ruby_deep_clone"
22
23
 
23
24
  spec.add_development_dependency "bundler", "~> 1.3"
24
25
  spec.add_development_dependency "rake"
@@ -0,0 +1,34 @@
1
+ # This is taken from ActiveSupport
2
+ module ActiveSupport
3
+ module String
4
+ def constantize
5
+ names = self.gsub("_", "::").split('::')
6
+ names.shift if names.empty? || names.first.empty?
7
+
8
+ names.inject(Object) do |constant, name|
9
+ if constant == Object
10
+ constant.const_get(name)
11
+ else
12
+ candidate = constant.const_get(name)
13
+ next candidate if constant.const_defined?(name, false)
14
+ next candidate unless Object.const_defined?(name)
15
+
16
+ # Go down the ancestors to check it it's owned
17
+ # directly before we reach Object or the end of ancestors.
18
+ constant = constant.ancestors.inject do |const, ancestor|
19
+ break const if ancestor == Object
20
+ break ancestor if ancestor.const_defined?(name, false)
21
+ const
22
+ end
23
+
24
+ # owner is in Object, so raise
25
+ constant.const_get(name, false)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ class String
33
+ include ActiveSupport::String
34
+ end
@@ -15,7 +15,8 @@ module Inquisitio
15
15
 
16
16
  def build
17
17
  components = [url_root]
18
- components << (@filters.empty?? simple_query : boolean_query)
18
+ is_simple = @filters.empty? && Array(@query).size == 1
19
+ components << (is_simple ? simple_query : boolean_query)
19
20
  components << return_fields_query_string
20
21
  components << arguments
21
22
  components.join("")
@@ -23,25 +24,36 @@ module Inquisitio
23
24
 
24
25
  private
25
26
  def simple_query
26
- "q=#{URI.encode(@query.gsub('\'',''))}"
27
+ "q=#{URI.encode(@query.first.gsub('\'',''))}"
27
28
  end
28
29
 
29
30
  def boolean_query
30
- filters = @filters.map do |key,value|
31
- key = key.to_s.gsub('\'','')
32
31
 
32
+ query_blocks = []
33
+
34
+ if Array(@query).empty?
35
+ # query_blocks = []
36
+ elsif @query.size == 1
37
+ query_blocks << "'#{sanitise(@query.first)}'"
38
+ else
39
+ query_blocks << "(or #{@query.map{|q| "'#{sanitise(q)}'"}.join(' ')})"
40
+ end
41
+
42
+ query_blocks += @filters.map do |key,value|
33
43
  if value.is_a?(String)
34
- "#{key}:'#{value.to_s.gsub('\'','')}'"
44
+ "#{sanitise(key)}:'#{sanitise(value)}'"
35
45
  elsif value.is_a?(Array)
36
- mapping = value.map {|v| "#{key}:'#{v.to_s.gsub('\'','')}'" }.join(" ")
37
- "(or #{mapping})"
46
+ "(or #{value.map {|v| "#{sanitise(key)}:'#{sanitise(v)}'" }.join(" ")})"
38
47
  else
39
48
  raise InquisitioError.new("Filter values must be strings or arrays.")
40
49
  end
41
50
  end
42
- queries = filters.join(" ")
43
- queries = "'#{@query.to_s.gsub('\'','')}' #{queries}" if @query
44
- "bq=#{URI.encode("(and #{queries})")}"
51
+
52
+ "bq=#{URI.encode("(and #{query_blocks.join(' ')})")}"
53
+ end
54
+
55
+ def sanitise(value)
56
+ value.to_s.gsub('\'','');
45
57
  end
46
58
 
47
59
  def return_fields_query_string
@@ -1,49 +1,134 @@
1
1
  require 'excon'
2
+ require "deep_clone"
2
3
 
3
4
  module Inquisitio
4
5
  class Searcher
5
6
 
6
- def self.search(*args)
7
- searcher = new(*args)
8
- searcher.search
9
- searcher
7
+ def self.method_missing(name, *args)
8
+ Searcher.new.send(name, *args)
10
9
  end
11
10
 
12
- attr_reader :results
13
- def initialize(query, filters = {})
14
- raise InquisitioError.new("Query is null") if query.nil?
11
+ attr_reader :params
12
+ def initialize(params = nil)
13
+ @params = params || {
14
+ criteria: [],
15
+ filters: {},
16
+ per: 10,
17
+ page: 1,
18
+ returns: [],
19
+ with: {}
20
+ }
15
21
 
16
- if query.is_a?(String)
17
- @query = query
18
- @filters = filters
19
- else
20
- @filters = query
21
- end
22
-
23
- @return_fields = @filters.delete(:return_fields)
24
- @arguments = @filters.delete(:arguments)
22
+ yield(self) if block_given?
25
23
  end
26
24
 
27
25
  def search
28
- response = Excon.get(search_url)
29
- raise InquisitioError.new("Search failed with status code: #{response.status} Message #{response.body}") unless response.status == 200
30
- body = response.body
31
- @results = JSON.parse(body)["hits"]["hit"]
26
+ results
32
27
  end
33
28
 
34
29
  def ids
35
- @ids ||= @results.map{|result|result['id']}
30
+ @ids ||= map{|r|r['med_id']}
36
31
  end
37
32
 
38
33
  def records
39
- @records ||= @results.map do |result|
40
- {result['type'] => result['id']}
34
+ @records ||= begin
35
+ klasses = {}
36
+ map do |result|
37
+ klass = result['med_type']
38
+ klasses[klass] ||= []
39
+ klasses[klass] << result['med_id']
40
+ end
41
+
42
+ klasses.map {|klass, ids|
43
+ klass.constantize.where(id: ids)
44
+ }.flatten
45
+ end
46
+ end
47
+
48
+ def where(value)
49
+ clone do |s|
50
+ if value.is_a?(Array)
51
+ s.params[:criteria] += value
52
+ elsif value.is_a?(Hash)
53
+ value.each do |k,v|
54
+ s.params[:filters][k] ||= []
55
+ if v.is_a?(Array)
56
+ s.params[:filters][k] = v
57
+ else
58
+ s.params[:filters][k] << v
59
+ end
60
+ end
61
+ else
62
+ s.params[:criteria] << value
63
+ end
64
+ end
65
+ end
66
+
67
+ def per(value)
68
+ clone do |s|
69
+ s.params[:per] = value.to_i
70
+ end
71
+ end
72
+
73
+ def page(value)
74
+ clone do |s|
75
+ s.params[:page] = value.to_i
76
+ end
77
+ end
78
+
79
+ def returns(*value)
80
+ clone do |s|
81
+ if value.is_a?(Array)
82
+ s.params[:returns] += value
83
+ else
84
+ s.params[:returns] << value
85
+ end
41
86
  end
42
87
  end
43
88
 
89
+ def with(value)
90
+ clone do |s|
91
+ s.params[:with].merge!(value)
92
+ end
93
+ end
94
+
95
+ # Proxy everything to the results so that this this class
96
+ # transparently acts as an Array.
97
+ def method_missing(name, *args, &block)
98
+ results.to_a.send(name, *args, &block)
99
+ end
100
+
44
101
  private
102
+
103
+ def results
104
+ if @results.nil?
105
+ response = Excon.get(search_url)
106
+ raise InquisitioError.new("Search failed with status code: #{response.status} Message #{response.body}") unless response.status == 200
107
+ @results = JSON.parse(response.body)["hits"]["hit"]
108
+ end
109
+ @results
110
+ end
111
+
45
112
  def search_url
46
- @search_url ||= SearchUrlBuilder.build(query: @query, filters: @filters, arguments: @arguments, return_fields: @return_fields)
113
+ @search_url ||= begin
114
+ return_fields = params[:returns].empty?? [:med_type, :med_id] : params[:returns]
115
+
116
+ SearchUrlBuilder.build(
117
+ query: params[:criteria],
118
+ filters: params[:filters],
119
+ arguments: params[:with].merge({
120
+ size: params[:per],
121
+ start: params[:per] * params[:page]
122
+ }),
123
+ return_fields: return_fields
124
+ )
125
+ end
126
+ end
127
+
128
+ def clone
129
+ Searcher.new(DeepClone.clone(params)) do |s|
130
+ yield(s) if block_given?
131
+ end
47
132
  end
48
133
  end
49
134
  end
@@ -1,3 +1,3 @@
1
1
  module Inquisitio
2
- VERSION = "0.0.12"
2
+ VERSION = "0.0.13"
3
3
  end
data/lib/inquisitio.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require "inquisitio/version"
2
2
  require "inquisitio/inquisitio_error"
3
3
  require "inquisitio/logger"
4
+ require "inquisitio/active_support"
5
+
4
6
  require "inquisitio/configuration"
5
7
  require "inquisitio/document"
6
8
  require "inquisitio/search_url_builder"
@@ -33,12 +35,46 @@ module Inquisitio
33
35
  end
34
36
  end
35
37
 
36
- # Perform a search.
38
+ # Exectues the generated query and returns self.
39
+ #
40
+ # @param query The search query.
41
+ def self.search
42
+ Searcher.search
43
+ end
44
+
45
+ # Specify a condition as either a string, an array, or a hash.
46
+ #
47
+ # @param query The search query.
48
+ def self.where(query)
49
+ Searcher.where(query)
50
+ end
51
+
52
+ # Specify a page number. Defaults to 1
53
+ #
54
+ # @param query The page number.
55
+ def self.page(page)
56
+ Searcher.page(page)
57
+ end
58
+
59
+ # Specify the amount of results you want back
60
+ #
61
+ # @param query The amount of results.
62
+ def self.per(num)
63
+ Searcher.per(num)
64
+ end
65
+
66
+ # Specify which fields you want returned.
67
+ #
68
+ # @param query A string or array specifying the fields
69
+ def self.returns(num)
70
+ Searcher.returns(num)
71
+ end
72
+
73
+ # Specify any other fields you want to send as part of the request.
37
74
  #
38
- # @param [String] query The search query.
39
- # @param [Hash] options. Optionaly specify return_fields. The fields to be returned in the search results.
40
- def self.search(query, options = {})
41
- Searcher.search(query, options)
75
+ # @param query An array of fields.
76
+ def self.with(num)
77
+ Searcher.with(num)
42
78
  end
43
79
 
44
80
  # Index a batch of documents.
@@ -9,14 +9,26 @@ module Inquisitio
9
9
  Inquisitio.config.default_search_size = '10'
10
10
  end
11
11
 
12
- def test_create_correct_search_url_without_return_fields
13
- url = SearchUrlBuilder.build(query: 'Star Wars')
12
+ def test_create_correct_search_url_with_single_criteria_query
13
+ url = SearchUrlBuilder.build(query: ['Star Wars'])
14
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&size=10'
15
+ assert_equal expected_url, url
16
+ end
17
+
18
+ def test_create_correct_search_url_with_multiple_criteria_should_create_boolean_query
19
+ url = SearchUrlBuilder.build(query: ['Star Wars', 'Episode One'])
20
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20(or%20\'Star%20Wars\'%20\'Episode%20One\'))&size=10'
21
+ assert_equal expected_url, url
22
+ end
23
+
24
+ def test_create_correct_search_url_with_multiple_criteria
25
+ url = SearchUrlBuilder.build(query: ['Star Wars'])
14
26
  expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&size=10'
15
27
  assert_equal expected_url, url
16
28
  end
17
29
 
18
30
  def test_create_correct_search_url_including_return_fields
19
- url = SearchUrlBuilder.build(query: 'Star Wars', return_fields: [ 'title', 'year', '%' ] )
31
+ url = SearchUrlBuilder.build(query: ['Star Wars'], return_fields: [ 'title', 'year', '%' ] )
20
32
  expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&return-fields=title,year,%25&size=10'
21
33
  assert_equal expected_url, url
22
34
  end
@@ -28,49 +40,62 @@ module Inquisitio
28
40
  end
29
41
 
30
42
  def test_create_boolean_query_search_url_with_query_and_filters
31
- url = SearchUrlBuilder.build(query: 'Star Wars', filters: {genre: 'Animation'})
43
+ url = SearchUrlBuilder.build(query: ['Star Wars'], filters: {genre: 'Animation'})
32
44
  expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20\'Star%20Wars\'%20genre:\'Animation\')&size=10'
33
45
  assert_equal expected_url, url
34
46
  end
35
47
 
36
48
  def test_create_boolean_query_search_url_with_query_and_filters_and_return_fields
37
- url = SearchUrlBuilder.build(query: 'Star Wars', filters: {genre: 'Animation'}, return_fields: [ 'title', 'year', '%' ])
49
+ url = SearchUrlBuilder.build(query: ['Star Wars'], filters: {genre: 'Animation'}, return_fields: [ 'title', 'year', '%' ])
38
50
  expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20\'Star%20Wars\'%20genre:\'Animation\')&return-fields=title,year,%25&size=10'
39
51
  assert_equal expected_url, url
40
52
  end
41
53
 
42
54
  def test_create_search_url_with_added_arguments
43
- url = SearchUrlBuilder.build(query: 'Star Wars', filters: {genre: 'Animation'}, :arguments => { facet: 'genre', 'facet-genre-constraints' => 'Animation', 'facet-genre-top-n' => '5'})
55
+ url = SearchUrlBuilder.build(query: ['Star Wars'], filters: {genre: 'Animation'}, :arguments => { facet: 'genre', 'facet-genre-constraints' => 'Animation', 'facet-genre-top-n' => '5'})
44
56
  expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20\'Star%20Wars\'%20genre:\'Animation\')&facet=genre&facet-genre-constraints=Animation&facet-genre-top-n=5&size=10'
45
57
  assert_equal expected_url, url
46
58
  end
47
59
 
48
60
  def test_create_search_url_with_default_size
49
- url = SearchUrlBuilder.build(query: 'Star Wars')
61
+ url = SearchUrlBuilder.build(query: ['Star Wars'])
50
62
  expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&size=10'
51
63
  assert_equal expected_url, url
52
64
  end
53
65
 
54
66
  def test_create_search_url_overriding_default_size
55
- url = SearchUrlBuilder.build(query: 'Star Wars', :arguments => { size: '200' })
67
+ url = SearchUrlBuilder.build(query: ['Star Wars'], :arguments => { size: '200' })
56
68
  expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&size=200'
57
69
  assert_equal expected_url, url
58
70
  end
59
71
 
72
+ def test_create_search_url_with_start_and_default_size
73
+ url = SearchUrlBuilder.build(query: ['Star Wars'], :arguments => { start: '20' })
74
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&start=20&size=10'
75
+ assert_equal expected_url, url
76
+ end
77
+
78
+ def test_create_search_url_with_start_and_size
79
+ url = SearchUrlBuilder.build(query: ['Star Wars'], :arguments => { start: '2', size: '200' })
80
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&start=2&size=200'
81
+ assert_equal expected_url, url
82
+ end
83
+
60
84
  def test_create_correct_search_url_with_sanatised_query_string
61
- url = SearchUrlBuilder.build(query: 'Star\' Wars', filters: {genre: 'Anim\'ation'}, :arguments => { facet: 'ge\'nre', 'facet-genr\'e-constraints' => 'Anim\'ation', 'facet-gen\'re-top-n' => '\'5'}, return_fields: [ 't\'itle', 'y\'ear' ])
85
+ url = SearchUrlBuilder.build(query: ['Star\' Wars'], filters: {genre: 'Anim\'ation'}, :arguments => { facet: 'ge\'nre', 'facet-genr\'e-constraints' => 'Anim\'ation', 'facet-gen\'re-top-n' => '\'5'}, return_fields: [ 't\'itle', 'y\'ear' ])
62
86
  expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20\'Star%20Wars\'%20genre:\'Animation\')&return-fields=title,year&facet=genre&facet-genre-constraints=Animation&facet-genre-top-n=5&size=10'
63
87
  assert_equal expected_url, url
64
88
  end
65
89
 
66
90
  def test_create_search_url_with_filter_array
67
- url = SearchUrlBuilder.build(query: 'Star Wars', filters: {genre: ['Animation', 'Action']})
91
+ url = SearchUrlBuilder.build(query: ['Star Wars'], filters: {genre: ['Animation', 'Action']})
68
92
  expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20\'Star%20Wars\'%20(or%20genre:\'Animation\'%20genre:\'Action\'))&size=10'
69
93
  assert_equal expected_url, url
70
94
  end
95
+
71
96
  def test_throws_exception_when_using_unsupported_filter_value_type
72
97
  assert_raises(InquisitioError) do
73
- SearchUrlBuilder.build(query: 'Star Wars', filters: {genre: {}})
98
+ SearchUrlBuilder.build(query: ['Star Wars'], filters: {genre: {}})
74
99
  end
75
100
  end
76
101
  end
@@ -6,16 +6,17 @@ module Inquisitio
6
6
  super
7
7
  @search_endpoint = 'http://my.search-endpoint.com'
8
8
  Inquisitio.config.search_endpoint = @search_endpoint
9
- @expected_result_1 = {'id' => 1, 'title' => "Foobar", 'type' => "cat"}
10
- @expected_result_2 = {'id' => 2, 'title' => "Foobar2", 'type' => "dog"}
11
- @expected_results = [@expected_result_1, @expected_result_2]
9
+ @result_1 = {'med_id' => 1, 'title' => "Foobar", 'med_type' => "Cat"}
10
+ @result_2 = {'med_id' => 2, 'title' => "Foobar", 'med_type' => "Cat"}
11
+ @result_3 = {'med_id' => 20, 'title' => "Foobar2", 'med_type' => "Module_Dog"}
12
+ @expected_results = [@result_1, @result_2, @result_3]
12
13
 
13
- body = <<-EOS
14
+ @body = <<-EOS
14
15
  {"rank":"-text_relevance","match-expr":"(label 'star wars')","hits":{"found":2,"start":0,"hit":#{@expected_results.to_json}},"info":{"rid":"9d3b24b0e3399866dd8d376a7b1e0f6e930d55830b33a474bfac11146e9ca1b3b8adf0141a93ecee","time-ms":3,"cpu-time-ms":0}}
15
16
  EOS
16
17
 
17
18
  Excon.defaults[:mock] = true
18
- Excon.stub({}, {body: body, status: 200})
19
+ Excon.stub({}, {body: @body, status: 200})
19
20
  end
20
21
 
21
22
  def teardown
@@ -23,68 +24,255 @@ module Inquisitio
23
24
  Excon.stubs.clear
24
25
  end
25
26
 
26
- def test_initialization_with_string
27
- filters = { :genre => [ 'Animation' ] }
28
- return_fields = [ 'title' ]
29
- searcher = Searcher.new('Star Wars', filters.merge({return_fields: return_fields}))
30
- assert_equal 'Star Wars', searcher.instance_variable_get("@query")
31
- assert_equal filters, searcher.instance_variable_get("@filters")
32
- assert_equal return_fields, searcher.instance_variable_get("@return_fields")
27
+ def test_where_sets_variable
28
+ criteria = 'Star Wars'
29
+ searcher = Searcher.where(criteria)
30
+ assert_equal [criteria], searcher.params[:criteria]
33
31
  end
34
32
 
35
- def test_initialization_with_hash
36
- filters = { :genre => [ 'Animation' ] }
37
- return_fields = [ 'title' ]
38
- searcher = Searcher.new(filters.merge({return_fields: return_fields}))
39
- assert_equal nil, searcher.instance_variable_get("@query")
40
- assert_equal filters, searcher.instance_variable_get("@filters")
41
- assert_equal return_fields, searcher.instance_variable_get("@return_fields")
33
+ def test_where_sets_variable_with_an_array
34
+ criteria = ['Star', 'Wars']
35
+ searcher = Searcher.where(criteria)
36
+ assert_equal criteria, searcher.params[:criteria]
42
37
  end
43
38
 
44
- def test_searcher_should_raise_exception_if_query_null
45
- assert_raises(InquisitioError, "Query is nil") do
46
- Searcher.search(nil)
47
- end
39
+ def test_where_doesnt_mutate_searcher
40
+ initial_criteria = 'star wars'
41
+ searcher = Searcher.where(initial_criteria)
42
+ searcher.where('Return of the Jedi')
43
+ assert_equal [initial_criteria], searcher.params[:criteria]
44
+ end
45
+
46
+ def test_where_returns_a_new_searcher
47
+ searcher1 = Searcher.where('star wars')
48
+ searcher2 = searcher1.where('star wars')
49
+ refute_same searcher1, searcher2
50
+ end
51
+
52
+ def test_where_sets_filters
53
+ filters = {genre: 'Animation'}
54
+ searcher = Searcher.where(filters)
55
+ assert_equal({genre: ['Animation']}, searcher.params[:filters])
56
+ end
57
+
58
+ def test_where_merges_filters
59
+ filters1 = {genre: 'Animation'}
60
+ filters2 = {foobar: 'Cat'}
61
+ searcher = Searcher.where(filters1).where(filters2)
62
+ assert_equal({genre: ['Animation'], foobar: ['Cat']}, searcher.params[:filters])
63
+ end
64
+
65
+ def test_where_merges_filters_with_same_key
66
+ filters1 = {genre: 'Animation'}
67
+ filters2 = {genre: 'Action'}
68
+ searcher = Searcher.where(filters1).where(filters2)
69
+ assert_equal({genre: ["Animation", "Action"]}, searcher.params[:filters])
70
+ end
71
+
72
+ def test_where_gets_correct_url
73
+ searcher = Searcher.where('Star Wars')
74
+ assert searcher.send(:search_url).include? "q=Star%20Wars"
75
+ end
76
+
77
+ def test_where_gets_correct_url_with_filters
78
+ searcher = Searcher.where(title: 'Star Wars')
79
+ assert searcher.send(:search_url).include? "bq=(and%20(or%20title:'Star%20Wars'))"
80
+ end
81
+
82
+ def test_where_works_with_array_in_a_hash
83
+ criteria = {thing: ['foo', 'bar']}
84
+ searcher = Searcher.where(criteria)
85
+ assert_equal criteria, searcher.params[:filters]
86
+ end
87
+
88
+ def test_where_works_with_string_and_array
89
+ str_criteria = 'Star Wars'
90
+ hash_criteria = {thing: ['foo', 'bar']}
91
+ searcher = Searcher.where(str_criteria).where(hash_criteria)
92
+ assert_equal hash_criteria, searcher.params[:filters]
93
+ assert_equal [str_criteria], searcher.params[:criteria]
94
+ end
95
+
96
+ def test_per_doesnt_mutate_searcher
97
+ searcher = Searcher.per(10)
98
+ searcher.per(15)
99
+ assert_equal 10, searcher.params[:per]
100
+ end
101
+
102
+ def test_per_returns_a_new_searcher
103
+ searcher1 = Searcher.where('star wars')
104
+ searcher2 = searcher1.where('star wars')
105
+ refute_same searcher1, searcher2
106
+ end
107
+
108
+ def test_per_sets_variable
109
+ searcher = Searcher.per(15)
110
+ assert_equal 15, searcher.params[:per]
111
+ end
112
+
113
+ def test_per_parses_a_string
114
+ searcher = Searcher.per("15")
115
+ assert_equal 15, searcher.params[:per]
116
+ end
117
+
118
+ def test_per_gets_correct_url
119
+ searcher = Searcher.per(15)
120
+ assert searcher.send(:search_url).include? "&size=15"
121
+ end
122
+
123
+ def test_page_doesnt_mutate_searcher
124
+ searcher = Searcher.page(1)
125
+ searcher.page(2)
126
+ assert_equal 1, searcher.params[:page]
127
+ end
128
+
129
+ def test_page_returns_a_new_searcher
130
+ searcher1 = Searcher.page(1)
131
+ searcher2 = searcher1.page(2)
132
+ refute_same searcher1, searcher2
133
+ end
134
+
135
+ def test_page_sets_variable
136
+ searcher = Searcher.page(3)
137
+ assert_equal 3, searcher.params[:page]
138
+ end
139
+
140
+ def test_page_parses_a_string
141
+ searcher = Searcher.page("15")
142
+ assert_equal 15, searcher.params[:page]
143
+ end
144
+
145
+ def test_page_gets_correct_url
146
+ searcher = Searcher.page(3).per(15)
147
+ assert searcher.send(:search_url).include? "&start=45"
148
+ end
149
+
150
+ def test_returns_doesnt_mutate_searcher
151
+ searcher = Searcher.returns(:foobar)
152
+ searcher.returns(:dogcat)
153
+ assert_equal [:foobar], searcher.params[:returns]
154
+ end
155
+
156
+ def test_returns_returns_a_new_searcher
157
+ searcher1 = Searcher.returns(1)
158
+ searcher2 = searcher1.returns(2)
159
+ refute_same searcher1, searcher2
160
+ end
161
+
162
+ def test_returns_sets_variable
163
+ searcher = Searcher.returns('foobar')
164
+ assert searcher.params[:returns].include?('foobar')
165
+ end
166
+
167
+ def test_returns_gets_correct_urlns_appends_variable
168
+ searcher = Searcher.returns('foobar')
169
+ assert searcher.send(:search_url).include? "&return-fields=foobar"
170
+ end
171
+
172
+ def test_returns_with_array_sets_variable
173
+ searcher = Searcher.returns('dog', 'cat')
174
+ assert_equal ['dog', 'cat'], searcher.params[:returns]
175
+ end
176
+
177
+ def test_returns_with_array_gets_correct_url
178
+ searcher = Searcher.returns('med_id', 'foobar')
179
+ assert searcher.send(:search_url).include? "&return-fields=med_id,foobar"
180
+ end
181
+
182
+ def test_returns_appends_variable
183
+ searcher = Searcher.returns('med_id').returns('foobar')
184
+ assert_equal ['med_id', 'foobar'], searcher.params[:returns]
185
+ end
186
+
187
+ def test_with_saves_variable
188
+ searcher = Searcher.with(foo: 'bar')
189
+ assert_equal({foo:'bar'}, searcher.params[:with])
190
+ end
191
+
192
+ def test_with_appends_to_variable
193
+ searcher = Searcher.with(foo: 'bar').with(cat: 'dog')
194
+ assert_equal({foo:'bar', cat:'dog'}, searcher.params[:with])
195
+ end
196
+
197
+ def test_with_gets_correct_url
198
+ searcher = Searcher.with(foo: 'bar').with(cat: 'dog')
199
+ assert searcher.send(:search_url).include? "&foo=bar&cat=dog"
48
200
  end
49
201
 
202
+ def test_search_calls_search_url_builder
203
+ SearchUrlBuilder.any_instance.expects(build: "http://www.example.com")
204
+ searcher = Searcher.where('Star Wars')
205
+ searcher.search
206
+ end
50
207
 
51
208
  def test_search_raises_exception_when_response_not_200
52
209
  Excon.stub({}, {:body => 'Bad Happened', :status => 500})
53
210
 
54
- searcher = Searcher.new('Star Wars')
211
+ searcher = Searcher.where('Star Wars')
55
212
 
56
213
  assert_raises(InquisitioError, "Search failed with status code 500") do
57
214
  searcher.search
58
215
  end
59
216
  end
60
217
 
61
- def test_search_should_set_results
62
- searcher = Searcher.new('Star Wars', { :return_fields => [ 'title', 'year', '%' ] } )
218
+ def test_that_iterating_calls_results
219
+ searcher = Searcher.where("star_wars")
220
+ searcher.expects(results: [])
221
+ searcher.each { }
222
+ end
223
+
224
+ def test_that_iterating_calls_each
225
+ searcher = Searcher.where("star_wars")
63
226
  searcher.search
64
- assert_equal @expected_results, searcher.instance_variable_get("@results")
227
+ searcher.send(:results).expects(:each)
228
+ searcher.each { }
65
229
  end
66
230
 
67
- def test_search_should_set_ids
68
- searcher = Searcher.new('Star Wars', { :return_fields => [ 'title', 'year', '%' ] } )
231
+ def test_that_select_calls_each
232
+ searcher = Searcher.where("star_wars")
69
233
  searcher.search
70
- assert_equal @expected_results.map{|r|r['id']}, searcher.ids
234
+ searcher.send(:results).expects(:select)
235
+ searcher.select { }
71
236
  end
72
237
 
73
- def test_search_should_set_records
74
- searcher = Searcher.new('Star Wars', { :return_fields => [ 'title', 'year', '%' ] } )
238
+ def test_search_should_results
239
+ searcher = Searcher.where("star_wars")
75
240
  searcher.search
241
+ assert_equal @expected_results, searcher.instance_variable_get("@results")
242
+ end
76
243
 
77
- # [{"MediaFile" => 1}, {...}]
78
- records = []
79
- records << {@expected_result_1['type'] => @expected_result_1['id']}
80
- records << {@expected_result_2['type'] => @expected_result_2['id']}
81
- assert_equal records, searcher.records
244
+ def test_search_only_runs_once
245
+ searcher = Searcher.where("star_wars")
246
+ Excon.expects(:get).returns(mock(status: 200, body: @body)).once
247
+ 2.times { searcher.search }
82
248
  end
83
249
 
84
- def test_search_calls_search_url_builder
85
- SearchUrlBuilder.any_instance.expects(build: "http://www.example.com")
86
- searcher = Searcher.new('Star Wars')
87
- searcher.search
250
+ def test_should_return_type_and_id_by_default
251
+ searcher = Searcher.where('Star Wars')
252
+ assert_equal [], searcher.params[:returns]
253
+ assert searcher.send(:search_url).include? "&return-fields=med_type,med_id"
254
+ searcher.send(:search_url)
255
+ end
256
+
257
+ def test_should_return_ids
258
+ searcher = Searcher.where('Star Wars')
259
+ assert_equal @expected_results.map{|r|r['med_id']}, searcher.ids
260
+ end
261
+
262
+ def test_should_return_ids
263
+ Object.const_set :Cat, Object.new
264
+ Module.const_set :Dog, Object.new
265
+
266
+ res1 = "Foobar"
267
+ res2 = 123
268
+ res3 = true
269
+
270
+ Cat.expects(:where).with(id: [1,2]).returns([res1, res2])
271
+ Module::Dog.expects(:where).with(id: [20]).returns([res3])
272
+
273
+ searcher = Searcher.new
274
+ searcher.instance_variable_set("@results", [])
275
+ assert_equal [res1, res2, res3], Searcher.records
88
276
  end
89
277
  end
90
278
  end
metadata CHANGED
@@ -1,14 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inquisitio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Walker
8
+ - Charles Care
9
+ - Malcolm Landon
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
- date: 2013-10-24 00:00:00.000000000 Z
13
+ date: 2013-10-28 00:00:00.000000000 Z
12
14
  dependencies:
13
15
  - !ruby/object:Gem::Dependency
14
16
  name: excon
@@ -24,6 +26,20 @@ dependencies:
24
26
  - - ~>
25
27
  - !ruby/object:Gem::Version
26
28
  version: 0.25.0
29
+ - !ruby/object:Gem::Dependency
30
+ name: ruby_deep_clone
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
27
43
  - !ruby/object:Gem::Dependency
28
44
  name: bundler
29
45
  requirement: !ruby/object:Gem::Requirement
@@ -97,6 +113,8 @@ dependencies:
97
113
  description: A Ruby Gem that wraps search for CloudSearch
98
114
  email:
99
115
  - jeremy@meducation.net
116
+ - charles@meducation.net
117
+ - malcolm@meducation.net
100
118
  executables:
101
119
  - boolean_query
102
120
  - facet_query
@@ -106,6 +124,7 @@ extensions: []
106
124
  extra_rdoc_files: []
107
125
  files:
108
126
  - .gitignore
127
+ - .travis.yml
109
128
  - CHANGELOG.md
110
129
  - CONTRIBUTING.md
111
130
  - Gemfile
@@ -118,6 +137,7 @@ files:
118
137
  - bin/search
119
138
  - inquisitio.gemspec
120
139
  - lib/inquisitio.rb
140
+ - lib/inquisitio/active_support.rb
121
141
  - lib/inquisitio/configuration.rb
122
142
  - lib/inquisitio/document.rb
123
143
  - lib/inquisitio/indexer.rb