ansr 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +35 -0
  3. data/ansr.gemspec +2 -1
  4. data/ansr_blacklight/Gemfile +3 -0
  5. data/ansr_blacklight/README.md +37 -0
  6. data/ansr_blacklight/ansr_blacklight.gemspec +28 -0
  7. data/ansr_blacklight/lib/ansr_blacklight.rb +57 -0
  8. data/ansr_blacklight/lib/ansr_blacklight/arel.rb +6 -0
  9. data/ansr_blacklight/lib/ansr_blacklight/arel/big_table.rb +57 -0
  10. data/ansr_blacklight/lib/ansr_blacklight/arel/visitors.rb +6 -0
  11. data/ansr_blacklight/lib/ansr_blacklight/arel/visitors/query_builder.rb +217 -0
  12. data/ansr_blacklight/lib/ansr_blacklight/arel/visitors/to_no_sql.rb +14 -0
  13. data/ansr_blacklight/lib/ansr_blacklight/base.rb +21 -0
  14. data/ansr_blacklight/lib/ansr_blacklight/connection_adapters/no_sql_adapter.rb +38 -0
  15. data/ansr_blacklight/lib/ansr_blacklight/model/querying.rb +29 -0
  16. data/ansr_blacklight/lib/ansr_blacklight/relation.rb +50 -0
  17. data/ansr_blacklight/lib/ansr_blacklight/relation/solr_projection_methods.rb +55 -0
  18. data/ansr_blacklight/lib/ansr_blacklight/request_builders.rb +141 -0
  19. data/ansr_blacklight/lib/ansr_blacklight/solr.rb +4 -0
  20. data/ansr_blacklight/lib/ansr_blacklight/solr/request.rb +46 -0
  21. data/ansr_blacklight/lib/ansr_blacklight/solr/response.rb +94 -0
  22. data/ansr_blacklight/lib/ansr_blacklight/solr/response/group.rb +32 -0
  23. data/ansr_blacklight/lib/ansr_blacklight/solr/response/group_response.rb +50 -0
  24. data/ansr_blacklight/lib/ansr_blacklight/solr/response/more_like_this.rb +14 -0
  25. data/ansr_blacklight/lib/ansr_blacklight/solr/response/pagination_methods.rb +35 -0
  26. data/ansr_blacklight/lib/ansr_blacklight/solr/response/spelling.rb +92 -0
  27. data/ansr_blacklight/spec/fixtures/config.yml +0 -0
  28. data/ansr_blacklight/spec/lib/loaded_relation_spec.rb +223 -0
  29. data/ansr_blacklight/spec/lib/queryable_relation_spec.rb +133 -0
  30. data/ansr_blacklight/spec/lib/relation/faceting_spec.rb +475 -0
  31. data/ansr_blacklight/spec/lib/relation/grouping_spec.rb +159 -0
  32. data/ansr_blacklight/spec/spec_helper.rb +72 -0
  33. data/ansr_dpla/Gemfile +3 -0
  34. data/ansr_dpla/Gemfile.lock +138 -0
  35. data/ansr_dpla/README.md +2 -2
  36. data/ansr_dpla/ansr_dpla.gemspec +2 -2
  37. data/ansr_dpla/lib/ansr_dpla.rb +3 -0
  38. data/ansr_dpla/lib/ansr_dpla/api.rb +3 -3
  39. data/ansr_dpla/lib/ansr_dpla/arel.rb +1 -2
  40. data/ansr_dpla/lib/ansr_dpla/arel/big_table.rb +4 -0
  41. data/ansr_dpla/lib/ansr_dpla/arel/visitors.rb +6 -0
  42. data/ansr_dpla/lib/ansr_dpla/arel/visitors/query_builder.rb +188 -0
  43. data/ansr_dpla/lib/ansr_dpla/arel/visitors/to_no_sql.rb +9 -0
  44. data/ansr_dpla/lib/ansr_dpla/connection_adapters/no_sql_adapter.rb +58 -0
  45. data/ansr_dpla/lib/ansr_dpla/model/base.rb +7 -0
  46. data/ansr_dpla/lib/ansr_dpla/model/querying.rb +6 -10
  47. data/ansr_dpla/lib/ansr_dpla/relation.rb +61 -0
  48. data/ansr_dpla/lib/ansr_dpla/request.rb +5 -0
  49. data/ansr_dpla/spec/lib/api_spec.rb +8 -5
  50. data/ansr_dpla/spec/lib/item_spec.rb +2 -2
  51. data/ansr_dpla/spec/lib/relation/facet_spec.rb +27 -19
  52. data/ansr_dpla/spec/lib/relation/select_spec.rb +10 -8
  53. data/ansr_dpla/spec/lib/relation/where_spec.rb +1 -1
  54. data/ansr_dpla/spec/lib/relation_spec.rb +31 -29
  55. data/ansr_dpla/test/system.rb +4 -2
  56. data/lib/ansr.rb +7 -0
  57. data/lib/ansr/arel.rb +3 -0
  58. data/lib/ansr/arel/big_table.rb +43 -3
  59. data/lib/ansr/arel/configured_field.rb +19 -0
  60. data/lib/ansr/arel/nodes.rb +41 -0
  61. data/lib/ansr/arel/visitors.rb +7 -0
  62. data/lib/ansr/arel/visitors/context.rb +13 -0
  63. data/lib/ansr/arel/visitors/query_builder.rb +47 -0
  64. data/lib/ansr/arel/visitors/to_no_sql.rb +41 -0
  65. data/lib/ansr/base.rb +29 -1
  66. data/lib/ansr/configurable.rb +6 -12
  67. data/lib/ansr/connection_adapters.rb +5 -0
  68. data/lib/ansr/connection_adapters/no_sql_adapter.rb +80 -0
  69. data/lib/ansr/dummy_associations.rb +105 -0
  70. data/lib/ansr/facets.rb +103 -0
  71. data/lib/ansr/model.rb +17 -107
  72. data/lib/ansr/model/connection_handler.rb +6 -0
  73. data/lib/ansr/relation.rb +40 -23
  74. data/lib/ansr/relation/group.rb +31 -0
  75. data/lib/ansr/relation/predicate_builder.rb +106 -0
  76. data/lib/ansr/relation/query_methods.rb +192 -45
  77. data/lib/ansr/sanitization.rb +5 -18
  78. data/lib/ansr/utils.rb +89 -0
  79. data/lib/ansr/version.rb +1 -1
  80. metadata +73 -25
  81. data/ansr_dpla/lib/ansr_dpla/arel/connection.rb +0 -81
  82. data/ansr_dpla/lib/ansr_dpla/arel/query_builder.rb +0 -131
  83. data/lib/ansr/model/connection.rb +0 -103
