tripod 0.10.3 → 0.10.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d15c9a2a73060d3bb197938d1b54e7ac5cd389c
4
- data.tar.gz: 8ef936705121bbe021c213b0ad1e21612e977adc
3
+ metadata.gz: de26dbd697bf235132169fcd79cd217f12703968
4
+ data.tar.gz: 51f05ee55133a0efdb7fc818721e6fab2992b994
5
5
  SHA512:
6
- metadata.gz: 5d0298f5a4e5c2c9edfece03b5a902898eadbde2f5301d7bcafd2fa2c018d706cbc591dbde42da4705630d999f18ac1d3537438ab4ff41ba8299211024b3d259
7
- data.tar.gz: 988bbe224cc037aba6e6c70c676a59b59a82fdae8b225f2c7467f9e4461845638fea8bd074a6f0f5987df9a4f248eb785c56312dd9b5526d73932f13032412d4
6
+ metadata.gz: dc24de2078906bcbef21306de4803fff5792b6be1f124a8ce543b8269edddc0b85623f51634211b92a0d8fddc52b2f2fe71c9e42af73076c880eac18fc6522a0
7
+ data.tar.gz: 568716881b92d6d8b0c31380a45235afaebc04694b130c6f7340a55f592601a8de90c5493746d8e51d67c46ebdd005d7858316f3c6a864e15df3af332f02a098
data/lib/tripod.rb CHANGED
@@ -93,6 +93,7 @@ require "tripod/predicates"
93
93
  require "tripod/attributes"
94
94
  require "tripod/callbacks"
95
95
  require "tripod/validations/is_url"
96
+ require "tripod/rdf_type"
96
97
  require "tripod/errors"
97
98
  require "tripod/repository"
98
99
  require "tripod/fields"
@@ -104,6 +105,9 @@ require "tripod/eager_loading"
104
105
  require "tripod/serialization"
105
106
  require "tripod/state"
106
107
  require "tripod/graphs"
108
+ require "tripod/embeds"
109
+ require "tripod/embeds/many"
110
+ require "tripod/embedded_resource"
107
111
  require "tripod/version"
108
112
 
109
113
  # these need to be at the end
@@ -17,9 +17,11 @@ module Tripod::Components
17
17
  include Tripod::Attributes
18
18
  include Tripod::Callbacks
19
19
  include Tripod::Validations
20
+ include Tripod::RdfType
20
21
  include Tripod::Persistence
21
22
  include Tripod::Fields
22
23
  include Tripod::Links
24
+ include Tripod::Embeds
23
25
  include Tripod::Finders
24
26
  include Tripod::Repository
25
27
  include Tripod::EagerLoading
@@ -0,0 +1,27 @@
1
+ module Tripod::EmbeddedResource
2
+ extend ActiveSupport::Concern
3
+
4
+ include ActiveModel::Validations
5
+
6
+ include Tripod::Predicates
7
+ include Tripod::Attributes
8
+ include Tripod::Validations
9
+ include Tripod::Fields
10
+ include Tripod::RdfType
11
+
12
+ attr_reader :uri
13
+
14
+ def initialize(opts={})
15
+ @uri = opts.fetch(:node, RDF::Node.new) # use a blank node for the URI
16
+ @repository = opts.fetch(:repository, RDF::Repository.new)
17
+ set_rdf_type
18
+ end
19
+
20
+ def to_statements
21
+ @repository.statements
22
+ end
23
+
24
+ def ==(resource)
25
+ (@uri == resource.uri)
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+ module Tripod::Embeds
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ validate :embedded_are_valid
6
+ end
7
+
8
+ def get_embeds(name, predicate, opts)
9
+ klass = opts.fetch(:class, nil)
10
+ klass ||= (self.class.name.deconstantize + '::' + name.to_s.classify).constantize
11
+ Many.new(klass, predicate, self)
12
+ end
13
+
14
+ def embedded_are_valid
15
+ self.class.get_embedded.each do |name|
16
+ self.errors.add(name, 'contains an invalid resource') unless self.send(name).all? {|resource| resource.valid? }
17
+ end
18
+ end
19
+
20
+ module ClassMethods
21
+ def embeds(name, predicate, opts={})
22
+ re_define_method name do
23
+ get_embeds(name, predicate, opts)
24
+ end
25
+
26
+ # use this as a way to get to all the embedded properties for validation
27
+ @_EMBEDDED ||= []
28
+ @_EMBEDDED << name
29
+ end
30
+
31
+ def get_embedded
32
+ @_EMBEDDED || []
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ module Tripod::Embeds
2
+ class Many
3
+ include Enumerable
4
+
5
+ def initialize(klass, predicate, parent)
6
+ @parent = parent
7
+ @predicate = predicate
8
+ nodes = @parent.read_predicate(@predicate) # gets the UUIDs of the associated blank nodes
9
+ @resources = nodes.map do |node|
10
+ repository = RDF::Repository.new
11
+ @parent.repository.query([node, :predicate, :object]) {|statement| repository << statement}
12
+ klass.new(node: node, repository: repository)
13
+ end
14
+ end
15
+
16
+ def each(&block)
17
+ @resources.each(&block)
18
+ end
19
+
20
+ def <<(resource)
21
+ @parent.repository.insert(*resource.to_statements)
22
+ @parent.append_to_predicate(@predicate, resource.uri)
23
+ end
24
+
25
+ def delete(resource)
26
+ statements = @parent.repository.query([resource.uri, :predicate, :object]).to_a
27
+ statements << [@parent.uri, RDF::URI.new(@predicate), resource.uri]
28
+ @parent.repository.delete(*statements)
29
+ end
30
+ end
31
+ end
@@ -109,7 +109,7 @@ module Tripod::Finders
109
109
  uris_sparql_str = uris.map{ |u| "<#{u.to_s}>" }.join(" ")
