active-triples 0.11.0 → 1.0.0.rc1

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.
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ describe ActiveTriples::NodeConfig do
5
+ subject(:config) { described_class.new(term, predicate) }
6
+ let(:predicate) { RDF::URI(nil) }
7
+ let(:term) { :moomin }
8
+
9
+ it { is_expected.to have_attributes(predicate: predicate, term: term) }
10
+
11
+ describe '#[]' do
12
+ subject(:config) { described_class.new(term, predicate, some_opt: :moomin) }
13
+
14
+ it 'accesses arbitrary opts' do
15
+ expect(config[:some_opt]).to eq :moomin
16
+ end
17
+ end
18
+
19
+ describe '#cast' do
20
+ it 'defaults to true' do
21
+ expect { config.cast = false }
22
+ .to change { config.cast }
23
+ .from(true)
24
+ .to(false)
25
+ end
26
+
27
+ it 'is set with the initializer' do
28
+ expect(described_class.new(term, predicate, cast: false).cast).to be false
29
+ end
30
+ end
31
+
32
+ describe '#with_index' do
33
+ it 'yields an index configuration object' do
34
+ expect { |b| config.with_index(&b) }
35
+ .to yield_with_args(an_instance_of(described_class::IndexObject))
36
+ end
37
+
38
+ it 'accepts behavior settings' do
39
+ config.with_index do |index|
40
+ index.as :moomin, :snork
41
+ end
42
+
43
+ expect(config.behaviors).to contain_exactly :moomin, :snork
44
+ end
45
+
46
+ it 'accepts type settings' do
47
+ config.with_index do |index|
48
+ index.type :moomin
49
+ end
50
+
51
+ expect(config.type).to eq :moomin
52
+ end
53
+ end
54
+ end
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
  describe ActiveTriples::ParentStrategy do
5
5
  subject { described_class.new(rdf_source) }
6
6
  let(:rdf_source) { BasicPersistable.new }
7
-
7
+
8
8
  shared_context 'with a parent' do
9
9
  subject { rdf_source.persistence_strategy }
10
10
  let(:parent) { BasicPersistable.new }
@@ -50,7 +50,7 @@ describe ActiveTriples::ParentStrategy do
50
50
  rdf_source.insert(*statements)
51
51
  subject.persist!
52
52
  end
53
-
53
+
54
54
  let(:statements) do
55
55
  [RDF::Statement(subject.source.rdf_subject, RDF::Vocab::DC.title, 'moomin'),
56
56
  RDF::Statement(subject.parent, RDF::Vocab::DC.relation, subject.source.rdf_subject)]
@@ -58,7 +58,7 @@ describe ActiveTriples::ParentStrategy do
58
58
 
59
59
  it 'removes graph from the parent' do
60
60
  subject.destroy
61
-
61
+
62
62
  statements.each do |statement|
63
63
  expect(subject.parent.statements).not_to have_statement statement
64
64
  end
@@ -83,18 +83,18 @@ describe ActiveTriples::ParentStrategy do
83
83
 
84
84
  context 'with parent' do
85
85
  include_context 'with a parent'
86
-
86
+
87
87
  it 'gives the parent' do
88
88
  expect(subject.ancestors).to contain_exactly(parent)
89
89
  end
90
90
 
91
91
  context 'and nested parents' do
92
92
  let(:parents) do