@@ -0,0 +1,6 @@
1
+ module Ansr::Dpla::Arel
2
+ module Visitors
3
+ require 'ansr_dpla/arel/visitors/query_builder'
4
+ require 'ansr_dpla/arel/visitors/to_no_sql'
5
+ end
6
+ end
@@ -0,0 +1,188 @@
1
+ module Ansr::Dpla::Arel::Visitors
2
+ class QueryBuilder < Ansr::Arel::Visitors::QueryBuilder
3
+ attr_reader :query_opts
4
+
5
+ def initialize(table, query_opts=nil)
6
+ super(table)
7
+ @query_opts = query_opts ||= Ansr::Dpla::Request.new
8
+ @query_opts.path = table.name
9
+ end
10
+
11
+ # determines whether multiple values should accumulate or overwrite in merges
12
+ def multiple?(field_key)
13
+ true
14
+ end
15
+
16
+ def visit_String o, a
17
+ case a
18
+ when Ansr::Arel::Visitors::From
19
+ query_opts.path = o
20
+ when Ansr::Arel::Visitors::Facet
21
+ filter_field(o.to_sym)
22
+ when Ansr::Arel::Visitors::Order
23
+ order(o)
24
+ else
25
+ raise "visited String \"#{o}\" with #{a.to_s}"
26
+ end
27
+ end
28
+
29
+ def visit_Arel_SqlLiteral(n, attribute)
30
+ select_val = n.to_s.split(" AS ")
31
+ case attribute
32
+ when Ansr::Arel::Visitors::Order
33
+ order(n.to_s)
34
+ when Ansr::Arel::Visitors::Facet
35
+ filter_field(select_val[0].to_sym)
36
+ else
37
+ field(select_val[0].to_sym)
38
+ if select_val[1]
39
+ query_opts.aliases ||= {}
40
+ query_opts.aliases[select_val[0]] = select_val[1]
41
+ end
42
+ end
43
+ end
44
+
45
+ def visit_Ansr_Arel_Nodes_Filter(object, attribute)
46
+ expr = object.expr
47
+ case expr
48
+ when ::Arel::SqlLiteral
49
+ visit expr, Ansr::Arel::Visitors::Filter.new(attribute) if object.select
50
+ when ::Arel::Attributes::Attribute
51
+ name = object.expr.name
52
+ name = "#{expr.relation.name}.#{name}" if expr.relation.name.to_s != table.name.to_s
53
+ visit name, Ansr::Arel::Visitors::Filter.new(attribute) if object.select
54
+ else
55
+ raise "Unexpected filter expression type #{object.expr.class}"
56
+ end
57
+ end
58
+
59
+ def visit_Ansr_Arel_Nodes_Facet(object, attribute)
60
+ expr = object.expr
61
+ case expr
62
+ when ::Arel::SqlLiteral
63
+ visit expr, Ansr::Arel::Visitors::Facet.new(attribute)
64
+ when ::Arel::Attributes::Attribute
65
+ name = object.expr.name
66
+ name = "#{expr.relation.name}.#{name}" if expr.relation.name.to_s != table.name.to_s
67
+ visit name, Ansr::Arel::Visitors::Facet.new(attribute) if object.select
68
+ else
69
+ raise "Unexpected filter expression type #{object.expr.class}"
70
+ end
71
+ end
72
+
73
+ def projections
74
+ query_opts[:fields] || []
75
+ end
76
+
77
+ def filter_projections
78
+ query_opts[:facets] || []
79
+ end
80
+
81
+
82
+ def field(field_name)
83
+ return unless field_name
84
+ old = query_opts[:fields] ? Array(query_opts[:fields]) : []
85
+ field_names = (old + Array(field_name)).uniq
86
+ if field_names[0]
87
+ query_opts[:fields] = field_names[1] ? field_names : field_names[0]
88
+ end
89
+ end
90
+
91
+ def filter_field(field_name)
92
+ return unless field_name
93
+ field_name = Array(field_name)
94
+ field_name.each {|fn| raise "#{fn} is not a facetable field" unless table.facets.include? fn.to_sym}
95
+ old = query_opts[:facets] ? Array(query_opts[:facets]) : []
96
+ field_names = (old + Array(field_name)).uniq
97
+ if field_names[0]
98
+ query_opts[:facets] = field_names[1] ? field_names : field_names[0]
99
+ end
100
+ end
101
+
102
+ def add_where_clause(attr_node, val)
103
+ field_key = field_key_from_node(attr_node)
104
+ if query_opts[field_key]
105
+ query_opts[field_key] = Array(query_opts[field_key]) << val
106
+ else
107
+ query_opts[field_key] = val
108
+ end
109
+ end
110
+
111
+ # the DPLA API makes no distinction between filter and normal queries
112
+ def visit_Arel_Nodes_Equality(object, attribute)
113
+ add_where_clause(object.left, object.right)
114
+ end
115
+
116
+ def visit_Arel_Nodes_NotEqual(object, attribute)
117
+ add_where_clause(object.left, "NOT " + object.right)
118
+ end
119
+ def visit_Arel_Nodes_Or(object, attribute)
120
+ add_where_clause(object.left, "OR " + object.right)
121
+ end
122
+
123
+ def visit_Arel_Nodes_Grouping(object, attribute)
124
+ visit object.expr, attribute
125
+ end
126
+
127
+ def visit_Arel_Nodes_Ordering(object, attribute)
128
+ if query_opts[:sort_by]
129
+ query_opts[:sort_by] = Array[query_opts[:sort_by]] << object.expr.name
130
+ else
131
+ query_opts[:sort_by] = object.expr.name
132
+ end
133
+ direction = :asc if (::Arel::Nodes::Ascending === object and direction)
134
+ direction = :desc if (::Arel::Nodes::Descending === object)
135
+ query_opts[:sort_order] = direction if direction
136
+ end
137
+
138
+ def order(*arel_nodes)
139
+ direction = nil
140
+ nodes = []
141
+ arel_nodes.inject(nodes) do |c, n|
142
+ if ::Arel::Nodes::Ordering === n
143
+ c << n
144
+ elsif n.is_a? String
145
+ _ns = n.split(',')
146
+ _ns.each do |_n|
147
+ _p = _n.split(/\s+/)
148
+ if (_p[1])
149
+ _p[1] = _p[1].downcase.to_sym
150
+ else
151
+ _p[1] = :asc
152
+ end
153
+ c << table[_p[0].to_sym].send(_p[1])
154
+ end
155
+ end
156
+ c
157
+ end
158
+ nodes.each do |node|
159
+ if ::Arel::Nodes::Ordering === node
160
+ if query_opts[:sort_by]
161
+ query_opts[:sort_by] = Array[query_opts[:sort_by]] << node.expr.name
162
+ else
163
+ query_opts[:sort_by] = node.expr.name
164
+ end
165
+ direction = :asc if (::Arel::Nodes::Ascending === node and direction)
166
+ direction = :desc if (::Arel::Nodes::Descending === node)
167
+ end
168
+ end
169
+ query_opts[:sort_order] = direction if direction
170
+ end
171
+
172
+ def visit_Arel_Nodes_Limit(object, attribute)
173
+ value = object.expr
174
+ if value and (value = value.to_i)
175
+ raise "Page size cannot be > 500 (#{value}" if value > 500
176
+ query_opts[:page_size] = value
177
+ end
178
+ end
179
+
180
+ def visit_Arel_Nodes_Offset(object, attribute)
181
+ value = object.expr
182
+ if value
183
+ query_opts[:page] = (value.to_i / (query_opts[:page_size] || Ansr::Relation::DEFAULT_PAGE_SIZE)) + 1
184
+ end
185
+ end
186
+
187
+ end
188
+ end
@@ -0,0 +1,9 @@
1
+ module Ansr::Dpla::Arel::Visitors
2
+ class ToNoSql < Ansr::Arel::Visitors::ToNoSql
3
+
4
+ def query_builder(opts = nil)
5
+ Ansr::Dpla::Arel::Visitors::QueryBuilder.new(table, opts)
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,58 @@
1
+ module Ansr::Dpla
2
+ module ConnectionAdapters
3
+ class NoSqlAdapter < Ansr::ConnectionAdapters::NoSqlAdapter
4
+
5
+ def self.connection_for(klass)
6
+ klass.api
7
+ end
8
+
9
+ def initialize(klass, logger = nil, pool = nil) #:nodoc:
10
+ super(klass, klass.api, logger, pool)
11
+ @visitor = Ansr::Dpla::Arel::Visitors::ToNoSql.new(@table)
12
+ end
13
+
14
+ def to_sql(*args)
15
+ to_nosql(*args)
16
+ end
17
+
18
+ def execute(query, name='ANSR-DPLA')
19
+ method = query.path
20
+ query = query.to_h if Ansr::Dpla::Request === query
21
+ query = query.dup
22
+ aliases = query.delete(:aliases)
23
+ json = @connection.send(method, query)
24
+ json = json.length > 0 ? JSON.load(json) : {'docs' => [], 'facets' => []}
25
+ if json['docs'] and aliases
26
+ json['docs'].each do |doc|
27
+ aliases.each do |k,v|
28
+ if doc[k]
29
+ old = doc.delete(k)
30
+ if old and doc[v]
31
+ doc[v] = Array(doc[v]) if doc[v]
32
+ Array(old).each {|ov| doc[v] << ov}
33
+ else
34
+ doc[v] = old
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ json
41
+ end
42
+
43
+ def table_exists?(table_name)
44
+ ['Collection', 'Item'].include? table_name
45
+ end
46
+
47
+ def sanitize_limit(limit_value)
48
+ if (0..500) === limit_value.to_s.to_i
49
+ limit_value
50
+ else
51
+ Ansr::Relation::DEFAULT_PAGE_SIZE
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+
58
+ end
@@ -6,6 +6,13 @@ module Ansr::Dpla
6
6
 
