tripod 0.0.8 → 0.0.9

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