Skip to content

Commit fc47d59

Browse files
committed
Add wrap_transaction keyword parameter to RDF::List#initialize.
For #417.
1 parent 637f676 commit fc47d59

2 files changed

Lines changed: 71 additions & 4 deletions

File tree

lib/rdf/model/list.rb

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,23 @@ def self.[](*values)
4949
# g = RDF::Graph.new << l
5050
# g.count # => l.count
5151
#
52+
# @example use a transaction for block initialization
53+
# l = RDF::List(graph: graph, wrap_transaction: true) do |list|
54+
# list << RDF::Literal(1)
55+
# # list.graph.rollback will rollback all list changes within this block.
56+
# end
57+
# list.count #=> 1
58+
#
5259
# @param [RDF::Resource] subject (RDF.nil)
5360
# Subject should be an {RDF::Node}, not a {RDF::URI}. A list with an IRI head will not validate, but is commonly used to detect if a list is valid.
5461
# @param [RDF::Graph] graph (RDF::Graph.new)
5562
# @param [Array<RDF::Term>] values
5663
# Any values which are not terms are coerced to `RDF::Literal`.
64+
# @param [Boolean] wrap_transaction (false)
65+
# Wraps the callback in a transaction, and replaces the graph with that transaction for the duraction of the callback. This has the effect of allowing any list changes to be made atomically, or rolled back.
5766
# @yield [list]
5867
# @yieldparam [RDF::List] list
59-
def initialize(subject: nil, graph: nil, values: nil, &block)
68+
def initialize(subject: nil, graph: nil, values: nil, wrap_transaction: false, &block)
6069
@subject = subject || RDF.nil
6170
@graph = graph || RDF::Graph.new
6271
is_empty = @graph.query({subject: subject, predicate: RDF.first}).empty?
@@ -78,9 +87,25 @@ def initialize(subject: nil, graph: nil, values: nil, &block)
7887
end
7988

8089
if block_given?
81-
case block.arity
82-
when 1 then block.call(self)
83-
else instance_eval(&block)
90+
if wrap_transaction
91+
old_graph = @graph
92+
begin
93+
Transaction.begin(@graph, graph_name: @graph.graph_name, mutable: @graph.mutable?) do |trans|
94+
@graph = trans
95+
case block.arity
96+
when 1 then block.call(self)
97+
else instance_eval(&block)
98+
end
99+
trans.execute if trans.mutated?
100+
end
101+
ensure
102+
@graph = old_graph
103+
end
104+
else
105+
case block.arity
106+
when 1 then block.call(self)
107+
else instance_eval(&block)
108+
end
84109
end
85110
end
86111
end

spec/model_list_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,48 @@
148148
described_class.new(RDF::Node.new, graph)
149149
}.to raise_error ArgumentError
150150
end
151+
152+
it "adds values to graph" do
153+
n = RDF::Node.new
154+
l = RDF::List.new(subject: n, graph: graph, values: [RDF::Literal(1), RDF::Literal(2)])
155+
expect(l.to_a).to include(RDF::Literal(1), RDF::Literal(2))
156+
expect(graph.first_object(subject: n, predicate: RDF.first)).to eql(RDF::Literal(1))
157+
end
158+
159+
it "yields itself" do
160+
expect {|b| described_class.new(&b)}.to yield_with_args(RDF::List)
161+
end
162+
163+
context :with_transaction do
164+
it "uses a transaction for the graph" do
165+
n = RDF::Node.new
166+
l = RDF::List.new(subject: n, graph: graph, wrap_transaction: true) do |list|
167+
expect(list.graph).to be_a(RDF::Transaction)
168+
expect(list.graph).not_to equal graph
169+
end
170+
end
171+
172+
it "adds values in a transaction" do
173+
n = RDF::Node.new
174+
l = RDF::List.new(graph: graph, wrap_transaction: true) do |list|
175+
list << RDF::Literal(1)
176+
expect(graph.first_object(subject: list.subject, predicate: RDF.first)).to be_nil
177+
end
178+
expect(graph.first_object(subject: l.subject, predicate: RDF.first)).to eql RDF::Literal(1)
179+
expect(l.to_a).to include(RDF::Literal(1))
180+
end
181+
182+
it "rollback added values in a transaction" do
183+
n = RDF::Node.new
184+
l = RDF::List.new(graph: graph, wrap_transaction: true) do |list|
185+
list << RDF::Literal(1)
186+
expect(graph.first_object(subject: list.subject, predicate: RDF.first)).to be_nil
187+
list.graph.rollback
188+
end
189+
expect(graph.first_object(subject: l.subject, predicate: RDF.first)).to be_nil
190+
expect(l.to_a).to be_empty
191+
end
192+
end
151193
end
152194
end
153195

0 commit comments

Comments
 (0)