safety_pin 0.0.5 → 0.0.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.
@@ -15,8 +15,9 @@ module SafetyPin
15
15
  nil
16
16
  end
17
17
 
18
- def self.find_or_create(path)
19
- find(path) || create(path)
18
+ def self.find_or_create(path, primary_type = nil)
19
+ node_blueprint = NodeBlueprint.new(:path => path.to_s, :primary_type => primary_type)
20
+ find(path) || create(node_blueprint)
20
21
  end
21
22
 
22
23
  def self.exists?(path)
@@ -27,31 +28,31 @@ module SafetyPin
27
28
  JCR.session
28
29
  end
29
30
 
30
- def self.build(path, node_type = nil, properties = nil)
31
- path = path.to_s
32
- node_type ||= "nt:unstructured"
33
- properties ||= {}
34
- rel_path = nil
35
- if path.start_with?("/")
36
- rel_path = path.sub("/","")
37
- else
38
- raise ArgumentError.new("Given path not absolute: #{path}")
39
- end
31
+ def self.build(node_blueprint)
32
+ raise NodeError.new("NodeBlueprint is nil") if node_blueprint.nil?
33
+ raise NodeError.new("NodeBlueprint has non-absolute path") unless node_blueprint.path.to_s.start_with?("/")
34
+ raise NodeError.new("Node already exists at path: #{node_blueprint.path}") if Node.exists?(node_blueprint.path)
40
35
 
41
- if session.root_node.has_node(rel_path)
42
- raise NodeError.new("Node already exists at path: #{path}")
43
- else
44
- node = self.new(session.root_node.add_node(rel_path, node_type))
45
- node.properties = properties
36
+ rel_path_to_root_node = node_blueprint.path.to_s[1..-1]
37
+ node = self.new(session.root_node.add_node(rel_path_to_root_node, node_blueprint.primary_type))
38
+ node.properties = node_blueprint.properties
46
39
 
47
- node
48
- end
40
+ node
49
41
  rescue javax.jcr.PathNotFoundException => e
50
- raise NodeError.new("Cannot add a new node to a non-existing parent at #{path}")
42
+ raise NodeError.new("Cannot add a new node to a non-existing parent at #{node_blueprint.path}")
43
+ end
44
+
45
+ def self.update(node_blueprint)
46
+ node = find(node_blueprint.path)
47
+ # raise NodeError.new("Cannot retrieve node for update -- might not exist") if node.nil?
48
+ node.properties = node_blueprint.properties
49
+ node.primary_type = node_blueprint.primary_type
50
+ node.save
51
+ node
51
52
  end
52
53
 
53
- def self.create(path, node_type = nil, properties = nil)
54
- node = self.build(path, node_type, properties)
54
+ def self.create(node_blueprint)
55
+ node = self.build(node_blueprint)
55
56
  node.save
56
57
  node
57
58
  end
@@ -66,7 +67,7 @@ module SafetyPin
66
67
  end
67
68
 
68
69
  results = intermediate_paths.reverse.map do |intermediate_path|
69
- create(intermediate_path) unless exists?(intermediate_path)
70
+ create(NodeBlueprint.new(:path => intermediate_path.to_s)) unless exists?(intermediate_path)
70
71
  end
71
72
 
72
73
  session.save
@@ -74,6 +75,17 @@ module SafetyPin
74
75
  results
75
76
  end
76
77
 
78
+ def self.create_or_update(node_blueprint_or_node_blueprints)
79
+ node_blueprints = Array(node_blueprint_or_node_blueprints)
80
+ node_blueprints.map do |node_blueprint|
81
+ if exists?(node_blueprint.path)
82
+ update(node_blueprint)
83
+ else
84
+ create(node_blueprint)
85
+ end
86
+ end
87
+ end
88
+
77
89
  def initialize(j_node)
78
90
  @j_node = j_node
79
91
  end
@@ -242,13 +254,41 @@ module SafetyPin
242
254
  def properties=(new_props)
243
255
  property_names = (properties.keys + new_props.keys).uniq
244
256
  property_names.each do |name|
