tripod 0.10.3 → 0.10.6

Sign up to get free protection for your applications and to get access to all the features.
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