7
7
  include Querying
8
8
 
9
+ def self.inherited(subclass)
10
+ super(subclass)
11
+ subclass.configure do |config|
12
+ config[:table_class] = Ansr::Dpla::Arel::BigTable
13
+ end
14
+ end
15
+
9
16
  def assign_nested_parameter_attributes(pairs)
10
17
  pairs.each do |k, v|
11
18
  v = PseudoAssociate.new(v) if Hash === v
@@ -5,10 +5,14 @@ module Ansr::Dpla
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  module ClassMethods
8
+ def build_default_scope
9
+ Ansr::Dpla::Relation.new(model(), table())
10
+ end
11
+
8
12
  def api
9
13
  @api ||= begin
10
14
  a = (config[:api] || Ansr::Dpla::Api).new
11
- a.config(self.config)
15
+ a.config{|x| x.merge!(self.config)}
12
16
  a
13
17
  end
14
18
  end
@@ -17,16 +21,8 @@ module Ansr::Dpla
17
21
  @api = api
18
22
  end
19
23
 
20
- def table
21
- @big_table ||= Ansr::Dpla::Arel::BigTable.new(model(), {:config => config()})
22
- end
23
-
24
- def table=(val)
25
- @big_table = val
26
- end
27
-
28
24
  def connection_handler