93
- [double('second', persistence_strategy: double('strategy2')),
93
+ [double('second', persistence_strategy: double('strategy2')),
94
94
  double('third', persistence_strategy: double('strategy3'))]
95
95
  end
96
96
  let(:last) { double('last', persistence_strategy: double('last_strategy')) }
97
-
97
+
98
98
  it 'gives all ancestors' do
99
99
  allow(parent.persistence_strategy)
100
100
  .to receive(:parent).and_return(parents.first)
@@ -102,7 +102,7 @@ describe ActiveTriples::ParentStrategy do
102
102
  .to receive(:parent).and_return(parents[1])
103
103
  allow(parents[1].persistence_strategy)
104
104
  .to receive(:parent).and_return(last)
105
-
105
+
106
106
  expect(subject.ancestors)
107
107
  .to contain_exactly(*(parents << parent << last))
108
108
  end
@@ -148,7 +148,19 @@ describe ActiveTriples::ParentStrategy do
148
148
  describe '#parent' do
149
149
  it { is_expected.to have_attributes(:parent => nil) }
150
150
 
151
- it 'requires its parent to be RDF::Mutable' do
151
+ context 'with a parent' do
152
+ include_context 'with a parent'
153
+ it { is_expected.to have_attributes(:parent => parent) }
154
+ end
155
+ end
156
+
157
+ describe '#parent=' do
158
+ it 'requires a non-nil value' do
159
+ expect { subject.parent = nil }
160
+ .to raise_error described_class::NilParentError
161
+ end
162
+
163
+ it 'requires the value to be RDF::Mutable' do
152
164
  expect { subject.parent = Object.new }
153
165
  .to raise_error described_class::UnmutableParentError
154
166
  end
@@ -159,11 +171,6 @@ describe ActiveTriples::ParentStrategy do
159
171
  expect { subject.parent = immutable }
160
172
  .to raise_error described_class::UnmutableParentError
161
173
  end
162
-
163
- context 'with a parent' do
164
- include_context 'with a parent'
165
- it { is_expected.to have_attributes(:parent => parent) }
166
- end
167
174
  end
168
175
 
169
176
  describe '#persist!' do
@@ -205,7 +212,7 @@ describe ActiveTriples::ParentStrategy do
205
212
  parent.persistence_strategy.parent = last
206
213
  rdf_source.reload
207
214
  end
208
-
215
+
209
216
  it 'writes to #parent graph when parent changes while child is live' do
210
217
  parent.insert(parent_st)
211
218
  parent.persist!
@@ -248,16 +255,16 @@ describe ActiveTriples::ParentStrategy::Ancestors do
248
255
  context 'with parents' do
249
256
  let(:parent) { BasicPersistable.new }
250
257
  let(:last) { BasicPersistable.new }
251
-
258
+
252
259
  before do
253
260
  parent.set_persistence_strategy(ActiveTriples::ParentStrategy)
254
261
  parent.persistence_strategy.parent = last
255
262
  rdf_source.set_persistence_strategy(ActiveTriples::ParentStrategy)
256
263
  rdf_source.persistence_strategy.parent = parent
257
264
  end
258
-
265
+
259
266
  it { expect(subject.each).to be_a Enumerator }
260
-
267
+
261
268
  it 'enumerates ancestors' do
262
269
  expect(subject.each).to contain_exactly(parent, last)
263
270
  end
@@ -17,6 +17,16 @@ describe ActiveTriples::Property do
17
17
  expect(subject.class_name).to eq "Test"
18
18
  end
19
19
 
20
+ it 'should hold a block' do
21
+ fake = Object.new
22
+ property = described_class.new(options) do
23
+ fake.configure
24
+ end
25
+
26
+ expect(fake).to receive(:configure)
27
+ property.config.call
28
+ end
29
+
20
30
  describe "#to_h" do
21
31
  it "should not return the property's name" do
22
32
  expect(subject.to_h).to eq (
@@ -18,8 +18,9 @@ describe ActiveTriples::RDFSource do
18
18
  end
19
19
 
20
20
  before { @enumerable = subject }
21
+
21
22
  let(:source_class) { Class.new { include ActiveTriples::RDFSource } }
22
- let(:uri) { RDF::URI('http://example.org/moomin') }
23
+ let(:uri) { RDF::URI('http://example.org/moomin') }
23
24
 
24
25
  subject { source_class.new }
25
26
 
@@ -107,6 +108,45 @@ describe ActiveTriples::RDFSource do
107
108
  end
108
109
  end
109
110
 
111
+ describe 'observers' do
112
+ let(:observer) { double('observer') }
113
+
114
+ before { subject.add_observer(observer) }
115
+
116
+ include_context 'with properties'
117
+
118
+ it 'notifies an observer of changes' do
119
+ expect(observer)
120
+ .to receive(:notify)
121
+ .with(:creator, a_collection_containing_exactly('moomin'))
122
+
123
+ subject.creator = 'moomin'
124
+ end
125
+
126
+ it 'notifies muliple observers of changes' do
127
+ other_observer = double('second observer')
128
+ values = ['moomin', 'snork']
129
+
130
+ expect(observer)
131
+ .to receive(:notify)
132
+ .with(:creator, a_collection_containing_exactly(*values))
133
+ expect(other_observer)
134
+ .to receive(:notify)
135
+ .with(:creator, a_collection_containing_exactly(*values))
136
+
137
+ subject.add_observer(other_observer)
138
+ subject.creator = values
139
+ end
140
+
141
+ it 'does not notify removed observers' do
142
+ expect(observer).not_to receive(:notify)
143
+
144
+ subject.delete_observer(observer)
145
+
146
+ subject.creator = 'moomin'
147
+ end
148
+ end
149
+
110
150
  describe '#==' do
111
151
  shared_examples 'Term equality' do
112
152
  it 'equals itself' do
@@ -172,9 +212,9 @@ describe ActiveTriples::RDFSource do
172
212
 
173
213
  context 'with statements for other subjects' do
174
214
  before do
175
- subject <<
215
+ subject <<
176
216
  RDF::Statement(RDF::URI('http://example.org/OTHER_SUBJECT'),
177
- RDF::URI('http://example.org/ontology/OTHER_PRED'),
217
+ RDF::URI('http://example.org/ontology/OTHER_PRED'),
178
218
  'OTHER_OBJECT')
179
219
  end
180
220
 
@@ -191,6 +231,16 @@ describe ActiveTriples::RDFSource do
191
231
  end
192
232
  end
193
233
 
234
+ describe '#default_labels' do
235
+ it 'prefers skos:prefLabel' do
236
+ expect(subject.default_labels.first).to eq RDF::Vocab::SKOS.prefLabel
237
+ end
238
+
239
+ it 'values are all valid predicates' do
240
+ subject.default_labels.each { |term| expect(term).to be_uri }
241
+ end
242
+ end
243
+
194
244
  describe '#fetch' do
195
245
  it 'raises an error when it is a node' do
196
246
  expect { subject.fetch }
@@ -271,6 +321,18 @@ describe ActiveTriples::RDFSource do
271
321
  end
272
322
  end
273
323
 
324
+ describe '#inspect' do
325
+ it 'includes bnode id' do
326
+ expect(subject.inspect).to include subject.to_base
327
+ end
328
+
329
+ it 'includes uri' do
330
+ subject.set_subject!('http://example.org/moomin')
331
+
332
+ expect(subject.inspect).to include subject.to_base
333
+ end
334
+ end
335
+
274
336
  describe '#rdf_subject' do
275
337
  its(:rdf_subject) { is_expected.to be_a_node }
276
338
 
@@ -373,6 +435,7 @@ describe ActiveTriples::RDFSource do
373
435
 
374
436
  shared_examples 'setting values' do
375
437
  include_context 'with properties'
438
+
376
439
  after do
377
440
  Object.send(:remove_const, 'SourceWithCreator') if
378
441
  defined? SourceWithCreator
@@ -473,6 +536,39 @@ describe ActiveTriples::RDFSource do
473
536
  end
474
537
  end
475
538
 
539
+ describe 'on child nodes' do
540
+ let(:parent) { source_class.new }
541
+ let(:subject) { source_class.new(uri, parent) }
542
+
543
+ include_examples 'setting values' do
544
+ let(:value) do
545
+ ['moomin',
546
+ Date.today,
547
+ RDF::Node.new,
548
+ source_class.new,
549
+ source_class.new(uri / 'new'),
550
+ subject]
551
+ end
552
+ end
553
+
554
+ it 'does not change parent' do
555
+ property = RDF::Vocab::DC.title
556
+
557
+ expect { subject.set_value(property, 'Comet in Moominland') }
558
+ .not_to change { parent.to_a }
559
+ end
560
+
561
+ it 'persists to parent' do
562
+ property = RDF::Vocab::DC.title
563
+
564
+ subject.set_value(property, 'Comet in Moominland')
565
+
566
+ expect { subject.persist! }
567
+ .to change { parent.to_a }
568
+ .to include RDF::Statement(subject, property, 'Comet in Moominland')
569
+ end
570
+ end
571
+
476
572
  context 'with reciprocal relations' do
477
573
  let(:document) { source_class.new }
478
574
  let(:person) { source_class.new }
@@ -550,15 +646,15 @@ describe ActiveTriples::RDFSource do
550
646
  expect { subject.set_value(predicate, child_other) }
551
647
  .not_to change { child_other.persistence_strategy.parent }
552
648
  end
553
-
649
+
554
650
  context 'when setting to a relation' do
555
651
  it 'adds child node data to graph' do
556
652
  other << RDF::Statement(other, RDF::URI('p'), 'o')
557
-
558
- relation_source = source_class.new
653
+
654
+ relation_source = source_class.new
559
655
  relation_source.set_value(predicate, other)
560
656
  relation = relation_source.get_values(predicate)
561
-
657
+
562
658
  expect { subject.set_value(predicate, relation) }
563
659
  .to change { subject.statements.to_a }
564
660
  .to include(*other.statements.to_a)
@@ -673,119 +769,4 @@ describe ActiveTriples::RDFSource do
673
769
  expect { dummy_source.new.test_title }.not_to raise_error
674
770
  end
675
771
  end
676
-
677
- describe 'sources with properties with class_name defined' do
678
- before(:context) do
679
- class DummyChapter < ActiveTriples::Resource
680
- ontology = RDF::URI('http://www.example.com/ontology')
681
- type = RDF::URI('http://www.example.com/type')
682
-
683
- configure repository: :default, type: type / 'Chapter'
684
-
685
- property :title, predicate: ontology / 'title'
686
- property :subtitle, predicate: ontology / 'subtitle'
687
- end
688
-
689
- class DummyBook < ActiveTriples::Resource
690
- ontology = RDF::URI('http://www.example.com/ontology')
691
- type = RDF::URI('http://www.example.com/type')
692
-
693
- configure repository: :default, type: type / 'Book'
694
-
695
- property :title, predicate: ontology / 'title'
696
- property :has_chapter, predicate: ontology / 'hasChapter',
697
- class_name: DummyChapter
698
- end
699
- end
700
-
701
- context 'when loading models from graph' do
702
- before(:context) do
703
- r = RDF::Repository.new
704
- ActiveTriples::Repositories.repositories[:default] = r
705
-
706
- @book_url = 'http://www.example.com/BOOK_URI'
707
- @book_title = 'Example Book.'
708
- @chapter_title = 'Chapter 1'
709
- ttl = "<#{@book_url}> a <http://www.example.com/type/Book>;
710
- <http://www.example.com/ontology/hasChapter> [
711
- a <http://www.example.com/type/Chapter>;
712
- <http://www.example.com/ontology/title> \"#{@chapter_title}\"
713
- ];
714
- <http://www.example.com/ontology/title> \"#{@book_title}\" ."
715
- book_graph = ::RDF::Graph.new.from_ttl ttl
716
- r = ActiveTriples::Repositories.repositories[:default]
717
- r << book_graph
718
-
719
- @book = DummyBook.new(RDF::URI.new(@book_url))
720
- end
721
-
722
- it 'populates DummyBook properly' do
723
- expect(@book.rdf_subject.to_s).to eq @book_url
724
- expect(@book).to be_a DummyBook
725
- expect(@book.type)
726
- .to include(RDF::URI.new('http://www.example.com/type/Book'))
727
- expect(@book.title.first).to eq @book_title
728
- end
729
-
730
- it 'populates DummyChapter properly' do
731
- chapter = @book.has_chapter.first
732
- expect(chapter).to be_a DummyChapter
733
- expect(chapter.title.first).to eq @chapter_title
734
- expect(chapter.type)
735
- .to include(RDF::URI.new('http://www.example.com/type/Chapter'))
736
- end
737
- end
738
-
739
- context 'when loading models through properties' do
740
- before(:context) do
741
- r = RDF::Repository.new
742
- ActiveTriples::Repositories.repositories[:default] = r
743
-
744
- bk1 = DummyBook.new('http://www.example.com/book1')
745
- bk1.title = 'Learning about Explicit Links in ActiveTriples'
746
-
747
- ch1 = DummyChapter.new('http://www.example.com/book1/chapter1')
748
- ch1.title = 'Defining a source with an Explicit Link'
749
- bk1.has_chapter = ch1
750
- ch1.persist!
751
- bk1.persist!
752
-
753
- @bk1 = DummyBook.new('http://www.example.com/book1')
754
- @ch1 = DummyChapter.new('http://www.example.com/book1/chapter1')
755
- end
756
-
757
- it 'populates DummyBook (resumed resource) properly' do
758
- expect(@bk1.type.first)
759
- .to eq RDF::URI('http://www.example.com/type/Book')
760
- expect(@bk1.title.first)
761
- .to eq 'Learning about Explicit Links in ActiveTriples'
762
- end
763
-
764
- it 'populates DummyChapter (property resource) properly' do
765
- ch1 = @bk1.has_chapter.first
766
- expect(ch1.type.first)
767
- .to eq RDF::URI('http://www.example.com/type/Chapter')
768
- expect(ch1.title.first)
769
- .to eq 'Defining a source with an Explicit Link'
770
- end
771
-
772
- it 'populates DummyChapter (directly from repository) properly' do
773
- expect(@ch1.type.first)
774
- .to eq RDF::URI('http://www.example.com/type/Chapter')
775
- expect(@ch1.title.first)
776
- .to eq 'Defining a source with an Explicit Link'
777
- end
778
-
779
- it 'does not reload from repository twice' do
780
- ch1 = @bk1.has_chapter.first
781
- expect(ch1.title.first).to eq 'Defining a source with an Explicit Link'
782
-
783
- @ch1.subtitle = 'Changed after original load'
784
- @ch1.persist!
785
- expect(@ch1.subtitle).to eq ['Changed after original load']
786
-
787
- expect(ch1.subtitle).to eq []
788
- end
789
- end
790
- end
791
772
  end