245
- if new_props[name].is_a?(Hash)
246
- build(name, nil, new_props[name])
257
+ # REFACTOR ME PLZ
258
+ child_path = Pathname(path.to_s) + name.to_s
259
+ if new_props[name].is_a? Hash
260
+ new_props[name] = convert_hash_to_node_blueprint(new_props[name])
261
+ end
262
+
263
+ if new_props[name].respond_to?(:node_blueprint?) and new_props[name].node_blueprint?
264
+ # Handle node blue prints
265
+ node_blueprint = NodeBlueprint.new(:properties => new_props[name].properties,
266
+ :path => child_path.to_s,
267
+ :primary_type => new_props[name].primary_type)
268
+ if Node.exists?(child_path)
269
+ Node.update(node_blueprint)
270
+ else
271
+ Node.build(node_blueprint)
272
+ end
247
273
  else
274
+ # handle everything else
248
275
  self[name] = new_props[name]
249
276
  end
250
277
  end
251
278
  end
279
+
280
+ # Convert a hash (and it's values recursively) to NodeBlueprints. This is a
281
+ # helper method, allowing a hash to be passed in to Node#properties= when
282
+ # only properties need to be set. One caveat: all node types will default
283
+ # to nt:unstructured.
284
+ def convert_hash_to_node_blueprint(hash)
285
+ hash.keys.each do |key|
286
+ if hash[key].is_a? Hash
287
+ hash[key] = convert_hash_to_node_blueprint(hash[key])
288
+ end
289
+ end
290
+ NodeBlueprint.new(:path => :no_path, :properties => hash)
291
+ end
252
292
 
253
293
  def value_factory
254
294
  session.value_factory
@@ -279,20 +319,34 @@ module SafetyPin
279
319
  def primary_type
280
320
  self["jcr:primaryType"]
281
321
  end
322
+
323
+ def primary_type=(primary_type)
324
+ j_node.set_primary_type(primary_type)
325
+ end
282
326
 
283
- def find_or_create(name, type = nil)
284
- child(name) || create(name, type)
327
+ def find_or_create(name, primary_type = nil)
328
+ path = Pathname(self.path) + name
329
+ self.class.find_or_create(path.to_s, primary_type)
285
330
  end
286
331
 
287
332
  # Create and return a child node with a given name
288
- def create(name, type = nil, properties = nil)
289
- path = Pathname(self.path) + name.to_s
290
- Node.create(path, type, properties)
333
+ def create(name, node_blueprint = nil)
334
+ Node.create(node_blueprint_for(name, node_blueprint))
335
+ end
336
+
337
+ def build(name, node_blueprint = nil)
338
+ Node.build(node_blueprint_for(name, node_blueprint))
291
339
  end
292
340
 
293
- def build(name, type = nil, properties = nil)
341
+ def node_blueprint_for(name, node_blueprint = nil)
294
342
  path = Pathname(self.path) + name.to_s
295
- Node.build(path, type, properties)
343
+
344
+ unless node_blueprint.nil?
345
+ properties = node_blueprint.properties
346
+ primary_type = node_blueprint.primary_type
347
+ end
348
+
349
+ NodeBlueprint.new(:path => path.to_s, :properties => properties, :primary_type => primary_type)
296
350
  end
297
351
  end
298
352
 
@@ -0,0 +1,18 @@
1
+ module SafetyPin
2
+ class NodeBlueprint
3
+ attr_accessor :path, :primary_type, :properties
4
+
5
+ def initialize(opts)
6
+ raise NodeBlueprintError.new("No path specified") unless opts[:path]
7
+ @path = opts[:path]
8
+ @primary_type = opts[:primary_type] || "nt:unstructured"
9
+ @properties = opts[:properties] || {}
10
+ end
11
+
12
+ def node_blueprint?
13
+ true
14
+ end
15
+ end
16
+
17
+ class NodeBlueprintError < Exception; end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module SafetyPin
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
data/lib/safety_pin.rb CHANGED
@@ -3,6 +3,7 @@ $: << File.dirname(__FILE__)
3
3
  require 'java'
