tripod 0.0.8 → 0.0.9

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.
@@ -27,6 +27,7 @@ require "active_support/core_ext"
27
27
  require 'active_support/json'
28
28
  require "active_support/inflector"
29
29
  require "active_model"
30
+ require "guid"
30
31
 
31
32
  require 'rdf'
32
33
  require 'rdf/rdfxml'
@@ -3,6 +3,61 @@
3
3
  # This module defines behaviour for persisting to the database.
4
4
  module Tripod::Persistence
5
5
  extend ActiveSupport::Concern
6
+
7
+ class Tripod::Persistence::Transaction
8
+
9
+ def initialize
10
+ self.transaction_id = Guid.new.to_s
11
+ end
12
+
13
+ attr_accessor :transaction_id
14
+ attr_accessor :query
15
+
16
+ def commit
17
+ Tripod::SparqlClient::Update::update(self.query)
18
+ clear_transaction
19
+ end
20
+
21
+ def abort
22
+ clear_transaction
23
+ end
24
+
25
+ def clear_transaction
26
+ self.transaction_id = nil
27
+ self.query = ""
28
+ Tripod::Persistence.transactions.delete(self.transaction_id)
29
+ end
30
+
31
+ def self.valid_transaction(transaction)
32
+ transaction && transaction.class == Tripod::Persistence::Transaction
33
+ end
34
+
35
+ def self.get_transcation(trans)
36
+ transaction = nil
37
+
38
+ if Tripod::Persistence::Transaction.valid_transaction(trans)
39
+
40
+ transaction_id = trans.transaction_id
41
+
42
+ Tripod::Persistence.transactions ||= {}
43
+
44
+ if Tripod::Persistence.transactions[transaction_id]
45
+ # existing transaction
46
+ transaction = Tripod::Persistence.transactions[transaction_id]
47
+ else
48
+ # new transaction
49
+ transaction = Tripod::Persistence.transactions[transaction_id] = trans
50
+ end
51
+ end
52
+
53
+ transaction
54
+ end
55
+
56
+ end
57
+
58
+ # hash of transactions against their ids.
59
+ mattr_accessor :transactions
60
+
6
61
  # Save the resource.
7
62
  # Note: regardless of whether it's a new_record or not, we always make the
8
63
  # db match the contents of this resource's statements.
@@ -11,19 +66,30 @@ module Tripod::Persistence
11
66
  # resource.save
12
67
  #
13
68
  # @return [ true, false ] True is success, false if not.
14
- def save()
69
+ def save(opts={})
70
+
71
+ transaction = Tripod::Persistence::Transaction.get_transcation(opts[:transaction])
72
+
15
73
  if self.valid?
74
+
16
75
  query = "
17
76
  DELETE {GRAPH ?g {<#{@uri.to_s}> ?p ?o}} WHERE {GRAPH ?g {<#{@uri.to_s}> ?p ?o}};
18
77
  INSERT DATA {
19
78
  GRAPH <#{@graph_uri}> {
20
79
  #{ @repository.dump(:ntriples) }
21
80
  }
22
- }
81
+ };
23
82
  "
24
- success = Tripod::SparqlClient::Update::update(query)
25
- @new_record = false if success
26
- success
83
+
84
+ if transaction
85
+ transaction.query ||= ""
86
+ transaction.query += query
87
+ else
88
+ Tripod::SparqlClient::Update::update(query)
89
+ end
90
+
91
+ @new_record = false # if running in a trans, just assume it worked. If the query is dodgy, it will throw an exception later.
92
+ true
27
93
  else
28
94
  false
29
95
  end
@@ -39,26 +105,43 @@ module Tripod::Persistence
39
105
  # @raise [Tripod::Errors::Validations] if invalid
40
106
  #
41
107
  # @return [ true ] True is success.
42
- def save!()
108
+ def save!(opts={})
43
109
  # try to save
44
- unless self.save()
110
+ unless self.save(opts)
111
+
45
112
  # if we get in here, save failed.
46
- self.class.fail_validate!(self)
113
+
114
+ # abort the transaction
115
+ transaction = Tripod::Persistence::Transaction.get_transcation(opts[:transaction])
116
+ transaction.abort() if transaction
117
+
118
+ self.class.fail_validate!(self) # throw an exception
119
+
47
120
  # TODO: similar stuff for callbacks?
48
121
  end
49
122
  return true
50
123
  end
51
124
 
52
- def destroy()
125
+ def destroy(opts={})
126
+
127
+ transaction = Tripod::Persistence::Transaction.get_transcation(opts[:transaction])
128
+
53
129
  query = "
54
130
  # delete from default graph:
55
131
  DELETE {<#{@uri.to_s}> ?p ?o} WHERE {<#{@uri.to_s}> ?p ?o};
56
132
  # delete from named graphs:
57
133
  DELETE {GRAPH ?g {<#{@uri.to_s}> ?p ?o}} WHERE {GRAPH ?g {<#{@uri.to_s}> ?p ?o}};
58
134
  "
59
- success = Tripod::SparqlClient::Update::update(query)
60
- @destroyed = true if success
61
- success
135
+
136
+ if transaction
137
+ transaction.query ||= ""
138
+ transaction.query += query
139
+ else
140
+ Tripod::SparqlClient::Update::update(query)
141
+ end
142
+
143
+ @destroyed = true
144
+ true
62
145
  end
63
146
 
64
147
  module ClassMethods #:nodoc:
@@ -1,3 +1,3 @@
1
1
  module Tripod
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -29,6 +29,7 @@ describe Tripod::Persistence do
29
29
  p
30
30
  end
31
31
 
32
+
32
33
  describe "#save" do
33
34
 
34
35
  context 'graph not set' do
@@ -100,4 +101,73 @@ describe Tripod::Persistence do
100
101
  lambda {unsaved_person.save!}.should raise_error(Tripod::Errors::Validations)
101
102
  end
102
103
  end
104
+
105
+ describe "transactions" do
106
+
107
+ it "only save on commit" do
108
+
109
+ transaction = Tripod::Persistence::Transaction.new
110
+
111
+ unsaved_person.save(transaction: transaction)
112
+ saved_person['http://pred2'] = 'blah'
113
+ saved_person.save(transaction: transaction)
114
+
115
+ # nothing should have changed yet.
116
+ lambda {Person.find(unsaved_person.uri)}.should raise_error(Tripod::Errors::ResourceNotFound)
117
+ Person.find(saved_person.uri)['http://pred2'].first.to_s.should == RDF::URI.new('http://obj2').to_s
118
+
119
+ transaction.commit
120
+
121
+ # things should have changed now.
122
+ lambda {Person.find(unsaved_person.uri)}.should_not raise_error()
123
+ Person.find(saved_person.uri)['http://pred2'].first.should == 'blah'
124
+
125
+ end
126
+
127
+ it "silently ignore invalid saves" do
128
+ transaction = Tripod::Persistence::Transaction.new
129
+
130
+ unsaved_person.uri = nil
131
+ unsaved_person.save(transaction: transaction).should be_false
132
+
133
+ saved_person['http://pred2'] = 'blah'
134
+ saved_person.save(transaction: transaction).should be_true
135
+
136
+ transaction.commit
137
+
138
+ # transaction should be gone
139
+ Tripod::Persistence.transactions[transaction.transaction_id].should be_nil
140
+
141
+ # unsaved person still not there
142
+ lambda {Person.find(unsaved_person.uri)}.should raise_error(Tripod::Errors::ResourceNotFound)
143
+
144
+ # saved person SHOULD be updated
145
+ Person.find(saved_person.uri)['http://pred2'].first.should == 'blah'
146
+ end
147
+
148
+ it "can be aborted" do
149
+ transaction = Tripod::Persistence::Transaction.new
150
+ unsaved_person.save(transaction: transaction)
151
+ transaction.abort()
152
+
153
+ # unsaved person still not there
154
+ lambda {Person.find(unsaved_person.uri)}.should raise_error(Tripod::Errors::ResourceNotFound)
155
+
156
+ #transaction gone.
157
+ transaction.query.should be_blank
158
+ Tripod::Persistence.transactions[transaction.transaction_id].should be_nil
159
+ end
160
+
161
+ it "should be removed once committed" do
162
+ transaction = Tripod::Persistence::Transaction.new
163
+ unsaved_person.save(transaction: transaction)
164
+ transaction.commit()
165
+
166
+ #transaction gone.
167
+ transaction.query.should be_blank
168
+ Tripod::Persistence.transactions[transaction.transaction_id].should be_nil
169
+ end
170
+
171
+ end
172
+
103
173
  end
@@ -25,4 +25,5 @@ Gem::Specification.new do |gem|
25
25
  gem.add_dependency "rdf-rdfxml"
26
26
  gem.add_dependency "rdf-n3"
27
27
  gem.add_dependency "rdf-json"
28
+ gem.add_dependency "guid"
28
29
  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.0.8
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-08 00:00:00.000000000 Z
12
+ date: 2012-10-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
16
- requirement: &70194090276740 !ruby/object:Gem::Requirement
16
+ requirement: &70271542059420 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70194090276740
24
+ version_requirements: *70271542059420
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activemodel
27
- requirement: &70194090276180 !ruby/object:Gem::Requirement
27
+ requirement: &70271542058760 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '3.1'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70194090276180
35
+ version_requirements: *70271542058760
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: equivalent-xml
38
- requirement: &70194090275760 !ruby/object:Gem::Requirement
38
+ requirement: &70271542058220 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70194090275760
46
+ version_requirements: *70271542058220
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rdf
49
- requirement: &70194090275180 !ruby/object:Gem::Requirement
49
+ requirement: &70271542057540 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0.3'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70194090275180
57
+ version_requirements: *70271542057540
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rdf-rdfxml
60
- requirement: &70194090274760 !ruby/object:Gem::Requirement
60
+ requirement: &70271542057020 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70194090274760
68
+ version_requirements: *70271542057020
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rdf-n3
71
- requirement: &70194090274160 !ruby/object:Gem::Requirement
71
+ requirement: &70271542056460 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70194090274160
79
+ version_requirements: *70271542056460
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rdf-json
82
- requirement: &70194090273720 !ruby/object:Gem::Requirement
82
+ requirement: &70271542055920 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,18 @@ dependencies:
87
87
  version: '0'
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *70194090273720
90
+ version_requirements: *70271542055920
91
+ - !ruby/object:Gem::Dependency
92
+ name: guid
93
+ requirement: &70271542055420 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: *70271542055420
91
102
  description: RDF ruby ORM
92
103
  email:
93
104
  - ric@swirrl.com