29
- @connection_handler ||= Ansr::Model::ConnectionHandler.new(Ansr::Dpla::Arel::Connection)
25
+ @connection_handler ||= Ansr::Model::ConnectionHandler.new(Ansr::Dpla::ConnectionAdapters::NoSqlAdapter)
30
26
  end
31
27
 
32
28
  def references
@@ -0,0 +1,61 @@
1
+ require 'yaml'
2
+ require 'blacklight'
3
+ module Ansr::Dpla
4
+ class Relation < ::Ansr::Relation
5
+
6
+ def initialize(klass, table, values = {})
7
+ raise "Cannot search nil model" if klass.nil?
8
+ super(klass, table, values)
9
+ end
10
+
11
+ def facet_values=(values)
12
+ values.each {|value| raise "#{value.expr.name.to_sym} is not facetable" unless table.facets.include? value.expr.name.to_sym}
13
+ super
14
+ end
15
+
16
+ def empty?
17
+ count == 0
18
+ end
19
+
20
+ def many?
21
+ count > 1
22
+ end
23
+
24
+ def offset!(value)
25
+ page_size = self.limit_value || default_limit_value
26
+ if (value.to_i % page_size.to_i) != 0
27
+ raise "Bad offset #{value} for page size #{page_size}"
28
+ end
29
+ self.offset_value=value
30
+ self
31
+ end
32
+
33
+ def count
34
+ self.load
35
+ @response['count']
36
+ end
37
+
38
+ def filters_from(response)
39
+ f = {}
40
+ (response['facets'] || {}).inject(f) do |h,(k,v)|
41
+
42
+ if v['total'] != 0
43
+ items = v['terms'].collect do |term|
44
+ Blacklight::SolrResponse::Facets::FacetItem.new(:value => term['term'], :hits => term['count'])
45
+ end
46
+ options = {:sort => 'asc', :offset => 0}
47
+ h[k] = Blacklight::SolrResponse::Facets::FacetField.new k, items, options
48
+ end
49
+ h
50
+ end
51
+ f
52
+ end
53
+
54
+ def docs_from(response)
55
+ response['docs']
56
+ end
57
+
58
+ end
59
+
60
+
61
+ end
@@ -0,0 +1,5 @@
1
+ module Ansr::Dpla
2
+ class Request < ::Ansr::OpenStructWithHashAccess
3
+ attr_accessor :path
4
+ end
5
+ end
@@ -9,18 +9,21 @@ describe Ansr::Dpla::Api do
9
9
 