4
4
  require 'safety_pin/jcr'
5
5
  require 'safety_pin/node'
6
+ require 'safety_pin/node_blueprint'
6
7
  require 'safety_pin/query'
7
8
  require 'safety_pin/query/where_condition'
8
9
 
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe SafetyPin::NodeBlueprint do
4
+ let(:node_blueprint) { SafetyPin::NodeBlueprint.new(:path => "/content/foo/bar", :primary_type => "nt:folder", :properties => {"foo" => "bar"}) }
5
+
6
+ describe "#primary_type" do
7
+ it "has a primary type" do
8
+ node_blueprint.primary_type.should == "nt:folder"
9
+ end
10
+
11
+ it "has a default primary type" do
12
+ SafetyPin::NodeBlueprint.new(:path => "/something").primary_type.should == "nt:unstructured"
13
+ end
14
+ end
15
+
16
+ describe "#properties" do
17
+ it "has properties" do
18
+ node_blueprint.properties.should == {"foo" => "bar"}
19
+ end
20
+
21
+ it "defaults to an empty hash" do
22
+ SafetyPin::NodeBlueprint.new(:path => "/something").properties.should == {}
23
+ end
24
+ end
25
+
26
+ describe "#path" do
27
+ it "requires a path" do
28
+ lambda { SafetyPin::NodeBlueprint.new({}).path }.should raise_error(NodeBlueprintError)
29
+ end
30
+
31
+ it "has a path" do
32
+ node_blueprint.path.should == "/content/foo/bar"
33
+ end
34
+ end
35
+ end
data/spec/node_spec.rb CHANGED
@@ -24,22 +24,22 @@ describe SafetyPin::Node do
24
24
  describe ".find_or_create" do
25
25
  context "given a node path that exists" do
26
26
  it "should return the node at that path" do
27
- SafetyPin::Node.create("/content/foo")
27
+ SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
28
28
  SafetyPin::Node.find_or_create("/content/foo").path.should eql "/content/foo"
29
29
  end
30
30
  end
31
31
 
32
- context "give a node path that doesn't exist" do
33
- it "should create a node at the path and return it" do
32
+ context "when node doesn't exist" do
33
+ it "returns node created at path" do
34
34
  SafetyPin::Node.find("/content/foo").should be_nil
35
- SafetyPin::Node.find_or_create("/content/foo").path.should eql "/content/foo"
35
+ SafetyPin::Node.find_or_create("/content/foo").path.should == "/content/foo"
36
36
  end
37
37
  end
38
38
  end
39
39
 
40
40
  describe ".exists?" do
41
41
  it "returns true if node exists at path" do
42
- SafetyPin::Node.create("/content/foo")
42
+ SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
43
43
  SafetyPin::Node.exists?("/content/foo").should be_true
44
44
  end
45
45
 
@@ -82,7 +82,7 @@ describe SafetyPin::Node do
82
82
  end
83
83
 
84
84
  it "should return a grandchild node given a relative path" do
85
- SafetyPin::Node.create("/content/foo")
85
+ SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
86
86
  node.child("content/foo").name.should eql("foo")
87
87
  end
88
88
  end
@@ -98,9 +98,35 @@ describe SafetyPin::Node do
98
98
  end
99
99
  end
100
100
  end
101
+
102
+ describe ".create_or_update", :focus => true do
103
+ let(:node_blueprint) { SafetyPin::NodeBlueprint.new(:path => "/content/foo") }
104
+
105
+ it "calls Node.create with arg when nothing exists at path" do
106
+ SafetyPin::Node.should_receive(:create).with(node_blueprint)
107
+ SafetyPin::Node.create_or_update(node_blueprint)
108
+ end
109
+
110
+ it "calls Node.update with arg when node exists at path" do
111
+ SafetyPin::Node.create(node_blueprint)
112
+ SafetyPin::Node.should_receive(:update).with(node_blueprint)
113
+ SafetyPin::Node.create_or_update(node_blueprint)
114
+ end
115
+
116
+ it "takes a node blueprint" do
117
+ SafetyPin::Node.create_or_update(node_blueprint)
118
+ SafetyPin::Node.exists?(node_blueprint.path).should be_true
119
+ end
120
+
121
+ it "takes an array of node blueprints" do
122
+ node_blueprints = [node_blueprint, SafetyPin::NodeBlueprint.new(:path => "/content/foo/bar")]
123
+ SafetyPin::Node.create_or_update(node_blueprints)
124
+ node_blueprints.each {|node_blueprint| SafetyPin::Node.exists?(node_blueprint.path).should be_true }
125
+ end
126
+ end
101
127
 
