bigbertha 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/Gemfile +12 -0
- data/Gemfile.lock +42 -0
- data/README.md +322 -0
- data/Rakefile +21 -0
- data/bigbertha.gemspec +28 -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/bigbertha.rb +17 -0
- data/lib/bigbertha/action.rb +141 -0
- data/lib/bigbertha/core.rb +1 -0
- data/lib/bigbertha/core_ext/map.rb +23 -0
- data/lib/bigbertha/core_ext/string.rb +15 -0
- data/lib/bigbertha/faults.rb +9 -0
- data/lib/bigbertha/load.rb +22 -0
- data/lib/bigbertha/ref.rb +64 -0
- data/lib/bigbertha/snapshot.rb +99 -0
- data/lib/bigbertha/version.rb +3 -0
- data/spec/bigbertha/.firebase_spec.rb.swp +0 -0
- data/spec/bigbertha/core_ext/map_spec.rb +45 -0
- data/spec/bigbertha/core_ext/string_spec.rb +26 -0
- data/spec/bigbertha/ref_spec.rb +109 -0
- data/spec/bigbertha/root_spec.rb +301 -0
- data/spec/bigbertha/snapshot_spec.rb +174 -0
- data/spec/spec_helper.rb +10 -0
- metadata +104 -0
data/examples/b.rb
ADDED
data/examples/c.rb
ADDED
data/examples/d.rb
ADDED
data/examples/e.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bigbertha'
|
2
|
+
|
3
|
+
ref = Bigbertha::Load.new( ENV['fb_url'] )
|
4
|
+
ref.remove
|
5
|
+
data = {
|
6
|
+
a: {
|
7
|
+
a_1: %s(Hello World),
|
8
|
+
a_2: {
|
9
|
+
a_2_1: 10.5,
|
10
|
+
a_2_2: "Word!"
|
11
|
+
}
|
12
|
+
},
|
13
|
+
b: {
|
14
|
+
b_1: 10,
|
15
|
+
b_2: true
|
16
|
+
}
|
17
|
+
}
|
18
|
+
ref.set( data )
|
19
|
+
ref.child( :a ).update( a_1:"BumbleBee Tuna" )
|
20
|
+
ref.child( 'a/a_2' ).update( a_2_2:"You bet!" )
|
21
|
+
ref.child( 'a/a_3' ).update( a_3_1:"You bet!" )
|
data/examples/f.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bigbertha'
|
2
|
+
|
3
|
+
ref = Bigbertha::Load.new( ENV['fb_url'] )
|
4
|
+
ref.remove
|
5
|
+
data = {
|
6
|
+
a: {
|
7
|
+
a_1: %s(Hello World),
|
8
|
+
a_2: {
|
9
|
+
a_2_1: 10.5,
|
10
|
+
a_2_2: "Word!"
|
11
|
+
}
|
12
|
+
},
|
13
|
+
b: {
|
14
|
+
b_1: 10,
|
15
|
+
b_2: true
|
16
|
+
}
|
17
|
+
}
|
18
|
+
ref.set( data )
|
19
|
+
ref.child( 'a/a_2/a_2_2' ).remove
|
20
|
+
ref.child( :b ).remove
|
data/examples/g.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bigbertha'
|
2
|
+
|
3
|
+
ref = Bigbertha::Load.new( ENV['fb_url'] )
|
4
|
+
ref.remove
|
5
|
+
data = {
|
6
|
+
a: {
|
7
|
+
a_1: %s(Hello World),
|
8
|
+
a_2: {
|
9
|
+
a_2_1: 10.5,
|
10
|
+
a_2_2: "Word!"
|
11
|
+
}
|
12
|
+
},
|
13
|
+
b: {
|
14
|
+
b_1: 10,
|
15
|
+
b_2: true
|
16
|
+
}
|
17
|
+
}
|
18
|
+
ref.set( data )
|
19
|
+
ref.child( 'a/a_2/a_2_2' ).read
|
20
|
+
ref.child( :b ).remove
|
data/examples/h.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bigbertha'
|
2
|
+
|
3
|
+
ref = Bigbertha::Load.new( ENV['fb_url'] )
|
4
|
+
ref.remove
|
5
|
+
data = {
|
6
|
+
a: {
|
7
|
+
a_1: %s(Hello World),
|
8
|
+
a_2: 10.5
|
9
|
+
},
|
10
|
+
b: {
|
11
|
+
b_1: 10,
|
12
|
+
b_2: true
|
13
|
+
}
|
14
|
+
}
|
15
|
+
ref.set( data )
|
16
|
+
a_2_ref = ref.child( 'a/a_2' )
|
17
|
+
puts "A_2", a_2_ref.read
|
18
|
+
|
19
|
+
val = ref.child( :a ).read
|
20
|
+
puts val.class
|
21
|
+
puts "A_1", val.a_1, val[:a_1]
|
22
|
+
puts "A_2", val.a_2, val[:a_2]
|
data/examples/i.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'bigbertha'
|
2
|
+
|
3
|
+
ref = Bigbertha::Load.new( ENV['fb_url'] )
|
4
|
+
ref.remove
|
5
|
+
data = {
|
6
|
+
a: {
|
7
|
+
a_1: %s(Hello World),
|
8
|
+
a_2: {
|
9
|
+
a_2_1: 10.5,
|
10
|
+
a_2_2: "Word!"
|
11
|
+
}
|
12
|
+
},
|
13
|
+
b: {
|
14
|
+
b_1: 10,
|
15
|
+
b_2: true
|
16
|
+
}
|
17
|
+
}
|
18
|
+
ref.set( data )
|
19
|
+
a_2_2_ref = ref.child( 'a/a_2/a_2_2' )
|
20
|
+
a_2_ref = a_2_2_ref.parent
|
21
|
+
puts "A_2", a_2_ref.name, a_2_ref.read.inspect
|
22
|
+
a_ref = a_2_2_ref.parent.parent
|
23
|
+
puts "A", a_ref.name, a_ref.read.inspect
|
24
|
+
|
25
|
+
a_2_2_ref = ref.child( :a ).child( :a_2 ).child( :a_2_2 )
|
26
|
+
puts "A_2", a_2_ref.name, a_2_ref.read.inspect
|
data/examples/j.rb
ADDED
data/lib/bigbertha.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'typhoeus'
|
3
|
+
require 'map'
|
4
|
+
|
5
|
+
module Bigbertha
|
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
|
+
Bigbertha.require_all_libs_relative_to File.expand_path( "bigbertha", Bigbertha::LIBPATH )
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'bigbertha/faults'
|
2
|
+
|
3
|
+
module Bigbertha
|
4
|
+
module Action
|
5
|
+
include Bigbertha::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
|
+
Bigbertha::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
|
@@ -0,0 +1 @@
|
|
1
|
+
Bigbertha.require_all_libs_relative_to File.expand_path( File.join( %w(bigbertha core_ext), Bigbertha::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( Bigbertha::Load.evt_value, k )
|
14
|
+
else
|
15
|
+
events << Event.new( Bigbertha::Load.evt_child_removed, k )
|
16
|
+
end
|
17
|
+
else
|
18
|
+
events << Event.new( Bigbertha::Load.evt_child_added, k )
|
19
|
+
end
|
20
|
+
end
|
21
|
+
events
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Bigbertha
|
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
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bigbertha/ref'
|
2
|
+
|
3
|
+
module Bigbertha
|
4
|
+
class Load
|
5
|
+
include Bigbertha::Ref
|
6
|
+
include Bigbertha::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
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Bigbertha
|
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
|
+
Bigbertha::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
|
+
Bigbertha::Load.new( root.uri.merge(path).to_s )
|
26
|
+
end
|
27
|
+
|
28
|
+
def child( child_path )
|
29
|
+
Bigbertha::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
|