10
10
  it "should be configurable with a Hash" do
11
11
  config_fixture = {:api_key => :foo, :url => :bar}
12
- @test.config(config_fixture)
12
+ @test.config{|x| x.merge!(config_fixture)}
13
13
  expect(@test.url).to eql(:bar)
14
14
  end
15
15
 
16
16
  it "should be configurable with a path to a yaml" do
17
- @test.config(fixture_path('dpla.yml'))
17
+ open(fixture_path('dpla.yml')) do |blob|
18
+ config = YAML.load(blob)
19
+ @test.config{|x| x.merge!(config)}
20
+ end
18
21
  expect(@test.url).to eql('http://fake.dp.la/v0/')
19
22
  end
20
23
 
21
24
  it "should raise an error of the config doesn't have required fields" do
22
- expect { Ansr::Dpla::Api.new.config({:url => :foo})}.to raise_error
23
- Ansr::Dpla::Api.new.config({:url => :foo, :api_key => :foo})
25
+ expect { Ansr::Dpla::Api.new.config{|x| x.merge!(:url => :foo)}}.to raise_error
26
+ Ansr::Dpla::Api.new.config {|x| x.merge!({:url => :foo, :api_key => :foo})}
24
27
  end
25
28
 
26
29
  end
@@ -28,7 +31,7 @@ describe Ansr::Dpla::Api do
28
31
  describe '#path_for' do