110
110
 
111
111
  # Do a big describe statement, and read the results into an in-memory repo
112
- ntriples_string = Tripod::SparqlClient::Query.query("CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o . VALUES ?s { #{uris_sparql_str} } }", "application/n-triples")
112
+ ntriples_string = Tripod::SparqlClient::Query.query("CONSTRUCT { ?s ?p ?o } WHERE { VALUES ?s { #{uris_sparql_str} } ?s ?p ?o . }", "application/n-triples")
113
113
  graph = _rdf_graph_from_ntriples_string(ntriples_string, graph)
114
114
  end
115
115
 
@@ -172,16 +172,20 @@ module Tripod::Finders
172
172
  def _describe_query_for_select(select_sparql, opts={})
173
173
  uri_variable = opts[:uri_variable] || "uri"
174
174
  "
175
- CONSTRUCT { ?tripod_construct_s ?tripod_construct_p ?tripod_construct_o }
176
- WHERE {
177
- ?tripod_construct_s ?tripod_construct_p ?tripod_construct_o .
175
+ CONSTRUCT {
176
+ ?tripod_construct_s ?tripod_construct_p ?tripod_construct_o .
177
+ # ?tripod_construct_o ?tripod_construct_ep ?tripod_construct_eo .
178
+ }
179
+ WHERE {
180
+ {
181
+ SELECT (?#{uri_variable} as ?tripod_construct_s)
178
182
  {
179
- SELECT (?#{uri_variable} as ?tripod_construct_s)
180
- {
181
- #{select_sparql}
182
- }
183
+ #{select_sparql}
183
184
  }
184
- }
185
+ }
186
+ ?tripod_construct_s ?tripod_construct_p ?tripod_construct_o .
187
+ # OPTIONAL { ?tripod_construct_o ?tripod_construct_ep ?tripod_construct_eo . }
188
+ }
185
189
  "
186
190
  end
187
191
 
@@ -216,6 +220,10 @@ module Tripod::Finders
216
220
  data_graph = RDF::Graph.new
217
221
  repo.query( [RDF::URI.new(u), :predicate, :object] ) do |statement|
218
222
  data_graph << statement
223
+
224
+ if statement.object.is_a? RDF::Node
225
+ repo.query( [statement.object, :predicate, :object] ) {|s| data_graph << s}
226
+ end
219
227
  end
220
228
 
221
229
  # use it to hydrate this resource
@@ -0,0 +1,25 @@
1
+ module Tripod::RdfType
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ # every instance of a resource has an rdf type field, which is set at the class level
6
+ class_attribute :_RDF_TYPE
7
+ end
8
+
9
+ def set_rdf_type
10
+ self.rdf_type = self.class.get_rdf_type if respond_to?(:rdf_type=) && self.class.get_rdf_type
11
+ end
12
+
13
+ module ClassMethods
14
+ # makes a "field" on this model called rdf_type
15
+ # and sets a class level _RDF_TYPE variable with the rdf_type passed in.
16
+ def rdf_type(new_rdf_type)
17
+ self._RDF_TYPE = RDF::URI.new(new_rdf_type.to_s)
18
+ field :rdf_type, RDF.type, :multivalued => true, :is_uri => true # things can have more than 1 type and often do
19
+ end
20
+
21
+ def get_rdf_type
22
+ self._RDF_TYPE
23
+ end
24
+ end
25
+ end
@@ -56,11 +56,7 @@ module Tripod::Repository
56
56
  end
57
57
 
58
58
  def retrieve_triples_from_database(accept_header="application/n-triples")
59
- graph_selector = self.graph_uri.present? ? "<#{graph_uri.to_s}>" : "?g"
60
- Tripod::SparqlClient::Query.query(
61
- "CONSTRUCT {<#{uri}> ?p ?o} WHERE { GRAPH #{graph_selector} { <#{uri}> ?p ?o } }",
62
- accept_header
63
- )
59
+ Tripod::SparqlClient::Query.query(self.class.all_triples_query(uri, graph_uri: self.graph_uri), accept_header)
64
60
  end
65
61
 
66
62
  # returns a graph of triples from the underlying repository where this resource's uri is the subject.
@@ -87,6 +83,12 @@ module Tripod::Repository
87
83
  repo
88
84
  end
89
85
 
86
+ def all_triples_query(uri, opts={})
87
+ graph_uri = opts.fetch(:graph_uri, nil)
88
+ graph_selector = graph_uri.present? ? "<#{graph_uri.to_s}>" : "?g"
89
+ "CONSTRUCT {<#{uri}> ?p ?o . ?o ?ep ?eo . } WHERE { GRAPH #{graph_selector} { <#{uri}> ?p ?o . OPTIONAL { ?o ?ep ?eo } } }"
90
+ end
91
+
90
92
  end
91
93
 
92
- end
94
+ end
@@ -13,8 +13,6 @@ module Tripod::Resource
13
13
  validates_presence_of :graph_uri
14
14
  # uri is a valid linked data url
15
15
  validates :uri, is_url: true
16
- # every instance of a resource has an rdf type field, which is set at the class level
17
- class_attribute :_RDF_TYPE
18
16
  # the Graph URI is set at the class level by default also, although this can be overridden in the constructor
19
17
  class_attribute :_GRAPH_URI
20
18
  end
@@ -52,7 +50,7 @@ module Tripod::Resource
52
50
  run_callbacks :initialize do
53
51
  graph_uri ||= self.class.get_graph_uri unless ignore_graph
54
52
  @graph_uri = RDF::URI(graph_uri) if graph_uri
55
- self.rdf_type = self.class.get_rdf_type if respond_to?(:rdf_type=) && self.class.get_rdf_type
53
+ set_rdf_type
56
54
  end
57
55
  end
58
56
 
@@ -107,17 +105,6 @@ module Tripod::Resource
107
105
  other.class == Class ? self <= other : other.is_a?(self)
108
106
  end
109
107
 
110
- # makes a "field" on this model called rdf_type
111
- # and sets a class level _RDF_TYPE variable with the rdf_type passed in.
112
- def rdf_type(new_rdf_type)
113
- self._RDF_TYPE = RDF::URI.new(new_rdf_type.to_s)
114
- field :rdf_type, RDF.type, :multivalued => true, :is_uri => true # things can have more than 1 type and often do
115
- end
116
-
117
- def get_rdf_type
118
- self._RDF_TYPE
119
- end
120
-
121
108
  def graph_uri(new_graph_uri)
122
109
  self._GRAPH_URI = new_graph_uri
123
110
  end
@@ -130,4 +117,4 @@ module Tripod::Resource
130
117
  end
131
118
 
132
119
  # causes any hooks to be fired, if they've been setup on_load of :tripod.
133
- ActiveSupport.run_load_hooks(:triploid, Tripod::Resource)
120
+ ActiveSupport.run_load_hooks(:triploid, Tripod::Resource)
@@ -1,3 +1,3 @@
1
1
  module Tripod
2
- VERSION = "0.10.3"
2
+ VERSION = "0.10.6"
3
3
  end
@@ -14,4 +14,6 @@ class Dog
14
14
 
15
15
  linked_to :arch_enemy, 'http://example.com/archenemy', class_name: 'Dog'
16
16
  linked_to :enemies, 'http://example.com/enemy', class_name: 'Dog'
17
- end
17
+
18
+ embeds :fleas, 'http://example.com/fleas'
19
+ end
@@ -0,0 +1,8 @@
1
+ class Flea
2
+ include Tripod::EmbeddedResource
3
+
4
+ rdf_type 'http://example.com/flea'
5
+
6
+ field :name, 'http://example.com/flea/name'
7
+ validates_presence_of :name
8
+ end
data/spec/spec_helper.rb CHANGED
@@ -31,7 +31,7 @@ Tripod.configure do |config|
31
31
  # config.update_endpoint = 'http://127.0.0.1:3030/tripod-test/update'
32
32
  # config.query_endpoint = 'http://127.0.0.1:3030/tripod-test/sparql'
33
33
  # config.data_endpoint = 'http://127.0.0.1:3030/tripod-test/data'
34
-
34
+
35
35
  config.update_endpoint = 'http://127.0.0.1:3002/sparql/raw/update'
36
36
  config.query_endpoint = 'http://127.0.0.1:3002/sparql/raw'
37
37
  #config.data_endpoint = 'http://127.0.0.1:3030/tripod-test/data'
@@ -41,4 +41,4 @@ end
41
41
  Dir[ File.join(MODELS, "*.rb") ].sort.each do |file|
42
42
  name = File.basename(file, ".rb")
43
43
  autoload name.camelize.to_sym, name
44
- end
44
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ module Tripod
4
+ describe EmbeddedResource do
5
+ describe 'an instance' do
6
+ let(:flea) { Flea.new }
7
+
8
+ it 'should have getters & setters on fields' do
9
+ flea.name = 'Bob'
10
+ expect(flea.name).to eq('Bob')
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tripod::Embeds do
4
+ let(:uri) { 'http://example.com/id/spot' }
5
+ let(:dog) {
6
+ d = Dog.new(uri)
7
+ d.name = "Spot"
8
+ d
9
+ }
10
+ let(:flea) {
11
+ f = Flea.new
12
+ f.name = 'Starsky'
13
+ f
14
+ }
15
+
16
+ it 'should set and get embedded resources through the proxy' do
17
+ dog.fleas << flea
18
+ expect(dog.fleas.include?(flea)).to eq(true)
19
+ end
20
+
21
+ it 'should validate embedded resources' do
22
+ dog.fleas << Flea.new
23
+ expect(dog.valid?).to eq(false)
24
+ end
25
+
26
+ context 'given a saved instance' do
27
+ before do
28
+ dog.fleas << flea
29
+ dog.save
30
+ end
31
+
32
+ context 'retrieved by uri' do
33
+ let(:dogg) { Dog.find(uri) }
34
+
35
+ it 'should hydrate embedded resources from the triple store' do
36
+ f = dogg.fleas.first
37
+ expect(f.name).to eq(flea.name)
38
+ end
39
+ end
40
+
41
+ context 'retrieved as part of a resource collection' do
42
+ let(:dogg) { Dog.all.resources.first }
43
+
44
+ # RR: this is commented out as I backed out the (slow) update to the hydration CONSTRUCT
45
+ it 'should hydrate embedded resources from the triple store' #do
46
+ # f = dogg.fleas.first
47
+ # expect(f.name).to eq(flea.name)
48
+ # end
49
+ end
50
+ end
51
+
52
+
53
+ describe 'delete' do
54
+ before do
55
+ dog.fleas << flea
56
+ end
57
+
58
+ it 'should remove all trace of the resource' do
59
+ dog.fleas.delete(flea)
60
+ expect(dog.fleas.include?(flea)).to eq(false)
61
+ end
62
+ end
63
+ end
@@ -30,9 +30,7 @@ describe Tripod::Repository do
30
30
 
31
31
  context 'graph_uri set on object' do
32
32
  it 'populates the object with triples, restricted to the graph_uri' do
33
- Tripod::SparqlClient::Query.should_receive(:query).with(
34
- "CONSTRUCT {<#{person.uri}> ?p ?o} WHERE { GRAPH <#{person.graph_uri}> { <#{person.uri}> ?p ?o } }",
35
- "application/n-triples").and_call_original
33
+ Tripod::SparqlClient::Query.should_receive(:query).with(Person.all_triples_query(person.uri, graph_uri: person.graph_uri), 'application/n-triples').and_call_original
36
34
  person.hydrate!
37
35
  person.repository.should_not be_empty
38
36
  end
@@ -40,9 +38,7 @@ describe Tripod::Repository do
40
38
 
41
39
  context 'graph_uri not set on object' do
42
40
  it 'populates the object with triples, not to a graph' do
43
- Tripod::SparqlClient::Query.should_receive(:query).with(
44
- "CONSTRUCT {<#{graphless_resource.uri}> ?p ?o} WHERE { GRAPH ?g { <#{graphless_resource.uri}> ?p ?o } }",
45
- "application/n-triples").and_call_original
41
+ Tripod::SparqlClient::Query.should_receive(:query).with(Person.all_triples_query(person.uri), 'application/n-triples').and_call_original
46
42
  graphless_resource.hydrate!
47
43
  graphless_resource.repository.should_not be_empty
48
44
  end
@@ -73,4 +69,4 @@ describe Tripod::Repository do
73
69
  end
74
70
 
75
71
 
76
- end
72
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tripod
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.3
4
+ version: 0.10.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ric Roberts
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-01-08 00:00:00.000000000 Z
13
+ date: 2015-01-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rest-client
@@ -214,6 +214,9 @@ files:
214
214
  - lib/tripod/criteria.rb
215
215
  - lib/tripod/criteria/execution.rb
216
216
  - lib/tripod/eager_loading.rb
217
+ - lib/tripod/embedded_resource.rb
218
+ - lib/tripod/embeds.rb
219
+ - lib/tripod/embeds/many.rb
217
220
  - lib/tripod/errors.rb
218
221
  - lib/tripod/errors/bad_data_request.rb
219
222
  - lib/tripod/errors/bad_sparql_request.rb
@@ -239,6 +242,7 @@ files:
239
242
  - lib/tripod/locale/en.yml
240
243
  - lib/tripod/persistence.rb
241
244
  - lib/tripod/predicates.rb
245
+ - lib/tripod/rdf_type.rb
242
246
  - lib/tripod/repository.rb
243
247
  - lib/tripod/resource.rb
244
248
  - lib/tripod/resource_collection.rb
@@ -250,6 +254,7 @@ files:
250
254
  - lib/tripod/validations/is_url.rb
251
255
  - lib/tripod/version.rb
252
256
  - spec/app/models/dog.rb
257
+ - spec/app/models/flea.rb
253
258
  - spec/app/models/person.rb
254
259
  - spec/app/models/resource.rb
255
260
  - spec/spec_helper.rb
@@ -257,6 +262,8 @@ files:
257
262
  - spec/tripod/criteria_execution_spec.rb
258
263
  - spec/tripod/criteria_spec.rb
259
264
  - spec/tripod/eager_loading_spec.rb
265
+ - spec/tripod/embedded_resource_spec.rb
266
+ - spec/tripod/embeds_spec.rb
260
267
  - spec/tripod/fields_spec.rb
261
268
  - spec/tripod/finders_spec.rb
262
269
  - spec/tripod/graphs_spec.rb
@@ -297,6 +304,7 @@ specification_version: 4
297
304
  summary: Active Model style RDF ORM
298
305
  test_files:
299
306
  - spec/app/models/dog.rb
307
+ - spec/app/models/flea.rb
300
308
  - spec/app/models/person.rb
301
309
  - spec/app/models/resource.rb
302
310
  - spec/spec_helper.rb
@@ -304,6 +312,8 @@ test_files:
304
312
  - spec/tripod/criteria_execution_spec.rb
305
313
  - spec/tripod/criteria_spec.rb
306
314
  - spec/tripod/eager_loading_spec.rb
315
+ - spec/tripod/embedded_resource_spec.rb
316
+ - spec/tripod/embeds_spec.rb
307
317
  - spec/tripod/fields_spec.rb
308
318
  - spec/tripod/finders_spec.rb
309
319
  - spec/tripod/graphs_spec.rb