ansr_dpla 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +137 -0
- data/README.md +59 -0
- data/ansr_dpla.gemspec +27 -0
- data/app/models/collection.rb +2 -0
- data/app/models/item.rb +2 -0
- data/fixtures/collection.json +1 -0
- data/fixtures/collection.jsonld +14 -0
- data/fixtures/collections.json +1 -0
- data/fixtures/collections.jsonld +65 -0
- data/fixtures/dpla.yml +2 -0
- data/fixtures/empty.jsonld +1 -0
- data/fixtures/item.json +1 -0
- data/fixtures/item.jsonld +272 -0
- data/fixtures/kittens.json +1 -0
- data/fixtures/kittens.jsonld +2477 -0
- data/fixtures/kittens_faceted.json +1 -0
- data/fixtures/kittens_faceted.jsonld +2693 -0
- data/lib/ansr_dpla.rb +9 -0
- data/lib/ansr_dpla/api.rb +78 -0
- data/lib/ansr_dpla/arel.rb +7 -0
- data/lib/ansr_dpla/arel/big_table.rb +108 -0
- data/lib/ansr_dpla/arel/visitors.rb +6 -0
- data/lib/ansr_dpla/arel/visitors/query_builder.rb +188 -0
- data/lib/ansr_dpla/arel/visitors/to_no_sql.rb +9 -0
- data/lib/ansr_dpla/connection_adapters/no_sql_adapter.rb +58 -0
- data/lib/ansr_dpla/model.rb +7 -0
- data/lib/ansr_dpla/model/base.rb +24 -0
- data/lib/ansr_dpla/model/pseudo_associate.rb +14 -0
- data/lib/ansr_dpla/model/querying.rb +34 -0
- data/lib/ansr_dpla/relation.rb +60 -0
- data/lib/ansr_dpla/request.rb +5 -0
- data/spec/adpla_test_api.rb +9 -0
- data/spec/lib/api_spec.rb +113 -0
- data/spec/lib/item_spec.rb +57 -0
- data/spec/lib/relation/facet_spec.rb +82 -0
- data/spec/lib/relation/select_spec.rb +54 -0
- data/spec/lib/relation/where_spec.rb +74 -0
- data/spec/lib/relation_spec.rb +307 -0
- data/spec/spec_helper.rb +36 -0
- data/test/debug.rb +14 -0
- data/test/system.rb +52 -0
- metadata +236 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'ansr'
|
2
|
+
module Ansr::Dpla
|
3
|
+
module Model
|
4
|
+
class Base < Ansr::Base
|
5
|
+
self.abstract_class = true
|
6
|
+
|
7
|
+
include Querying
|
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
|
+
|
16
|
+
def assign_nested_parameter_attributes(pairs)
|
17
|
+
pairs.each do |k, v|
|
18
|
+
v = PseudoAssociate.new(v) if Hash === v
|
19
|
+
_assign_attribute(k, v)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# a class to pretend the unfindable "associations" are real models
|
2
|
+
module Ansr::Dpla
|
3
|
+
module Model
|
4
|
+
class PseudoAssociate
|
5
|
+
def initialize(doc = {})
|
6
|
+
@doc = doc.with_indifferent_access
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(name, *args)
|
10
|
+
@doc[name] or super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
module Ansr::Dpla
|
3
|
+
module Model
|
4
|
+
module Querying
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def build_default_scope
|
9
|
+
Ansr::Dpla::Relation.new(model(), table())
|
10
|
+
end
|
11
|
+
|
12
|
+
def api
|
13
|
+
@api ||= begin
|
14
|
+
a = (config[:api] || Ansr::Dpla::Api).new
|
15
|
+
a.config{|x| x.merge!(self.config)}
|
16
|
+
a
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def api=(api)
|
21
|
+
@api = api
|
22
|
+
end
|
23
|
+
|
24
|
+
def connection_handler
|
25
|
+
@connection_handler ||= Ansr::Model::ConnectionHandler.new(Ansr::Dpla::ConnectionAdapters::NoSqlAdapter)
|
26
|
+
end
|
27
|
+
|
28
|
+
def references
|
29
|
+
['provider', 'object']
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module Ansr::Dpla
|
3
|
+
class Relation < ::Ansr::Relation
|
4
|
+
|
5
|
+
def initialize(klass, table, values = {})
|
6
|
+
raise "Cannot search nil model" if klass.nil?
|
7
|
+
super(klass, table, values)
|
8
|
+
end
|
9
|
+
|
10
|
+
def facet_values=(values)
|
11
|
+
values.each {|value| raise "#{value.expr.name.to_sym} is not facetable" unless table.facets.include? value.expr.name.to_sym}
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def empty?
|
16
|
+
count == 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def many?
|
20
|
+
count > 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def offset!(value)
|
24
|
+
page_size = self.limit_value || default_limit_value
|
25
|
+
if (value.to_i % page_size.to_i) != 0
|
26
|
+
raise "Bad offset #{value} for page size #{page_size}"
|
27
|
+
end
|
28
|
+
self.offset_value=value
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def count
|
33
|
+
self.load
|
34
|
+
@response['count']
|
35
|
+
end
|
36
|
+
|
37
|
+
def filters_from(response)
|
38
|
+
f = {}
|
39
|
+
(response['facets'] || {}).inject(f) do |h,(k,v)|
|
40
|
+
|
41
|
+
if v['total'] != 0
|
42
|
+
items = v['terms'].collect do |term|
|
43
|
+
Ansr::Facets::FacetItem.new(:value => term['term'], :hits => term['count'])
|
44
|
+
end
|
45
|
+
options = {:sort => 'asc', :offset => 0}
|
46
|
+
h[k] = Ansr::Facets::FacetField.new k, items, options
|
47
|
+
end
|
48
|
+
h
|
49
|
+
end
|
50
|
+
f
|
51
|
+
end
|
52
|
+
|
53
|
+
def docs_from(response)
|
54
|
+
response['docs']
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,113 @@
|
|
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{|x| x.merge!(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
|
+
open(fixture_path('dpla.yml')) do |blob|
|
18
|
+
config = YAML.load(blob)
|
19
|
+
@test.config{|x| x.merge!(config)}
|
20
|
+
end
|
21
|
+
expect(@test.url).to eql('http://fake.dp.la/v0/')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise an error of the config doesn't have required fields" do
|
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})}
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#path_for' do
|
32
|
+
before do
|
33
|
+
@test = Ansr::Dpla::Api.new
|
34
|
+
@test.config{|x| x.merge!(:api_key => :testing)}
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
describe 'queries' do
|
39
|
+
it "should build paths for basic queries" do
|
40
|
+
fixture = {:foo => ['kittens', 'cats'], :bar => ['puppies', 'dogs']}
|
41
|
+
expected = 'tests?api_key=testing&foo=kittens+AND+cats&bar=puppies+AND+dogs'
|
42
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
43
|
+
expect(@test.items_path(fixture)).to eql(expected.sub(/^tests/,'items'))
|
44
|
+
expect(@test.collections_path(fixture)).to eql(expected.sub(/^tests/,'collections'))
|
45
|
+
expect(@test.item_path('foo')).to eql('items/foo?api_key=testing')
|
46
|
+
expect(@test.collection_path('foo')).to eql('collections/foo?api_key=testing')
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should build paths for OR and NOT queries" do
|
50
|
+
fixture = {:foo => ['kittens', 'NOT cats']}
|
51
|
+
expected = 'tests?api_key=testing&foo=kittens+AND+NOT+cats'
|
52
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
53
|
+
|
54
|
+
fixture = {:foo => ['NOT kittens', 'cats']}
|
55
|
+
expected = 'tests?api_key=testing&foo=NOT+kittens+AND+cats'
|
56
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
57
|
+
|
58
|
+
fixture = {:foo => ['kittens', 'OR cats']}
|
59
|
+
expected = 'tests?api_key=testing&foo=kittens+OR+cats'
|
60
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
61
|
+
|
62
|
+
fixture = {:foo => ['OR kittens', 'cats']}
|
63
|
+
expected = 'tests?api_key=testing&foo=kittens+AND+cats'
|
64
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should build paths for facets right" do
|
69
|
+
fixture = {:foo => 'kittens', :facets => :bar}
|
70
|
+
expected = 'tests?api_key=testing&foo=kittens&facets=bar'
|
71
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
72
|
+
|
73
|
+
fixture = {:foo => 'kittens', :facets => [:bar, :baz]}
|
74
|
+
expected = 'tests?api_key=testing&foo=kittens&facets=bar%2Cbaz'
|
75
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
76
|
+
|
77
|
+
fixture = {:foo => 'kittens', :facets => 'bar,baz'}
|
78
|
+
expected = 'tests?api_key=testing&foo=kittens&facets=bar%2Cbaz'
|
79
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should build paths for sorts right" do
|
83
|
+
fixture = {:foo => 'kittens', :sort_by => [:bar, :baz]}
|
84
|
+
expected = 'tests?api_key=testing&foo=kittens&sort_by=bar%2Cbaz'
|
85
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
86
|
+
|
87
|
+
fixture = {:foo => 'kittens', :sort_by => 'bar,baz'}
|
88
|
+
expected = 'tests?api_key=testing&foo=kittens&sort_by=bar%2Cbaz'
|
89
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
90
|
+
|
91
|
+
fixture = {:foo => 'kittens', :sort_by => 'bar,baz', :sort_order => :desc}
|
92
|
+
expected = 'tests?api_key=testing&foo=kittens&sort_by=bar%2Cbaz&sort_order=desc'
|
93
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should build paths for field selections right" do
|
97
|
+
fixture = {:foo => 'kittens', :fields => [:bar, :baz]}
|
98
|
+
expected = 'tests?api_key=testing&foo=kittens&fields=bar%2Cbaz'
|
99
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
100
|
+
|
101
|
+
fixture = {:foo => 'kittens', :fields => 'bar,baz'}
|
102
|
+
expected = 'tests?api_key=testing&foo=kittens&fields=bar%2Cbaz'
|
103
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should build paths for limits and page sizes right" do
|
107
|
+
fixture = {:foo => 'kittens', :page_size=>25, :page=>4}
|
108
|
+
expected = 'tests?api_key=testing&foo=kittens&page_size=25&page=4'
|
109
|
+
expect(@test.path_for('tests', fixture)).to eql(expected)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
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 {|x| x.merge!(: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{|x| x.merge!({: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,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ansr::Dpla::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{ |x| x[:api_key] = :foo}
|
10
|
+
Item.engine.api= @mock_api
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { Ansr::Dpla::Relation.new(Item, Item.table) }
|
14
|
+
describe '#filter' do
|
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
|
26
|
+
end
|
27
|
+
it "do a single field, multiple value filter" do
|
28
|
+
test = subject.filter(:object=>['kittens', 'cats']).facet(:object)
|
29
|
+
@mock_api.should_receive(:items).with(:object => ['kittens','cats'], :facets => :object).and_return('')
|
30
|
+
test.load
|
31
|
+
end
|
32
|
+
it "do merge single field, multiple value filters" do
|
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('')
|
35
|
+
test.load
|
36
|
+
end
|
37
|
+
it "do a multiple field, single value filter" do
|
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('')
|
40
|
+
test.load
|
41
|
+
end
|
42
|
+
it "should keep scope distinct from spawned Relations" do
|
43
|
+
test = subject.filter(:"provider.name"=>'kittens').facet(:"provider.name")
|
44
|
+
test.where(:q=>'cats')
|
45
|
+
@mock_api.should_receive(:items).with(:"provider.name" => 'kittens', :facets => :"provider.name").and_return('')
|
46
|
+
test.load
|
47
|
+
end
|
48
|
+
it "should raise an error if the requested field is not a facetable field" do
|
49
|
+
expect {subject.facet(:foo)}.to raise_error
|
50
|
+
end
|
51
|
+
it "should facet without a filter" do
|
52
|
+
test = subject.facet(:object)
|
53
|
+
@mock_api.should_receive(:items).with(:facets => :object).and_return('')
|
54
|
+
test.load
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#filters' do
|
59
|
+
it 'should return Blacklight types' do
|
60
|
+
# Blacklight::SolrResponse::Facets::FacetItem.new(:value => s, :hits => v)
|
61
|
+
# options = {:sort => 'asc', :offset => 0}
|
62
|
+
# Blacklight::SolrResponse::Facets::FacetField.new name, items, options
|
63
|
+
test = subject.where(:q=>'kittens')
|
64
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').and_return(@faceted)
|
65
|
+
test.load
|
66
|
+
fkey = test.filters.keys.first
|
67
|
+
facet = test.filters[fkey]
|
68
|
+
expect(facet).to be_a(Ansr::Facets::FacetField)
|
69
|
+
facet.items
|
70
|
+
end
|
71
|
+
it 'should dispatch a query with no docs requested if not loaded' do
|
72
|
+
test = subject.where(:q=>'kittens')
|
73
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :page_size=>0).once.and_return(@faceted)
|
74
|
+
fkey = test.filters.keys.first
|
75
|
+
facet = test.filters[fkey]
|
76
|
+
expect(facet).to be_a(Ansr::Facets::FacetField)
|
77
|
+
expect(test.loaded?).to be_false
|
78
|
+
test.filters # make sure we memoized the facet values
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,54 @@
|
|
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{ |x| x[:api_key] = :foo}
|
10
|
+
Item.engine.api= @mock_api
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { Ansr::Dpla::Relation.new(Item, Item.table) }
|
14
|
+
|
15
|
+
describe '#select' do
|
16
|
+
describe 'with a block given' do
|
17
|
+
it "should build an array" do
|
18
|
+
test = subject.where(q:'kittens')
|
19
|
+
@mock_api.should_receive(:items).with(:q => 'kittens').and_return(@kittens)
|
20
|
+
actual = test.select {|d| true}
|
21
|
+
expect(actual).to be_a(Array)
|
22
|
+
expect(actual.length).to eql(test.limit_value)
|
23
|
+
actual = test.select {|d| false}
|
24
|
+
expect(actual).to be_a(Array)
|
25
|
+
expect(actual.length).to eql(0)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
describe 'with a String or Symbol key given' do
|
29
|
+
it 'should change the requested document fields' do
|
30
|
+
test = subject.where(q:'kittens')
|
31
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :fields=>:name).and_return('')
|
32
|
+
test = test.select('name')
|
33
|
+
test.load
|
34
|
+
end
|
35
|
+
end
|
36
|
+
describe 'with a list of keys' do
|
37
|
+
it "should add all the requested document fields" do
|
38
|
+
test = subject.where(q:'kittens')
|
39
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :fields=>[:name,:foo]).and_return('')
|
40
|
+
test = test.select(['name','foo'])
|
41
|
+
test.load
|
42
|
+
end
|
43
|
+
it "should add all the requested document fields and proxy them" do
|
44
|
+
test = subject.where(q:'kittens')
|
45
|
+
@mock_api.should_receive(:items).with(:q => 'kittens', :fields=>:object).and_return(@kittens)
|
46
|
+
test = test.select('object AS my_object')
|
47
|
+
test.load
|
48
|
+
expect(test.to_a.first['object']).to be_nil
|
49
|
+
expect(test.to_a.first['my_object']).to eql('http://ark.digitalcommonwealth.org/ark:/50959/6682xj30d/thumbnail')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|