29
32
  before do
30
33
  @test = Ansr::Dpla::Api.new
31
- @test.config({:api_key => :testing})
34
+ @test.config{|x| x.merge!(:api_key => :testing)}
32
35
  end
33
36
 
34
37
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Item do
4
4
  describe '.configure' do
5
5
  it "should store the configured Api class" do
6
- Item.configure({:api=>Ansr::Dpla::TestApi, :api_key => :dummy})
6
+ Item.configure {|x| x.merge!(:api=>Ansr::Dpla::TestApi, :api_key => :dummy)}
7
7
  expect(Item.api).to be_a Ansr::Dpla::TestApi
8
8
  end
9
9
  end
@@ -25,7 +25,7 @@ describe Item do
25
25
 
26
26
  describe '.where' do
27
27
  before do
28
- Item.configure({:api=>Ansr::Dpla::TestApi, :api_key => :dummy})
28
+ Item.configure{|x| x.merge!({:api=>Ansr::Dpla::TestApi, :api_key => :dummy})}
29
29
  end
30
30
  it 'should return a Relation when there is query information' do
31
31
  expect(Item.where({:q=>'kittens'})).to be_a Ansr::Relation
@@ -1,47 +1,55 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Ansr::Relation do
3
+ describe Ansr::Dpla::Relation do
4
4
  before do
5
5
  @kittens = read_fixture('kittens.jsonld')
6
6
  @faceted = read_fixture('kittens_faceted.jsonld')
7
7
  @empty = read_fixture('empty.jsonld')
8
8
  @mock_api = double('api')
9
- Item.config({:api_key => :foo})
9
+ Item.config{ |x| x[:api_key] = :foo}
10
10
  Item.engine.api= @mock_api
11
11
  end
12
+
13
+ subject { Ansr::Dpla::Relation.new(Item, Item.table) }
12
14
  describe '#filter' do
13
- it "do a single field, single value filter" do
14
- test = Ansr::Relation.new(Item, Item.table).filter(:object=>'kittens')
15
- @mock_api.should_receive(:items).with(:object => 'kittens', :facets => :object).and_return('')
16
- test.load
15
+ describe "do a single field, single value filter" do
16
+ it "with facet" do
17
+ test = subject.filter(:object=>'kittens').facet(:object)
18
+ @mock_api.should_receive(:items).with(:object => 'kittens', :facets => :object).and_return('')
19
+ test.load
20
+ end
21
+ it "without facet" do
22
+ test = subject.filter(:object=>'kittens')
23
+ @mock_api.should_receive(:items).with(:object => 'kittens').and_return('')
24
+ test.load
25
+ end
17
26
  end
