basilik 0.0.1
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.
- checksums.yaml +15 -0
- data/.autotest +1 -0
- data/.gitignore +4 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +42 -0
- data/README.md +319 -0
- data/Rakefile +21 -0
- data/basilik.gemspec +27 -0
- data/examples/a.rb +10 -0
- data/examples/b.rb +5 -0
- data/examples/c.rb +6 -0
- data/examples/d.rb +15 -0
- data/examples/e.rb +21 -0
- data/examples/f.rb +20 -0
- data/examples/g.rb +20 -0
- data/examples/h.rb +22 -0
- data/examples/i.rb +26 -0
- data/examples/j.rb +10 -0
- data/lib/basilik/action.rb +141 -0
- data/lib/basilik/core.rb +1 -0
- data/lib/basilik/core_ext/map.rb +23 -0
- data/lib/basilik/core_ext/string.rb +15 -0
- data/lib/basilik/faults.rb +9 -0
- data/lib/basilik/load.rb +22 -0
- data/lib/basilik/ref.rb +64 -0
- data/lib/basilik/snapshot.rb +99 -0
- data/lib/basilik/version.rb +3 -0
- data/lib/basilik.rb +17 -0
- data/spec/basilik/.firebase_spec.rb.swp +0 -0
- data/spec/basilik/core_ext/map_spec.rb +45 -0
- data/spec/basilik/core_ext/string_spec.rb +26 -0
- data/spec/basilik/ref_spec.rb +109 -0
- data/spec/basilik/root_spec.rb +301 -0
- data/spec/basilik/snapshot_spec.rb +174 -0
- data/spec/spec_helper.rb +10 -0
- metadata +105 -0
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'basilik/faults'
|
2
|
+
|
3
|
+
module Basilik
|
4
|
+
module Action
|
5
|
+
include Basilik::Faults
|
6
|
+
|
7
|
+
def read
|
8
|
+
location = json_url
|
9
|
+
resp = Typhoeus.get( location, gen_opts( params: {format: :export} ) )
|
10
|
+
res = handle_response( resp, location )
|
11
|
+
res.is_a?(Map) ? Snapshot.new( res ).to_map : res.is_a?(String) ? res.to_val : res
|
12
|
+
end
|
13
|
+
|
14
|
+
def set( data )
|
15
|
+
location = json_url
|
16
|
+
resp = Typhoeus.put( location, gen_opts( body: data.to_json ) )
|
17
|
+
handle_response( resp, location )
|
18
|
+
end
|
19
|
+
|
20
|
+
def update( data )
|
21
|
+
location = json_url
|
22
|
+
resp = Typhoeus.patch( location, gen_opts( body: data.to_json ) )
|
23
|
+
handle_response( resp, location )
|
24
|
+
end
|
25
|
+
|
26
|
+
def inc( field )
|
27
|
+
map = read
|
28
|
+
current_val = map[field]
|
29
|
+
raise NonNumericFieldError, "The field #{field} does not have a numeric value" if current_val and !current_val.is_a? Numeric
|
30
|
+
if current_val
|
31
|
+
new_val = map[field] + 1
|
32
|
+
else
|
33
|
+
new_val = 0
|
34
|
+
end
|
35
|
+
update( field => new_val )
|
36
|
+
end
|
37
|
+
|
38
|
+
def dec( field )
|
39
|
+
map = read
|
40
|
+
current_val = map[field]
|
41
|
+
raise NonNumericFieldError, "The field #{field} does not have a numeric value" if current_val and !current_val.is_a? Numeric
|
42
|
+
if current_val
|
43
|
+
new_val = map[field] - 1
|
44
|
+
else
|
45
|
+
new_val = 0
|
46
|
+
end
|
47
|
+
update( field => new_val )
|
48
|
+
end
|
49
|
+
|
50
|
+
def remove
|
51
|
+
location = json_url
|
52
|
+
resp = Typhoeus.delete( location, gen_opts )
|
53
|
+
unless resp.success?
|
54
|
+
raise InvalidRequestError, "<#{resp.return_code}> Unable to perform request #{location}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def push( data=nil )
|
59
|
+
location = json_url
|
60
|
+
opts = {}
|
61
|
+
if data
|
62
|
+
opts[:body] = data.to_json
|
63
|
+
else
|
64
|
+
opts[:body] = ''.to_json
|
65
|
+
end
|
66
|
+
resp = Typhoeus.post( location, gen_opts( opts ) )
|
67
|
+
res = handle_response( resp, location )
|
68
|
+
Basilik::Load.new( uri.to_s + '/' + res.name )
|
69
|
+
end
|
70
|
+
|
71
|
+
def set_priority( priority )
|
72
|
+
location = json_url( true )
|
73
|
+
resp = Typhoeus.put( location, gen_opts( body: priority.to_json ) )
|
74
|
+
unless resp.success? or resp.body
|
75
|
+
raise InvalidRequestError, "<#{resp.return_code}> Unable to perform request #{location}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_priority
|
80
|
+
location = json_url( true )
|
81
|
+
resp = Typhoeus.get( location, gen_opts( params: { format: :export} ) )
|
82
|
+
res = handle_response( resp, location )
|
83
|
+
res.to_i
|
84
|
+
rescue NoDataError
|
85
|
+
nil
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_rules
|
89
|
+
location = rules_url
|
90
|
+
resp = Typhoeus.get( location, gen_opts )
|
91
|
+
handle_response( resp, location )
|
92
|
+
end
|
93
|
+
|
94
|
+
def set_rules( rules )
|
95
|
+
location = rules_url
|
96
|
+
resp = Typhoeus.put( location, gen_opts( body: {:rules => rules}.to_json ) )
|
97
|
+
handle_response( resp, location )
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def gen_opts( opts={} )
|
104
|
+
if @auth_token
|
105
|
+
opts[:params] ||= {}
|
106
|
+
opts[:params][:auth] = @auth_token
|
107
|
+
end
|
108
|
+
opts
|
109
|
+
end
|
110
|
+
|
111
|
+
def handle_response( resp, location )
|
112
|
+
if resp.response_code == 403
|
113
|
+
raise PermissionDeniedError, "No permission for #{location}"
|
114
|
+
end
|
115
|
+
unless resp.success?
|
116
|
+
raise InvalidRequestError, "<#{resp.return_code}> Unable to perform request #{location}"
|
117
|
+
end
|
118
|
+
if resp.body.empty? or resp.body == "null"
|
119
|
+
raise NoDataError, "No data found at location #{location}"
|
120
|
+
end
|
121
|
+
|
122
|
+
results = JSON.parse( resp.body ) rescue nil
|
123
|
+
results ? (results.is_a?(Hash) ? Map( results ) : results ) : resp.body.gsub( /\"/, '' )
|
124
|
+
end
|
125
|
+
|
126
|
+
def json_url( priority=nil )
|
127
|
+
if @url =~ /\.json$/
|
128
|
+
loc = @url
|
129
|
+
elsif root?
|
130
|
+
loc = @url + "/.json"
|
131
|
+
else
|
132
|
+
loc = @url + ".json"
|
133
|
+
end
|
134
|
+
priority ? loc.gsub( /\.json$/, "/.priority/.json" ) : loc
|
135
|
+
end
|
136
|
+
|
137
|
+
def rules_url
|
138
|
+
@uri.merge( '.settings/rules.json' ).to_s
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/lib/basilik/core.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Basilik.require_all_libs_relative_to File.expand_path( File.join( %w(basilik core_ext), Basilik::LIBPATH ) )
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'values'
|
2
|
+
|
3
|
+
class Map
|
4
|
+
Event = Value.new( :event_type, :ref )
|
5
|
+
def diff(other)
|
6
|
+
res = dup.
|
7
|
+
delete_if { |k, v| other[k] == v }.
|
8
|
+
merge!(other.dup.delete_if { |k, v| has_key?(k) })
|
9
|
+
events = []
|
10
|
+
res.each_pair do |k,v|
|
11
|
+
if self[k]
|
12
|
+
if other[k]
|
13
|
+
events << Event.new( Basilik::Load.evt_value, k )
|
14
|
+
else
|
15
|
+
events << Event.new( Basilik::Load.evt_child_removed, k )
|
16
|
+
end
|
17
|
+
else
|
18
|
+
events << Event.new( Basilik::Load.evt_child_added, k )
|
19
|
+
end
|
20
|
+
end
|
21
|
+
events
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Basilik
|
2
|
+
module Faults
|
3
|
+
class NoDataError < RuntimeError; end
|
4
|
+
class InvalidRequestError < RuntimeError; end
|
5
|
+
class InvalidJSONError < RuntimeError; end
|
6
|
+
class PermissionDeniedError < RuntimeError; end
|
7
|
+
class NonNumericFieldError < RuntimeError; end
|
8
|
+
end
|
9
|
+
end
|
data/lib/basilik/load.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'basilik/ref'
|
2
|
+
|
3
|
+
module Basilik
|
4
|
+
class Load
|
5
|
+
include Basilik::Ref
|
6
|
+
include Basilik::Action
|
7
|
+
|
8
|
+
attr_reader :url, :uri
|
9
|
+
|
10
|
+
def self.evt_value; :value; end
|
11
|
+
def self.evt_child_added; :add_child; end
|
12
|
+
def self.evt_child_changed; :mod_child; end
|
13
|
+
def self.evt_child_removed; :rm_child; end
|
14
|
+
def self.evt_child_moved; :mv_child; end
|
15
|
+
|
16
|
+
def initialize( url, auth_token=nil )
|
17
|
+
@url = url
|
18
|
+
@uri = URI.parse( @url )
|
19
|
+
@auth_token = auth_token
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/basilik/ref.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Basilik
|
4
|
+
module Ref
|
5
|
+
def name
|
6
|
+
parse_path[-1]
|
7
|
+
end
|
8
|
+
|
9
|
+
def val
|
10
|
+
read
|
11
|
+
end
|
12
|
+
|
13
|
+
def root
|
14
|
+
return self if root?
|
15
|
+
Basilik::Load.new( @uri.scheme + '://' + @uri.host )
|
16
|
+
end
|
17
|
+
|
18
|
+
def root?
|
19
|
+
@uri.path.empty? or @uri.path == "/"
|
20
|
+
end
|
21
|
+
|
22
|
+
def parent
|
23
|
+
return nil if root?
|
24
|
+
path = parse_path[0..-2].join( "/" )
|
25
|
+
Basilik::Load.new( root.uri.merge(path).to_s )
|
26
|
+
end
|
27
|
+
|
28
|
+
def child( child_path )
|
29
|
+
Basilik::Load.new( "#{uri.to_s}/#{child_path}" )
|
30
|
+
end
|
31
|
+
|
32
|
+
def child?( child_path )
|
33
|
+
child( child_path ).read
|
34
|
+
true
|
35
|
+
rescue
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
def children?
|
40
|
+
data = read
|
41
|
+
data.is_a? Map and !data.empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
def num_children
|
45
|
+
data = read
|
46
|
+
if data.is_a? Map and !data.empty?
|
47
|
+
data.count
|
48
|
+
else
|
49
|
+
0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
@url
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def parse_path
|
61
|
+
@uri.path.split( "/" )
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Basilik
|
2
|
+
class Snapshot
|
3
|
+
|
4
|
+
class Node
|
5
|
+
attr_accessor :priority, :name, :parent, :children, :value
|
6
|
+
|
7
|
+
def initialize( name )
|
8
|
+
@name = name
|
9
|
+
@priority = nil
|
10
|
+
@children = []
|
11
|
+
@value = nil
|
12
|
+
@parent = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_child( child )
|
16
|
+
child.parent = self
|
17
|
+
children << child
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_map
|
21
|
+
map = Map.new
|
22
|
+
order( map )
|
23
|
+
map
|
24
|
+
end
|
25
|
+
|
26
|
+
def dump
|
27
|
+
puts "#{' '*level}#{name} [#{priority.inspect}] --#{value.inspect}"
|
28
|
+
children.sort_by do |c|
|
29
|
+
if c.priority and c.priority.is_a? Integer
|
30
|
+
"b_#{c.priority}_#{c.name}"
|
31
|
+
elsif c.priority
|
32
|
+
"z_#{c.priority}_#{c.name}"
|
33
|
+
else
|
34
|
+
"a_#{c.name}"
|
35
|
+
end
|
36
|
+
end.each do |c|
|
37
|
+
c.dump
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def order( map )
|
44
|
+
map[name] = children.empty? ? value : Map.new
|
45
|
+
children.sort_by do |c|
|
46
|
+
if c.priority and c.priority.is_a? Numeric
|
47
|
+
"b_#{'%05.2f' % c.priority}_#{c.name}"
|
48
|
+
elsif c.priority
|
49
|
+
"z_#{c.priority}_#{c.name}"
|
50
|
+
else
|
51
|
+
"a_#{c.name}"
|
52
|
+
end
|
53
|
+
end.each do |c|
|
54
|
+
c.send( :order, map[name] )
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def level
|
59
|
+
level = 0
|
60
|
+
node = self
|
61
|
+
while node.parent do
|
62
|
+
level +=1
|
63
|
+
node = node.parent
|
64
|
+
end
|
65
|
+
level
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def initialize( map )
|
70
|
+
@map = map
|
71
|
+
@root = Node.new( 'root' )
|
72
|
+
build( @map, @root )
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_map
|
76
|
+
@root.to_map.root
|
77
|
+
end
|
78
|
+
|
79
|
+
def dump
|
80
|
+
@root.dump
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def build( map, root )
|
86
|
+
map.each_pair do |k,v|
|
87
|
+
node = Node.new( k )
|
88
|
+
if v.is_a? Hash
|
89
|
+
priority = v.delete('.priority')
|
90
|
+
node.priority = priority if priority
|
91
|
+
build( v, node )
|
92
|
+
else
|
93
|
+
node.value = v.is_a?(String) ? v.to_val : v
|
94
|
+
end
|
95
|
+
root.add_child( node )
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/basilik.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'typhoeus'
|
3
|
+
require 'map'
|
4
|
+
|
5
|
+
module Basilik
|
6
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
7
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
8
|
+
|
9
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
10
|
+
dir ||= ::File.basename(fname, '.*')
|
11
|
+
search_me = ::File.expand_path(
|
12
|
+
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
13
|
+
Dir.glob(search_me).sort.each { |rb| require rb }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Basilik.require_all_libs_relative_to File.expand_path( "basilik", Basilik::LIBPATH )
|
Binary file
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Map do
|
4
|
+
describe '#diff' do
|
5
|
+
describe 'single vals' do
|
6
|
+
it "tracks value changes correctly" do
|
7
|
+
prev = Map(:a,1)
|
8
|
+
curr = Map(:a,2)
|
9
|
+
evts = prev.diff( curr )
|
10
|
+
evts.should have(1).item
|
11
|
+
evts.first.event_type.should == Basilik::Load.evt_value
|
12
|
+
evts.first.ref.should == 'a'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "tracks adds correctly" do
|
16
|
+
prev = Map.new
|
17
|
+
curr = Map(:a,2)
|
18
|
+
evts = prev.diff( curr )
|
19
|
+
evts.should have(1).item
|
20
|
+
evts.first.event_type.should == Basilik::Load.evt_child_added
|
21
|
+
evts.first.ref.should == 'a'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "tracks deletes correctly" do
|
25
|
+
prev = Map(:a,2)
|
26
|
+
curr = Map.new
|
27
|
+
evts = prev.diff( curr )
|
28
|
+
evts.should have(1).item
|
29
|
+
evts.first.event_type.should == Basilik::Load.evt_child_removed
|
30
|
+
evts.first.ref.should == 'a'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'multi vals' do
|
35
|
+
it 'tracks multi value changes correctly' do
|
36
|
+
prev = Map(:a,1)
|
37
|
+
curr = Map({a:{a_1:10, a_2:20}})
|
38
|
+
evts = prev.diff( curr )
|
39
|
+
evts.should have(1).item
|
40
|
+
evts.first.event_type.should == Basilik::Load.evt_value
|
41
|
+
evts.first.ref.should == 'a'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe String do
|
4
|
+
describe '#to_val' do
|
5
|
+
it "keep strings unchanged" do
|
6
|
+
"fred".to_val.should == "fred"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "converts an integer correctly" do
|
10
|
+
"10".to_val.should == 10
|
11
|
+
end
|
12
|
+
|
13
|
+
it "converts an float correctly" do
|
14
|
+
"10.5".to_val.should == 10.5
|
15
|
+
end
|
16
|
+
|
17
|
+
it "converts a boolean correctly" do
|
18
|
+
"true".to_val.should == true
|
19
|
+
"false".to_val.should == false
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'converts null correctly' do
|
23
|
+
'null'.to_val.should == "null"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Basilik::Ref do
|
4
|
+
before :all do
|
5
|
+
@ref = Basilik::Load.new( ENV['fb_url'] )
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#child?' do
|
9
|
+
it "retrieves complex values correctly" do
|
10
|
+
@ref.set( a:{b:{c:1, d:"hello"}} )
|
11
|
+
@ref.child?( :a ).should == true
|
12
|
+
@ref.child?( 'a/b' ).should == true
|
13
|
+
@ref.child?( :z ).should == false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#children?' do
|
18
|
+
it "retrieves complex values correctly" do
|
19
|
+
@ref.set( a:{b:{c:1, d:"hello"}} )
|
20
|
+
@ref.child(:a).children?.should == true
|
21
|
+
@ref.child('a/b').children?.should == true
|
22
|
+
@ref.child( 'a/b/c' ).children?.should == false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#num_children' do
|
27
|
+
it "retrieves complex values correctly" do
|
28
|
+
@ref.set( a:{b:{c:1, d:"hello"}} )
|
29
|
+
@ref.child(:a).num_children.should == 1
|
30
|
+
@ref.child('a/b').num_children.should == 2
|
31
|
+
@ref.child( 'a/b/c' ).num_children.should == 0
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#val' do
|
36
|
+
it "retrieves simple value correctly" do
|
37
|
+
@ref.set( a:1 )
|
38
|
+
@ref.child( :a ).val.to_i.should == 1
|
39
|
+
end
|
40
|
+
|
41
|
+
it "retrieves complex values correctly" do
|
42
|
+
@ref.set( a:{b:{c:1, d:"hello"}} )
|
43
|
+
@ref.child( :a ).val.should == {b:{c:1, d:"hello"}}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#child' do
|
48
|
+
it "creates a child ref correctly" do
|
49
|
+
child_ref = @ref.child( 'fred')
|
50
|
+
child_ref.name.should == 'fred'
|
51
|
+
child_ref.parent.to_s.should == ENV['fb_url']
|
52
|
+
end
|
53
|
+
|
54
|
+
it "creates a deep child ref correctly" do
|
55
|
+
child_ref = @ref.child( 'fred/blee/duh')
|
56
|
+
child_ref.name.should == 'duh'
|
57
|
+
child_ref.parent.to_s.should == ENV['fb_url'] + '/fred/blee'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#name' do
|
62
|
+
it "identifies / as the root name correctly" do
|
63
|
+
@ref.name.should be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it "identifies a url name correctly" do
|
67
|
+
ref = Basilik::Load.new( ENV['fb_url'] + '/fred/blee' )
|
68
|
+
ref.name.should == 'blee'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#root' do
|
73
|
+
it "identifies / as root correctly" do
|
74
|
+
@ref.root.should == @ref
|
75
|
+
end
|
76
|
+
|
77
|
+
it "identifies non root url correctly" do
|
78
|
+
ref = Basilik::Load.new( ENV['fb_url'] + '/fred/blee' )
|
79
|
+
ref.root.to_s.should == ENV['fb_url']
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#root?' do
|
84
|
+
it "identifies root correctly" do
|
85
|
+
@ref.should be_root
|
86
|
+
end
|
87
|
+
|
88
|
+
it "identifies / as root correctly" do
|
89
|
+
ref = Basilik::Load.new( ENV['fb_url'] + '/' )
|
90
|
+
ref.should be_root
|
91
|
+
end
|
92
|
+
|
93
|
+
it "identifies non root correctly" do
|
94
|
+
ref = Basilik::Load.new( ENV['fb_url'] + '/fred' )
|
95
|
+
ref.should_not be_root
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '#parent' do
|
100
|
+
it "identifies parent from root correctly" do
|
101
|
+
@ref.parent.should be_nil
|
102
|
+
end
|
103
|
+
|
104
|
+
it "identifies a parent correctly" do
|
105
|
+
ref = Basilik::Load.new( ENV['fb_url'] + '/fred/blee' )
|
106
|
+
ref.parent.to_s.should == ENV['fb_url'] + '/fred'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|