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.
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