ansr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +127 -0
  4. data/ansr.gemspec +23 -0
  5. data/ansr_dpla/README.md +59 -0
  6. data/ansr_dpla/ansr_dpla.gemspec +27 -0
  7. data/ansr_dpla/app/models/collection.rb +2 -0
  8. data/ansr_dpla/app/models/item.rb +2 -0
  9. data/ansr_dpla/fixtures/collection.json +1 -0
  10. data/ansr_dpla/fixtures/collection.jsonld +14 -0
  11. data/ansr_dpla/fixtures/collections.json +1 -0
  12. data/ansr_dpla/fixtures/collections.jsonld +65 -0
  13. data/ansr_dpla/fixtures/dpla.yml +2 -0
  14. data/ansr_dpla/fixtures/empty.jsonld +1 -0
  15. data/ansr_dpla/fixtures/item.json +1 -0
  16. data/ansr_dpla/fixtures/item.jsonld +272 -0
  17. data/ansr_dpla/fixtures/kittens.json +1 -0
  18. data/ansr_dpla/fixtures/kittens.jsonld +2477 -0
  19. data/ansr_dpla/fixtures/kittens_faceted.json +1 -0
  20. data/ansr_dpla/fixtures/kittens_faceted.jsonld +2693 -0
  21. data/ansr_dpla/lib/ansr_dpla.rb +6 -0
  22. data/ansr_dpla/lib/ansr_dpla/api.rb +78 -0
  23. data/ansr_dpla/lib/ansr_dpla/arel.rb +8 -0
  24. data/ansr_dpla/lib/ansr_dpla/arel/big_table.rb +104 -0
  25. data/ansr_dpla/lib/ansr_dpla/arel/connection.rb +81 -0
  26. data/ansr_dpla/lib/ansr_dpla/arel/query_builder.rb +131 -0
  27. data/ansr_dpla/lib/ansr_dpla/model.rb +7 -0
  28. data/ansr_dpla/lib/ansr_dpla/model/base.rb +17 -0
  29. data/ansr_dpla/lib/ansr_dpla/model/pseudo_associate.rb +14 -0
  30. data/ansr_dpla/lib/ansr_dpla/model/querying.rb +38 -0
  31. data/ansr_dpla/spec/adpla_test_api.rb +9 -0
  32. data/ansr_dpla/spec/lib/api_spec.rb +110 -0
  33. data/ansr_dpla/spec/lib/item_spec.rb +57 -0
  34. data/ansr_dpla/spec/lib/relation/facet_spec.rb +74 -0
  35. data/ansr_dpla/spec/lib/relation/select_spec.rb +52 -0
  36. data/ansr_dpla/spec/lib/relation/where_spec.rb +74 -0
  37. data/ansr_dpla/spec/lib/relation_spec.rb +305 -0
  38. data/ansr_dpla/spec/spec_helper.rb +36 -0
  39. data/ansr_dpla/test/debug.rb +14 -0
  40. data/ansr_dpla/test/system.rb +50 -0
  41. data/lib/ansr.rb +16 -0
  42. data/lib/ansr/.DS_Store +0 -0
  43. data/lib/ansr/arel.rb +5 -0
  44. data/lib/ansr/arel/big_table.rb +24 -0
  45. data/lib/ansr/base.rb +29 -0
  46. data/lib/ansr/configurable.rb +20 -0
  47. data/lib/ansr/model.rb +159 -0
  48. data/lib/ansr/model/connection.rb +103 -0
  49. data/lib/ansr/model/connection_handler.rb +20 -0
  50. data/lib/ansr/relation.rb +121 -0
  51. data/lib/ansr/relation/arel_methods.rb +14 -0
  52. data/lib/ansr/relation/query_methods.rb +156 -0
  53. data/lib/ansr/sanitization.rb +36 -0
  54. data/lib/ansr/version.rb +6 -0
  55. 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,9 @@
1
+ module Ansr::Dpla
2
+ class TestApi
3
+ include Ansr::Configurable
4
+ def items(opts={})
5
+ end
6
+ def collections(opts={})
7
+ end
8
+ end
9
+ 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