102
128
  describe "#find_or_create_child" do
103
- let(:parent) { SafetyPin::Node.create("/content/foo") }
129
+ let(:parent) { SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo")) }
104
130
 
105
131
  context "an existing node path" do
106
132
  it "should return the child node" do
@@ -125,7 +151,7 @@ describe SafetyPin::Node do
125
151
  describe "#save" do
126
152
  context "on an existing node with changes" do
127
153
  before do
128
- @node = SafetyPin::Node.create("/content/foo")
154
+ @node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
129
155
  @node["bar"] = "baz"
130
156
  end
131
157
 
@@ -143,13 +169,13 @@ describe SafetyPin::Node do
143
169
 
144
170
  context "on a new node" do
145
171
  it "should save the node" do
146
- node = SafetyPin::Node.build("/content/foo")
172
+ node = SafetyPin::Node.build(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
147
173
  node.save.should be_true
148
174
  end
149
175
 
150
176
  it "should save changes in parent node" do
151
- parent_node = SafetyPin::Node.create("/content/foo")
152
- node = SafetyPin::Node.build("/content/foo/bar")
177
+ parent_node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
178
+ node = SafetyPin::Node.build(SafetyPin::NodeBlueprint.new(:path => "/content/foo/bar"))
153
179
  parent_node["baz"] = "qux"
154
180
  parent_node.should be_changed
155
181
  node.save
@@ -160,7 +186,7 @@ describe SafetyPin::Node do
160
186
 
161
187
  describe "#read_attribute" do
162
188
  context "on an existing node" do
163
- let(:node) { SafetyPin::Node.create("/content/foo") }
189
+ let(:node) { SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo")) }
164
190
 
165
191
  it "should return the string value of a string property" do
166
192
  node["foo"] = "bar"
@@ -208,12 +234,12 @@ describe SafetyPin::Node do
208
234
  end
209
235
 
210
236
  it "should throw an exception when accessing a non-existent (nil) property" do
211
- lambda { SafetyPin::Node.build("/content/foo").read_attribute("foo-bar-baz") }.should raise_error(SafetyPin::NilPropertyError)
237
+ lambda { SafetyPin::Node.build(SafetyPin::NodeBlueprint.new(:path => "/content/foo")).read_attribute("foo-bar-baz") }.should raise_error(SafetyPin::NilPropertyError)
212
238
  end
213
239
  end
214
240
 
215
241
  context "#write_attribute" do
216
- let(:node) { SafetyPin::Node.create("/content/foo") }
242
+ let(:node) { SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo")) }
217
243
 
218
244
  context "given a single value" do
219
245
  it "should set a string property value" do
@@ -302,7 +328,7 @@ describe SafetyPin::Node do
302
328
  end
303
329
 
304
330
  context "#reload" do
305
- let(:node) { SafetyPin::Node.create("/content/foo") }
331
+ let(:node) { SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo")) }
306
332
 
307
333
  it "should discard pending changes" do
308
334
  node["foo"] = "bar"
@@ -322,7 +348,7 @@ describe SafetyPin::Node do
322
348
 
323
349
  describe "#[]" do
324
350
  it "should return the value of a given property name" do
325
- node = SafetyPin::Node.create("/content/foo")
351
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
326
352
  node.write_attribute("bar","baz")
327
353
  node.save
328
354
  node["bar"].should eql("baz")
@@ -331,7 +357,7 @@ describe SafetyPin::Node do
331
357
 
332
358
  describe "#[]=" do
333
359
  it "should set the value of a given property name" do
334
- node = SafetyPin::Node.create("/content/foo")
360
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
335
361
  node.write_attribute("bar","baz")
336
362
  node["bar"] = "qux"
337
363
  node["bar"].should eql("qux")
@@ -354,7 +380,7 @@ describe SafetyPin::Node do
354
380
 
355
381
  context "#new?" do
356
382
  it "should return true if node has never been saved to JCR" do
357
- SafetyPin::Node.build("/content/foo").should be_new
383
+ SafetyPin::Node.build(SafetyPin::NodeBlueprint.new(:path => "/content/foo")).should be_new
358
384
  end
359
385
 
360
386
  it "should return false if node has been saved to JCR" do
@@ -369,7 +395,7 @@ describe SafetyPin::Node do
369
395
  end
370
396
 
371
397
  describe "#properties=" do
372
- let(:node) { SafetyPin::Node.create("/content/foo") }
398
+ let(:node) { SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo")) }
373
399
 
374
400
  it "should set the properties of a node" do
375
401
  node.properties = {"foo" => "bar"}
@@ -382,9 +408,25 @@ describe SafetyPin::Node do
382
408
  node.properties.should eql({"baz" => "qux"})
383
409
  end
384
410
 
385
- it "should create child nodes for hash values" do
386
- node.properties = {foo: {bar: "baz"}}
387
- node.child(:foo).properties.should == {"bar" => "baz"}
411
+ it "creates child nodes for node blueprints" do
412
+ node_blueprint = SafetyPin::NodeBlueprint.new(:path => "/this/path/gets/thrown/away",
413
+ :primary_type => "sling:OrderedFolder",
414
+ :properties => {"bar" => "baz"})
415
+ node.properties = {"foo" => node_blueprint}
416
+ node.child("foo").properties.should == {"bar" => "baz"}
417
+ node.child("foo").primary_type.should == "sling:OrderedFolder"
418
+ end
419
+
420
+ xit "updates child nodes when they already exist" do
421
+ # Create /content/foo/bar and /content/foo/bar/baz
422
+ node.create(:bar, "nt:unstructured", {"bar" => "baz"})
423
+ node.child(:bar).create(:baz)
424
+ node.child(:bar).child(:baz).path.should == "/content/foo/bar/baz"
425
+ # Update /content/foo/bar by updating /content/foo properties
426
+ node.properties = {bar: SafetyPin::NodeBlueprint.new(:path => "/this/path/gets/thrown/away", :primary_type => "sling:OrderedFolder", :properties => {"updated" => "props"})}
427
+ node.child(:bar).properties.should == {"updated" => "props"}
428
+ node.child(:bar).primary_type.should == "sling:OrderedFolder"
429
+ node.child(:bar).child(:baz).path.should == "/content/foo/bar/baz"
388
430
  end
389
431
  end
390
432
 
@@ -396,7 +438,7 @@ describe SafetyPin::Node do
396
438
 
397
439
  describe "#mixin_types" do
398
440
  it "should return the mixin types of a node" do
399
- node = SafetyPin::Node.create("/content/foo")
441
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
400
442
  node.j_node.add_mixin("mix:created")
401
443
  node.save
402
444
  node.mixin_types.should eql(["mix:created"])
@@ -404,7 +446,7 @@ describe SafetyPin::Node do
404
446
  end
405
447
 
406
448
  describe "#add_mixin" do
407
- let(:node) { SafetyPin::Node.create("/content/foo") }
449
+ let(:node) { SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo")) }
408
450
 
409
451
  it "should add a mixin type to node" do
410
452
  node.add_mixin("mix:created")
@@ -420,7 +462,7 @@ describe SafetyPin::Node do
420
462
 
421
463
  describe "#remove_mixin" do
422
464
  let(:node) do
423
- node = SafetyPin::Node.create("/content/foo")
465
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
424
466
  node.add_mixin("mix:created")
425
467
  node.save
426
468
  node
@@ -440,78 +482,88 @@ describe SafetyPin::Node do
440
482
  end
441
483
  end
442
484
 
443
- describe ".build" do
444
- context "given an absolute path" do
445
- it "should build and return a property-less, unsaved nt:unstructured child node" do
446
- node = SafetyPin::Node.build("/content/foo")
447
- node.should be_new
448
- node.properties.should eql({})
449
- end
485
+ describe ".update" do
486
+ let(:node) do
487
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
488
+ node.save
489
+ node
490
+ end
450
491
 
492
+ it "updates a nodes properties" do
493
+ SafetyPin::Node.update(SafetyPin::NodeBlueprint.new(:path => node.path, :properties => {"foo" => "barbazbuzzzzz"}))
494
+ SafetyPin::Node.find(node.path).properties.should == {"foo" => "barbazbuzzzzz"}
495
+ end
451
496
 
497
+ it "preserves node children" do
498
+ node.create(:bar)
499
+ SafetyPin::Node.update(SafetyPin::NodeBlueprint.new(:path => node.path, :primary_type => "sling:OrderedFolder", :properties => {"foo" => "bar"}))
500
+ SafetyPin::Node.exists?("/content/foo/bar").should be_true
501
+ end
452
502
 
453
- context "given properties" do
454
- it "should build a node with properties" do
455
- node = SafetyPin::Node.build("/content/foo", nil, {foo: "bar"})
456
- node.properties.should == {"foo" => "bar"}
457
- end
458
- end
459
-
460
- context "and a node type string" do
461
- it "should create an unsaved node of the given type" do
462
- node = SafetyPin::Node.build("/content/foo", "nt:folder")
463
- node.should be_new
464
- node["jcr:primaryType"].should eql("nt:folder")
465
- end
466
- end
503
+ it "modifies the primary type" do
504
+ SafetyPin::Node.update(SafetyPin::NodeBlueprint.new(:path => node.path, :primary_type => "sling:OrderedFolder"))
505
+ SafetyPin::Node.find(node.path).primary_type.should == "sling:OrderedFolder"
506
+ end
507
+ end
467
508
 
468
- context "that already exists" do
469
- it "should raise an error" do
470
- lambda { SafetyPin::Node.build("/content") }.should raise_error(SafetyPin::NodeError)
471
- end
472
- end
473
-
474
- it "should coerce path to a string" do
475
- node = SafetyPin::Node.build(Pathname("/content/foo"))
476
- node.should be_new
477
- node.properties.should eql({})
478
- end
509
+ describe "#primary_type=" do
510
+ let(:node) do
511
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
512
+ node.save
513
+ node
479
514
  end
480
-
481
- context "given an absolute path with a non-existent parent node" do
482
- it "should raise an error" do
483
- lambda { SafetyPin::Node.build("/content/foo/bar/baz") }.should raise_error(SafetyPin::NodeError)
484
- end
515
+
516
+ it "sets the primary type" do
517
+ node.primary_type.should == "nt:unstructured"
518
+ node.primary_type = "sling:OrderedFolder"
519
+ node.save
520
+ SafetyPin::Node.find(node.path).primary_type.should == "sling:OrderedFolder"
485
521
  end
486
-
487
- context "given a relative path" do
488
- it "should raise an error" do
489
- lambda { SafetyPin::Node.build("content/foo") }.should raise_error(ArgumentError)
490
- end
522
+ end
523
+
524
+ describe ".build" do
525
+ it "returns an unsaved node at path of a specified type with properties set" do
526
+ node = SafetyPin::Node.build(SafetyPin::NodeBlueprint.new(:path => "/content/foo", :primary_type => "sling:OrderedFolder", :properties => {"foo" => "bar"}))
527
+ node.should be_new
528
+ node.primary_type.should == "sling:OrderedFolder"
529
+ node.properties.should == {"foo" => "bar"}
530
+ end
531
+
532
+ it "complains when the nodes already exists" do
533
+ node_blueprint = SafetyPin::NodeBlueprint.new(:path => "/content/foo")
534
+ SafetyPin::Node.create(node_blueprint)
535
+ lambda { SafetyPin::Node.build(node_blueprint) }.should raise_error(SafetyPin::NodeError)
536
+ end
537
+
538
+ it "complains when given a path with missing parents" do
539
+ lambda { SafetyPin::Node.build(SafetyPin::NodeBlueprint.new(:path => "/content/foo/bar/baz/doesnt/exist")) }.should raise_error(SafetyPin::NodeError)
540
+ end
541
+
542
+ it "complains when given a relative path" do
543
+ lambda { SafetyPin::Node.build(SafetyPin::NodeBlueprint.new(:path => "foo/not/absolute")) }.should raise_error(SafetyPin::NodeError)
544
+ end
545
+
546
+ it "complains when given nil" do
547
+ lambda { SafetyPin::Node.build(nil) }.should raise_error(SafetyPin::NodeError)
491
548
  end
492
549
  end
493
550
 
494
551
  describe ".create" do
495
- context "given a path" do
496
- it "should build and save a node" do
497
- node = SafetyPin::Node.create("/content/foo")
498
- node.should be_a(SafetyPin::Node)
499
- node.destroy
500
- end
552
+ it "creates a node" do
553
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
554
+ node.should be_a(SafetyPin::Node)
501
555
  end
502
556
 
503
- context "given a path and a node type" do
504
- it "should build and save a node of the specified type" do
505
- node = SafetyPin::Node.create("/content/foo", "nt:folder")
506
- SafetyPin::Node.find("/content/foo").should_not be_nil
507
- end
557
+ it "creates a node of a specific type" do
558
+ SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo", :primary_type => "sling:OrderedFolder"))
559
+ SafetyPin::Node.find("/content/foo").primary_type.should == "sling:OrderedFolder"
508
560
  end
509
561
  end
510
562
 
511
563
  describe ".create_parents" do
512
564
  it "creates parent nodes if they do not exist" do
513
565
  SafetyPin::Node.create_parents("/content/foo/bar/baz")
514
- SafetyPin::Node.create("/content/foo/bar/baz").should_not be_nil
566
+ SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo/bar/baz")).should_not be_nil
515
567
  end
516
568
  end
517
569
 
@@ -523,7 +575,7 @@ describe SafetyPin::Node do
523
575
 
524
576
  describe "#property_is_multi_valued" do
525
577
  it "should return true if property is multi-valued" do
526
- node = SafetyPin::Node.create("/content/foo")
578
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
527
579
  node["bar"] = ["baz", "qux"]
528
580
  node.save
529
581
  property = node.j_node.get_property("bar")
@@ -531,7 +583,7 @@ describe SafetyPin::Node do
531
583
  end
532
584
 
533
585
  it "should return false if property is not multi-valued" do
534
- node = SafetyPin::Node.create("/content/foo")
586
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
535
587
  node["bar"] = "baz"
536
588
  node.save
537
589
  property = node.j_node.get_property("bar")
@@ -542,14 +594,14 @@ describe SafetyPin::Node do
542
594
  describe "#destroy" do
543
595
  it "should remove node from JCR" do
544
596
  path = "/content/foo"
545
- node = SafetyPin::Node.create(path)
597
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => path))
546
598
  node.destroy
547
599
  SafetyPin::Node.find(path).should be_nil
548
600
  end
549
601
 
550
602
  it "should save changes in parent node" do
551
- parent_node = SafetyPin::Node.create("/content/foo")
552
- node = SafetyPin::Node.create("/content/foo/bar")
603
+ parent_node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
604
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo/bar"))
553
605
  parent_node["baz"] = "qux"
554
606
  parent_node.should be_changed
555
607
  node.destroy
@@ -558,7 +610,7 @@ describe SafetyPin::Node do
558
610
 
559
611
  context "when it fails" do
560
612
  it "should raise an error" do
561
- node = SafetyPin::Node.create("/content/foo")
613
+ node = SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo"))
562
614
  node.add_mixin("mix:created")
563
615
  node.save
564
616
  node.remove_mixin("mix:created") # make node unremoveable
@@ -568,7 +620,7 @@ describe SafetyPin::Node do
568
620
  end
569
621
 
570
622
  describe "#primary_type" do
571
- let(:node) { SafetyPin::Node.create("/content/foo") }
623
+ let(:node) { SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo")) }
572
624
 
573
625
  it "should return the primary type of the node" do
574
626
  node.primary_type.should eql("nt:unstructured")
@@ -576,25 +628,25 @@ describe SafetyPin::Node do
576
628
  end
577
629
 
578
630
  describe "#build" do
579
- let(:node) { SafetyPin::Node.create("/content/foo") }
631
+ let(:node) { SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo")) }
580
632
 
581
633
  it "should create a child node with a given name" do
582
634
  node.build("bar").path.should == "/content/foo/bar"
583
635
  end
584
636
 
585
637
  it "should create a child node with a given name and node type" do
586
- child_node = node.build("bar", "nt:folder")
638
+ child_node = node.build("bar", SafetyPin::NodeBlueprint.new(:primary_type => "nt:folder", :path => :no_path))
587
639
  child_node.should be_a(SafetyPin::Node)
588
- child_node.primary_type.should eql("nt:folder")
640
+ child_node.primary_type.should == "nt:folder"
589
641
  end
590
642
 
591
643
  it "should create a child node with a name, node type, and properties" do
592
- node.build("bar", nil, {foo: "bar"}).properties.should == {"foo" => "bar"}
644
+ node.build("bar", SafetyPin::NodeBlueprint.new(:path => :no_path, :properties => {foo: "bar"})).properties.should == {"foo" => "bar"}
593
645
  end
594
646
  end
595
647
 
596
648
  describe "#create" do
597
- let(:node) { SafetyPin::Node.create("/content/foo") }
649
+ let(:node) { SafetyPin::Node.create(SafetyPin::NodeBlueprint.new(:path => "/content/foo")) }
598
650
 
599
651
  it "should create a child node with a given name" do
600
652
  child_node = node.create("bar")
@@ -603,13 +655,13 @@ describe SafetyPin::Node do
603
655
  end
604
656
 
605
657
  it "should create a child node with a given name and node type" do
606
- child_node = node.create("bar", "nt:folder")
658
+ child_node = node.create("bar", SafetyPin::NodeBlueprint.new(:path => :no_path, :primary_type => "nt:folder"))
607
659
  child_node.should_not be_new
608
660
  child_node.primary_type.should eql("nt:folder")
609
661
  end
610
662
 
611
663
  it "should create a child node with a name, node type, and properties" do
612
- child_node = node.create("bar", nil, {foo: "bar"})
664
+ child_node = node.create("bar", SafetyPin::NodeBlueprint.new(:path => :no_path, :properties => {foo: "bar"}))
613
665
  child_node.should_not be_new
614
666
  child_node.properties.should == {"foo" => "bar"}
615
667
  end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: safety_pin
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.5
5
+ version: 0.0.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jordan Raine
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-23 00:00:00.000000000 Z
12
+ date: 2012-10-15 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: An easy-to-use JCR connector for JRuby
15
15
  email:
@@ -31,12 +31,14 @@ files:
31
31
  - lib/safety_pin.rb
32
32
  - lib/safety_pin/jcr.rb
33
33
  - lib/safety_pin/node.rb
34
+ - lib/safety_pin/node_blueprint.rb
34
35
  - lib/safety_pin/query.rb
35
36
  - lib/safety_pin/query/where_condition.rb
36
37
  - lib/safety_pin/version.rb
37
38
  - safety_pin.gemspec
38
39
  - spec/jcr_spec.rb
39
40
  - spec/jcr_sql2_spec.rb
41
+ - spec/node_blueprint_spec.rb
40
42
  - spec/node_spec.rb
41
43
  - spec/query_spec.rb
42
44
  - spec/spec_helper.rb
@@ -68,6 +70,7 @@ summary: JCR connector for JRuby
68
70
  test_files:
69
71
  - spec/jcr_spec.rb
70
72
  - spec/jcr_sql2_spec.rb
73
+ - spec/node_blueprint_spec.rb
71
74
  - spec/node_spec.rb
72
75
  - spec/query_spec.rb
73
76
  - spec/spec_helper.rb