18
27
  it "do a single field, multiple value filter" do
19
- test = Ansr::Relation.new(Item, Item.table).filter(:object=>['kittens', 'cats'])
28
+ test = subject.filter(:object=>['kittens', 'cats']).facet(:object)
20
29
  @mock_api.should_receive(:items).with(:object => ['kittens','cats'], :facets => :object).and_return('')
21
30
  test.load
22
31
  end
23
32
  it "do merge single field, multiple value filters" do
24
- test = Ansr::Relation.new(Item, Item.table).filter(:"provider.name"=>'kittens').filter(:"provider.name"=>'cats')
25
- @mock_api.should_receive(:items).with(:"provider.name" => ['kittens','cats'], :facets => :"provider.name").and_return('')
33
+ test = subject.filter(:"provider.name"=>'kittens').filter(:"provider.name"=>'cats').facet(:"provider.name")
34
+ @mock_api.should_receive(:items).with(hash_including(:"provider.name" => ['kittens','cats'], :facets => :"provider.name")).and_return('')
26
35
  test.load
27
36
  end
28
37
  it "do a multiple field, single value filter" do
29
- test = Ansr::Relation.new(Item, Item.table).filter(:object=>'kittens',:isShownAt=>'bears')
30
- @mock_api.should_receive(:items).with(:object => 'kittens', :isShownAt=>'bears', :facets => [:object, :isShownAt]).and_return('')
38
+ test = subject.filter(:object=>'kittens',:isShownAt=>'bears').facet([:object, :isShownAt])
39
+ @mock_api.should_receive(:items).with(hash_including(:object => 'kittens', :isShownAt=>'bears', :facets => [:object, :isShownAt])).and_return('')
31
40
  test.load
32
41
  end
33
42
  it "should keep scope distinct from spawned Relations" do
34
- test = Ansr::Relation.new(Item, Item.table).filter(:"provider.name"=>'kittens')
43
+ test = subject.filter(:"provider.name"=>'kittens').facet(:"provider.name")
35
44
  test.where(:q=>'cats')
36
45
  @mock_api.should_receive(:items).with(:"provider.name" => 'kittens', :facets => :"provider.name").and_return('')
37
46
  test.load
38
47
  end
39
- it "should raise an error if the requested field is not a filtered field" do
40
- test = Ansr::Relation.new(Item, Item.table)
41
- expect {test.filter(:foo=>'kittens')}.to raise_error
48
+ it "should raise an error if the requested field is not a facetable field" do
49
+ expect {subject.facet(:foo)}.to raise_error
42
50
  end
43
- it "should not require a search value for the filter" do
44
- test = Ansr::Relation.new(Item, Item.table).filter(:object)
51
+ it "should facet without a filter" do
52
+ test = subject.facet(:object)
45
53
  @mock_api.should_receive(:items).with(:facets => :object).and_return('')
46
54
  test.load
47
55
  end
@@ -52,7 +60,7 @@ describe Ansr::Relation do
52
60
  # Blacklight::SolrResponse::Facets::FacetItem.new(:value => s, :hits => v)
53
61
  # options = {:sort => 'asc', :offset => 0}
54
62
  # Blacklight::SolrResponse::Facets::FacetField.new name, items, options
55
- test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
63
+ test = subject.where(:q=>'kittens')
56
64
  @mock_api.should_receive(:items).with(:q => 'kittens').and_return(@faceted)
57
65
  test.load
58
66
  fkey = test.filters.keys.first
@@ -61,7 +69,7 @@ describe Ansr::Relation do
61
69
  facet.items
62
70
  end
63
71
  it 'should dispatch a query with no docs requested if not loaded' do
64
- test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
72
+ test = subject.where(:q=>'kittens')
65
73
  @mock_api.should_receive(:items).with(:q => 'kittens', :page_size=>0).once.and_return(@faceted)
66
74
  fkey = test.filters.keys.first
67
75
  facet = test.filters[fkey]