ansr 0.0.1
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.
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +127 -0
- data/ansr.gemspec +23 -0
- data/ansr_dpla/README.md +59 -0
- data/ansr_dpla/ansr_dpla.gemspec +27 -0
- data/ansr_dpla/app/models/collection.rb +2 -0
- data/ansr_dpla/app/models/item.rb +2 -0
- data/ansr_dpla/fixtures/collection.json +1 -0
- data/ansr_dpla/fixtures/collection.jsonld +14 -0
- data/ansr_dpla/fixtures/collections.json +1 -0
- data/ansr_dpla/fixtures/collections.jsonld +65 -0
- data/ansr_dpla/fixtures/dpla.yml +2 -0
- data/ansr_dpla/fixtures/empty.jsonld +1 -0
- data/ansr_dpla/fixtures/item.json +1 -0
- data/ansr_dpla/fixtures/item.jsonld +272 -0
- data/ansr_dpla/fixtures/kittens.json +1 -0
- data/ansr_dpla/fixtures/kittens.jsonld +2477 -0
- data/ansr_dpla/fixtures/kittens_faceted.json +1 -0
- data/ansr_dpla/fixtures/kittens_faceted.jsonld +2693 -0
- data/ansr_dpla/lib/ansr_dpla.rb +6 -0
- data/ansr_dpla/lib/ansr_dpla/api.rb +78 -0
- data/ansr_dpla/lib/ansr_dpla/arel.rb +8 -0
- data/ansr_dpla/lib/ansr_dpla/arel/big_table.rb +104 -0
- data/ansr_dpla/lib/ansr_dpla/arel/connection.rb +81 -0
- data/ansr_dpla/lib/ansr_dpla/arel/query_builder.rb +131 -0
- data/ansr_dpla/lib/ansr_dpla/model.rb +7 -0
- data/ansr_dpla/lib/ansr_dpla/model/base.rb +17 -0
- data/ansr_dpla/lib/ansr_dpla/model/pseudo_associate.rb +14 -0
- data/ansr_dpla/lib/ansr_dpla/model/querying.rb +38 -0
- data/ansr_dpla/spec/adpla_test_api.rb +9 -0
- data/ansr_dpla/spec/lib/api_spec.rb +110 -0
- data/ansr_dpla/spec/lib/item_spec.rb +57 -0
- data/ansr_dpla/spec/lib/relation/facet_spec.rb +74 -0
- data/ansr_dpla/spec/lib/relation/select_spec.rb +52 -0
- data/ansr_dpla/spec/lib/relation/where_spec.rb +74 -0
- data/ansr_dpla/spec/lib/relation_spec.rb +305 -0
- data/ansr_dpla/spec/spec_helper.rb +36 -0
- data/ansr_dpla/test/debug.rb +14 -0
- data/ansr_dpla/test/system.rb +50 -0
- data/lib/ansr.rb +16 -0
- data/lib/ansr/.DS_Store +0 -0
- data/lib/ansr/arel.rb +5 -0
- data/lib/ansr/arel/big_table.rb +24 -0
- data/lib/ansr/base.rb +29 -0
- data/lib/ansr/configurable.rb +20 -0
- data/lib/ansr/model.rb +159 -0
- data/lib/ansr/model/connection.rb +103 -0
- data/lib/ansr/model/connection_handler.rb +20 -0
- data/lib/ansr/relation.rb +121 -0
- data/lib/ansr/relation/arel_methods.rb +14 -0
- data/lib/ansr/relation/query_methods.rb +156 -0
- data/lib/ansr/sanitization.rb +36 -0
- data/lib/ansr/version.rb +6 -0
- metadata +196 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
module Ansr::Dpla
|
3
|
+
module Model
|
4
|
+
module Querying
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def api
|
9
|
+
@api ||= begin
|
10
|
+
a = (config[:api] || Ansr::Dpla::Api).new
|
11
|
+
a.config(self.config)
|
12
|
+
a
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def api=(api)
|
17
|
+
@api = api
|
18
|
+
end
|
19
|
+
|
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
|
+
def connection_handler
|
29
|
+
@connection_handler ||= Ansr::Model::ConnectionHandler.new(Ansr::Dpla::Arel::Connection)
|
30
|
+
end
|
31
|
+
|
32
|
+
def references
|
33
|
+
['provider', 'object']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ansr::Dpla::Api do
|
4
|
+
|
5
|
+
describe '#config' do
|
6
|
+
before do
|
7
|
+
@test = Ansr::Dpla::Api.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be configurable with a Hash" do
|
11
|
+
config_fixture = {:api_key => :foo, :url => :bar}
|
12
|
+
@test.config(config_fixture)
|
13
|
+
expect(@test.url).to eql(:bar)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be configurable with a path to a yaml" do
|
17
|
+
@test.config(fixture_path('dpla.yml'))
|
18
|
+
expect(@test.url).to eql('http://fake.dp.la/v0/')
|
19
|
+
end
|
20
|
+
|
21
|
+
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})
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#path_for' do
|
29
|
+
before do
|
30
|
+
@test = Ansr::Dpla::Api.new
|
31
|
+
@test.config({:api_key => :testing})
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
describe 'queries' do
|
36
|
+
it "should build paths for basic queries" do
|
37
|
+
fixture = {:foo => ['kittens', 'cats'], :bar => ['puppies', 'dogs']}
|
38
|
+
expected = 'tests?api_key=testing&foo=kittens+AND+cats&bar=puppies+AND+dogs'
|
39
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
40
|
+
expect(@test.items_path(fixture)).to eql(expected.sub(/^tests/,'items'))
|
41
|
+
expect(@test.collections_path(fixture)).to eql(expected.sub(/^tests/,'collections'))
|
42
|
+
expect(@test.item_path('foo')).to eql('items/foo?api_key=testing')
|
43
|
+
expect(@test.collection_path('foo')).to eql('collections/foo?api_key=testing')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should build paths for OR and NOT queries" do
|
47
|
+
fixture = {:foo => ['kittens', 'NOT cats']}
|
48
|
+
expected = 'tests?api_key=testing&foo=kittens+AND+NOT+cats'
|
49
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
50
|
+
|
51
|
+
fixture = {:foo => ['NOT kittens', 'cats']}
|
52
|
+
expected = 'tests?api_key=testing&foo=NOT+kittens+AND+cats'
|
53
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
54
|
+
|
55
|
+
fixture = {:foo => ['kittens', 'OR cats']}
|
56
|
+
expected = 'tests?api_key=testing&foo=kittens+OR+cats'
|
57
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
58
|
+
|
59
|
+
fixture = {:foo => ['OR kittens', 'cats']}
|
60
|
+
expected = 'tests?api_key=testing&foo=kittens+AND+cats'
|
61
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should build paths for facets right" do
|
66
|
+
fixture = {:foo => 'kittens', :facets => :bar}
|
67
|
+
expected = 'tests?api_key=testing&foo=kittens&facets=bar'
|
68
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
69
|
+
|
70
|
+
fixture = {:foo => 'kittens', :facets => [:bar, :baz]}
|
71
|
+
expected = 'tests?api_key=testing&foo=kittens&facets=bar%2Cbaz'
|
72
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
73
|
+
|
74
|
+
fixture = {:foo => 'kittens', :facets => 'bar,baz'}
|
75
|
+
expected = 'tests?api_key=testing&foo=kittens&facets=bar%2Cbaz'
|
76
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should build paths for sorts right" do
|
80
|
+
fixture = {:foo => 'kittens', :sort_by => [:bar, :baz]}
|
81
|
+
expected = 'tests?api_key=testing&foo=kittens&sort_by=bar%2Cbaz'
|
82
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
83
|
+
|
84
|
+
fixture = {:foo => 'kittens', :sort_by => 'bar,baz'}
|
85
|
+
expected = 'tests?api_key=testing&foo=kittens&sort_by=bar%2Cbaz'
|
86
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
87
|
+
|
88
|
+
fixture = {:foo => 'kittens', :sort_by => 'bar,baz', :sort_order => :desc}
|
89
|
+
expected = 'tests?api_key=testing&foo=kittens&sort_by=bar%2Cbaz&sort_order=desc'
|
90
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should build paths for field selections right" do
|
94
|
+
fixture = {:foo => 'kittens', :fields => [:bar, :baz]}
|
95
|
+
expected = 'tests?api_key=testing&foo=kittens&fields=bar%2Cbaz'
|
96
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
97
|
+
|
98
|
+
fixture = {:foo => 'kittens', :fields => 'bar,baz'}
|
99
|
+
expected = 'tests?api_key=testing&foo=kittens&fields=bar%2Cbaz'
|
100
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should build paths for limits and page sizes right" do
|
104
|
+
fixture = {:foo => 'kittens', :page_size=>25, :page=>4}
|
105
|
+
expected = 'tests?api_key=testing&foo=kittens&page_size=25&page=4'
|
106
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Item do
|
4
|
+
describe '.configure' do
|
5
|
+
it "should store the configured Api class" do
|
6
|
+
Item.configure({:api=>Ansr::Dpla::TestApi, :api_key => :dummy})
|
7
|
+
expect(Item.api).to be_a Ansr::Dpla::TestApi
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.find' do
|
12
|
+
it "should find an item given an id" do
|
13
|
+
mock_api = double('api')
|
14
|
+
Item.api = mock_api
|
15
|
+
mock_api.should_receive(:items).with(:id=>"123", :page_size=>1).and_return(read_fixture('item.jsonld'))
|
16
|
+
Item.find('123')
|
17
|
+
end
|
18
|
+
it "should raise an exception for a bad id" do
|
19
|
+
mock_api = double('api')
|
20
|
+
Item.api = mock_api
|
21
|
+
mock_api.should_receive(:items).with(:id=>"123", :page_size=>1).and_return(read_fixture('empty.jsonld'))
|
22
|
+
expect {Item.find('123')}.to raise_error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '.where' do
|
27
|
+
before do
|
28
|
+
Item.configure({:api=>Ansr::Dpla::TestApi, :api_key => :dummy})
|
29
|
+
end
|
30
|
+
it 'should return a Relation when there is query information' do
|
31
|
+
expect(Item.where({:q=>'kittens'})).to be_a Ansr::Relation
|
32
|
+
end
|
33
|
+
it 'should return itself when there is no query information' do
|
34
|
+
expect(Item.where({})).to be Item
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'accessor methods' do
|
39
|
+
before do
|
40
|
+
mock_api = double('api')
|
41
|
+
Item.api = mock_api
|
42
|
+
@hash = JSON.parse(read_fixture('item.jsonld'))['docs'][0]
|
43
|
+
@test = Item.new(@hash)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should dispatch method names to the hash' do
|
47
|
+
@test.dataProvider.should == "Boston Public Library"
|
48
|
+
@test.sourceResource.identifier.should == [ "Local accession: 08_06_000884" ]
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should miss methods for undefined fields' do
|
52
|
+
expect {@test.foo}.to raise_error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ansr::Relation do
|
4
|
+
before do
|
5
|
+
@kittens = read_fixture('kittens.jsonld')
|
6
|
+
@faceted = read_fixture('kittens_faceted.jsonld')
|
7
|
+
@empty = read_fixture('empty.jsonld')
|
8
|
+
@mock_api = double('api')
|
9
|
+
Item.config({:api_key => :foo})
|
10
|
+
Item.engine.api= @mock_api
|
11
|
+
end
|
12
|
+
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
|
17
|
+
end
|
18
|
+
it "do a single field, multiple value filter" do
|
19
|
+
test = Ansr::Relation.new(Item, Item.table).filter(:object=>['kittens', 'cats'])
|
20
|
+
@mock_api.should_receive(:items).with(:object => ['kittens','cats'], :facets => :object).and_return('')
|
21
|
+
test.load
|
22
|
+
end
|
23
|
+
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('')
|
26
|
+
test.load
|
27
|
+
end
|
28
|
+
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('')
|
31
|
+
test.load
|
32
|
+
end
|
33
|
+
it "should keep scope distinct from spawned Relations" do
|
34
|
+
test = Ansr::Relation.new(Item, Item.table).filter(:"provider.name"=>'kittens')
|
35
|
+
test.where(:q=>'cats')
|
36
|
+
@mock_api.should_receive(:items).with(:"provider.name" => 'kittens', :facets => :"provider.name").and_return('')
|
37
|
+
test.load
|
38
|
+
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
|
42
|
+
end
|
43
|
+
it "should not require a search value for the filter" do
|
44
|
+
test = Ansr::Relation.new(Item, Item.table).filter(:object)
|
45
|
+
@mock_api.should_receive(:items).with(:facets => :object).and_return('')
|
46
|
+
test.load
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#filters' do
|
51
|
+
it 'should return Blacklight types' do
|
52
|
+
# Blacklight::SolrResponse::Facets::FacetItem.new(:value => s, :hits => v)
|
53
|
+
# options = {:sort => 'asc', :offset => 0}
|
54
|
+
# Blacklight::SolrResponse::Facets::FacetField.new name, items, options
|
55
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
|
56
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').and_return(@faceted)
|
57
|
+
test.load
|
58
|
+
fkey = test.filters.keys.first
|
59
|
+
facet = test.filters[fkey]
|
60
|
+
expect(facet).to be_a(Blacklight::SolrResponse::Facets::FacetField)
|
61
|
+
facet.items
|
62
|
+
end
|
63
|
+
it 'should dispatch a query with no docs requested if not loaded' do
|
64
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
|
65
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :page_size=>0).once.and_return(@faceted)
|
66
|
+
fkey = test.filters.keys.first
|
67
|
+
facet = test.filters[fkey]
|
68
|
+
expect(facet).to be_a(Blacklight::SolrResponse::Facets::FacetField)
|
69
|
+
expect(test.loaded?).to be_false
|
70
|
+
test.filters # make sure we memoized the facet values
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ansr::Relation do
|
4
|
+
before do
|
5
|
+
@kittens = read_fixture('kittens.jsonld')
|
6
|
+
@faceted = read_fixture('kittens_faceted.jsonld')
|
7
|
+
@empty = read_fixture('empty.jsonld')
|
8
|
+
@mock_api = double('api')
|
9
|
+
Item.config({:api_key => :foo})
|
10
|
+
Item.engine.api= @mock_api
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#select' do
|
14
|
+
describe 'with a block given' do
|
15
|
+
it "should build an array" do
|
16
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
17
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').and_return(@kittens)
|
18
|
+
actual = test.select {|d| true}
|
19
|
+
expect(actual).to be_a(Array)
|
20
|
+
expect(actual.length).to eql(test.limit_value)
|
21
|
+
actual = test.select {|d| false}
|
22
|
+
expect(actual).to be_a(Array)
|
23
|
+
expect(actual.length).to eql(0)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
describe 'with a String or Symbol key given' do
|
27
|
+
it 'should change the requested document fields' do
|
28
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
29
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'name').and_return('')
|
30
|
+
test = test.select('name')
|
31
|
+
test.load
|
32
|
+
end
|
33
|
+
end
|
34
|
+
describe 'with a list of keys' do
|
35
|
+
it "should add all the requested document fields" do
|
36
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
37
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'name,foo').and_return('')
|
38
|
+
test = test.select(['name','foo'])
|
39
|
+
test.load
|
40
|
+
end
|
41
|
+
it "should add all the requested document fields and proxy them" do
|
42
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
43
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'object').and_return(@kittens)
|
44
|
+
test = test.select('object AS my_object')
|
45
|
+
test.load
|
46
|
+
expect(test.to_a.first['object']).to be_nil
|
47
|
+
expect(test.to_a.first['my_object']).to eql('http://ark.digitalcommonwealth.org/ark:/50959/6682xj30d/thumbnail')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ansr::Relation do
|
4
|
+
before do
|
5
|
+
@kittens = read_fixture('kittens.jsonld')
|
6
|
+
@faceted = read_fixture('kittens_faceted.jsonld')
|
7
|
+
@empty = read_fixture('empty.jsonld')
|
8
|
+
@mock_api = double('api')
|
9
|
+
Item.config({:api_key => :foo})
|
10
|
+
Item.engine.api= @mock_api
|
11
|
+
end
|
12
|
+
describe '#where' do
|
13
|
+
it "do a single field, single value where" do
|
14
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
|
15
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').and_return('')
|
16
|
+
test.load
|
17
|
+
end
|
18
|
+
it "do a single field, multiple value where" do
|
19
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>['kittens', 'cats'])
|
20
|
+
@mock_api.should_receive(:items).with(:q => ['kittens','cats']).and_return('')
|
21
|
+
test.load
|
22
|
+
end
|
23
|
+
it "do merge single field, multiple value wheres" do
|
24
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens').where(:q=>'cats')
|
25
|
+
@mock_api.should_receive(:items).with(:q => ['kittens','cats']).and_return('')
|
26
|
+
test.load
|
27
|
+
end
|
28
|
+
it "do a multiple field, single value where" do
|
29
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens',:foo=>'bears')
|
30
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :foo=>'bears').and_return('')
|
31
|
+
test.load
|
32
|
+
end
|
33
|
+
it "should keep scope distinct from spawned Relations" do
|
34
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
|
35
|
+
test.where(:q=>'cats')
|
36
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').and_return('')
|
37
|
+
test.load
|
38
|
+
end
|
39
|
+
describe '#not' do
|
40
|
+
it 'should exclude a specified map of field values' do
|
41
|
+
test = Ansr::Relation.new(Item, Item.table)
|
42
|
+
test = test.where(:foo =>'kittens')
|
43
|
+
test = test.where.not(:foo => 'cats')
|
44
|
+
@mock_api.should_receive(:items).with(:foo => ['kittens', 'NOT cats']).and_return('')
|
45
|
+
test.load
|
46
|
+
end
|
47
|
+
|
48
|
+
pending 'should exclude a value from the default query' do
|
49
|
+
test = Ansr::Relation.new(Item, Item.table)
|
50
|
+
test = test.where('kittens')
|
51
|
+
test = test.where.not('cats')
|
52
|
+
@mock_api.should_receive(:items).with(:q => ['kittens', 'NOT cats']).and_return('')
|
53
|
+
test.load
|
54
|
+
end
|
55
|
+
|
56
|
+
pending 'should exclude a specified field' do
|
57
|
+
test = Ansr::Relation.new(Item, Item.table)
|
58
|
+
test = test.where(:foo => 'kittens')
|
59
|
+
test = test.where.not('cats')
|
60
|
+
@mock_api.should_receive(:items).with(:foo => 'kittens', :q => 'NOT cats').and_return('')
|
61
|
+
test.load
|
62
|
+
end
|
63
|
+
end
|
64
|
+
describe '#or' do
|
65
|
+
it 'should union a specified map of field values' do
|
66
|
+
test = Ansr::Relation.new(Item, Item.table)
|
67
|
+
test = test.where(:foo =>'kittens')
|
68
|
+
test = test.where.or(:foo => 'cats')
|
69
|
+
@mock_api.should_receive(:items).with(:foo => ['kittens', 'OR cats']).and_return('')
|
70
|
+
test.load
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,305 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ansr::Relation do
|
4
|
+
before do
|
5
|
+
@kittens = read_fixture('kittens.jsonld')
|
6
|
+
@faceted = read_fixture('kittens_faceted.jsonld')
|
7
|
+
@empty = read_fixture('empty.jsonld')
|
8
|
+
@mock_api = double('api')
|
9
|
+
Item.config({:api_key => :foo})
|
10
|
+
Item.engine.api= @mock_api
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
it "should identify the correct resource for the model" do
|
15
|
+
class Foo
|
16
|
+
def self.table
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
test = Ansr::Relation.new(Foo, Foo.table)
|
22
|
+
expect(test.resource).to eql(:foos)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".load" do
|
27
|
+
it "should fetch the appropriate REST resource" do
|
28
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
|
29
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').and_return('')
|
30
|
+
test.load
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "Relation attributes" do
|
34
|
+
it "should set attributes correctly from a response" do
|
35
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
|
36
|
+
@mock_api.stub(:items).and_return(@kittens)
|
37
|
+
test.load
|
38
|
+
expect(test.count).to eql(144)
|
39
|
+
expect(test.offset_value).to eql(0)
|
40
|
+
expect(test.limit_value).to eql(10)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should set attributes correctly for an empty response" do
|
44
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
|
45
|
+
@mock_api.stub(:items).and_return(@empty)
|
46
|
+
test.load
|
47
|
+
expect(test.count).to eql(0)
|
48
|
+
expect(test.offset_value).to eql(0)
|
49
|
+
expect(test.limit_value).to eql(10)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#all' do
|
55
|
+
it 'should fail because we don\'t have a test yet'
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#none' do
|
59
|
+
it 'should fail because we don\'t have a test yet'
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '.order' do
|
63
|
+
describe 'with symbol parms' do
|
64
|
+
it "should add sort clause to query" do
|
65
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens').order(:foo)
|
66
|
+
expect(test).to be_a(Ansr::Relation)
|
67
|
+
@mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo).and_return('')
|
68
|
+
test.load
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should add multiple sort clauses to query" do
|
72
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens').order(:foo).order(:bar)
|
73
|
+
expect(test).to be_a(Ansr::Relation)
|
74
|
+
@mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>[:foo,:bar]).and_return('')
|
75
|
+
test.load
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should sort in descending order if necessary" do
|
79
|
+
test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens').order(:foo => :desc)
|
80
|
+
expect(test).to be_a(Ansr::Relation)
|
81
|
+
@mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo, :sort_order=>:desc).and_return('')
|
82
|
+
test.load
|
83
|
+
end
|
84
|
+
end
|
85
|
+
describe 'with String parms' do
|
86
|
+
it "should add sort clause to query" do
|
87
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo")
|
88
|
+
expect(test).to be_a(Ansr::Relation)
|
89
|
+
@mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo).and_return('')
|
90
|
+
test.load
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should sort in descending order if necessary" do
|
94
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
|
95
|
+
expect(test).to be_a(Ansr::Relation)
|
96
|
+
@mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo, :sort_order=>:desc).and_return('')
|
97
|
+
test.load
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#reorder' do
|
103
|
+
it "should replace existing order" do
|
104
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
|
105
|
+
test = test.reorder("foo ASC")
|
106
|
+
expect(test).to be_a(Ansr::Relation)
|
107
|
+
@mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo).and_return('')
|
108
|
+
test.load
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#reverse_order' do
|
113
|
+
it "should replace existing DESC order" do
|
114
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
|
115
|
+
test = test.reverse_order
|
116
|
+
expect(test).to be_a(Ansr::Relation)
|
117
|
+
@mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo).and_return('')
|
118
|
+
test.load
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should replace existing ASC order" do
|
122
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo ASC")
|
123
|
+
test = test.reverse_order
|
124
|
+
expect(test).to be_a(Ansr::Relation)
|
125
|
+
@mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo, :sort_order=>:desc).and_return('')
|
126
|
+
test.load
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#unscope' do
|
131
|
+
it 'should remove clauses only from spawned Relation' do
|
132
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
|
133
|
+
test2 = test.unscope(:order)
|
134
|
+
expect(test2).to be_a(Ansr::Relation)
|
135
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').and_return('')
|
136
|
+
test2.load
|
137
|
+
expect(test.order_values.empty?).to be_false
|
138
|
+
end
|
139
|
+
# ActiveRecord::QueryMethods.VALID_UNSCOPING_VALUES =>
|
140
|
+
# Set.new([:where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having])
|
141
|
+
it 'should reject bad scope keys' do
|
142
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
|
143
|
+
expect { test.unscope(:foo) }.to raise_error
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '#select' do
|
148
|
+
describe 'with a block given' do
|
149
|
+
it "should build an array" do
|
150
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
151
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').and_return(@kittens)
|
152
|
+
actual = test.select {|d| true}
|
153
|
+
expect(actual).to be_a(Array)
|
154
|
+
expect(actual.length).to eql(test.limit_value)
|
155
|
+
actual = test.select {|d| false}
|
156
|
+
expect(actual).to be_a(Array)
|
157
|
+
expect(actual.length).to eql(0)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
describe 'with a String or Symbol key given' do
|
161
|
+
it 'should change the requested document fields' do
|
162
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
163
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'name').and_return('')
|
164
|
+
test = test.select('name')
|
165
|
+
test.load
|
166
|
+
end
|
167
|
+
end
|
168
|
+
describe 'with a list of keys' do
|
169
|
+
it "should add all the requested document fields" do
|
170
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
171
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'name,foo').and_return('')
|
172
|
+
test = test.select(['name','foo'])
|
173
|
+
test.load
|
174
|
+
end
|
175
|
+
it "should add all the requested document fields and proxy them" do
|
176
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
177
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'object').and_return(@kittens)
|
178
|
+
test = test.select('object AS my_object')
|
179
|
+
test.load
|
180
|
+
expect(test.to_a.first['object']).to be_nil
|
181
|
+
expect(test.to_a.first['my_object']).to eql('http://ark.digitalcommonwealth.org/ark:/50959/6682xj30d/thumbnail')
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe '#limit' do
|
187
|
+
it "should add page_size to the query params" do
|
188
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
189
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :page_size=>17).and_return('')
|
190
|
+
test = test.limit(17)
|
191
|
+
test.load
|
192
|
+
end
|
193
|
+
it "should raise an error if limit > 500" do
|
194
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
195
|
+
test = test.limit(500)
|
196
|
+
expect {test.load }.to raise_error
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe '#offset' do
|
201
|
+
it "should add page to the query params when page_size is defaulted" do
|
202
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
203
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :page=>3).and_return('')
|
204
|
+
test = test.offset(20)
|
205
|
+
test.load
|
206
|
+
end
|
207
|
+
it 'should raise an error if an offset is requested that is not a multiple of the page size' do
|
208
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').limit(12)
|
209
|
+
expect{test.offset(17)}.to raise_error(/^Bad/)
|
210
|
+
test.offset(24)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe '#to_a' do
|
215
|
+
it 'should load the records and return them' do
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe '#loaded?' do
|
220
|
+
it 'should be false before and true after' do
|
221
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
222
|
+
@mock_api.stub(:items).with(:q => 'kittens').and_return('')
|
223
|
+
expect(test.loaded?).to be_false
|
224
|
+
test.load
|
225
|
+
expect(test.loaded?).to be_true
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
describe '#any?'
|
231
|
+
|
232
|
+
|
233
|
+
describe '#blank?' do
|
234
|
+
it 'should load the records via to_a'
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
describe '#count' do
|
239
|
+
end
|
240
|
+
|
241
|
+
describe '#empty?' do
|
242
|
+
it 'should not make another call if records are loaded' do
|
243
|
+
test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
|
244
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').once.and_return(@empty)
|
245
|
+
test.load
|
246
|
+
expect(test.loaded?).to be_true
|
247
|
+
expect(test.empty?).to be_true
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
describe "#spawn" do
|
253
|
+
it "should create new, independent Relations from Query methods"
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
describe 'RDBMS-specific methods' do
|
258
|
+
describe '#references' do
|
259
|
+
it 'should not do anything at all'
|
260
|
+
end
|
261
|
+
describe '#joins' do
|
262
|
+
it 'should not do anything at all'
|
263
|
+
end
|
264
|
+
describe '#distinct and #uniq' do
|
265
|
+
it 'should not do anything at all'
|
266
|
+
end
|
267
|
+
describe '#preload' do
|
268
|
+
it 'should not do anything at all'
|
269
|
+
end
|
270
|
+
describe '#includes' do
|
271
|
+
it 'should not do anything at all'
|
272
|
+
end
|
273
|
+
describe '#having' do
|
274
|
+
it 'should not do anything at all'
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe 'read-write methods' do
|
279
|
+
describe '#readonly' do
|
280
|
+
it "should blissfully ignore no-args or true"
|
281
|
+
|
282
|
+
it "should refuse values of false"
|
283
|
+
|
284
|
+
end
|
285
|
+
describe '#create_with' do
|
286
|
+
it 'should not do anything at all'
|
287
|
+
end
|
288
|
+
describe '#insert' do
|
289
|
+
it 'should not do anything at all'
|
290
|
+
end
|
291
|
+
describe '#delete' do
|
292
|
+
it 'should not do anything at all'
|
293
|
+
end
|
294
|
+
describe '#delete_all' do
|
295
|
+
it 'should not do anything at all'
|
296
|
+
end
|
297
|
+
describe '#destroy' do
|
298
|
+
it 'should not do anything at all'
|
299
|
+
end
|
300
|
+
describe '#destroy_all' do
|
301
|
+
it 'should not do anything at all'
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|