basilik 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OTI5ZGFkMDRlODVlOTE1ODIyYmI1NmUxYWU2MDc5N2FmZjhlODlmMg==
5
+ data.tar.gz: !binary |-
6
+ NGU4M2EzNDU4M2ZkNjVlMzRlMzhhMTA3NGJmZTg1MWE5MThjYzc3MQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ZmNhOTE0Nzc0MGJiMDhhNzdkOTMzYjQ2ZDU4MmM4MzViODE2MjZhZjliZTY4
10
+ MTg0ZWZmYjU5YWFmY2Q5ZDYwZWVkMjIyNWVmNmQ2YjBjZDA5MmYzNGNlNmYw
11
+ NjU1YzcwNWNjOTVkZGE2YjAzMTE1MDY3Yjg0ZmNiZWJjODY4NmI=
12
+ data.tar.gz: !binary |-
13
+ ZTBjNzEyNWZiZWI1MDM0Nzg5YmVmNjk1YTIyZmM2OWE5YzY3ZjZhNGVhY2Jk
14
+ MDhjMDAwNDNhOTM5MjhhOGQ3OWNlZGU1NDVhZjEyZmE3Y2U2NzU5NmY3YTM4
15
+ ZTViMGVlOTYyOWRhZTRlZjYyZTAzYzVlMmJkNGJmYzBhNGNhMTk=
data/.autotest ADDED
@@ -0,0 +1 @@
1
+ require 'autotest/growl'
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ README.html
2
+ coverage
3
+ pkg
4
+ *.sh
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'map'
4
+ gem 'typhoeus'
5
+ gem 'values'
6
+
7
+ group 'test' do
8
+ gem "autotest"
9
+ gem "autotest-growl"
10
+ gem 'rspec'
11
+ gem 'simplecov'
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ ZenTest (4.9.0)
5
+ autotest (4.4.6)
6
+ ZenTest (>= 4.4.1)
7
+ autotest-growl (0.2.16)
8
+ diff-lcs (1.2.1)
9
+ ethon (0.5.10)
10
+ ffi (~> 1.3.0)
11
+ mime-types (~> 1.18)
12
+ ffi (1.3.1)
13
+ map (6.3.0)
14
+ mime-types (1.21)
15
+ multi_json (1.7.2)
16
+ rspec (2.13.0)
17
+ rspec-core (~> 2.13.0)
18
+ rspec-expectations (~> 2.13.0)
19
+ rspec-mocks (~> 2.13.0)
20
+ rspec-core (2.13.1)
21
+ rspec-expectations (2.13.0)
22
+ diff-lcs (>= 1.1.3, < 2.0)
23
+ rspec-mocks (2.13.0)
24
+ simplecov (0.7.1)
25
+ multi_json (~> 1.0)
26
+ simplecov-html (~> 0.7.1)
27
+ simplecov-html (0.7.1)
28
+ typhoeus (0.6.2)
29
+ ethon (~> 0.5.10)
30
+ values (1.5.0)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ autotest
37
+ autotest-growl
38
+ map
39
+ rspec
40
+ simplecov
41
+ typhoeus
42
+ values
data/README.md ADDED
@@ -0,0 +1,319 @@
1
+ # Basilik - Ruby firepower to your Firebase batteries
2
+
3
+ Firebase is a real-time backend that allows one to store key-value pairs in a hierarchical fashion, without
4
+ having to manage additional servers. Firebase offers api's for a variety of client libs such as javascript,
5
+ REST, IOS and now Ruby ;-). A cool thing about Firebase is that it broadcast changes to a variety of clients listening
6
+ on a given firebase and allows disparate client to share their data. Checkout http://firebase.com for the firehose...
7
+
8
+ ## Requirements
9
+
10
+ - Ruby >= 1.9
11
+ - Map
12
+ - Typhoeus
13
+
14
+ ## Getting Started
15
+
16
+ $ gem install basilik
17
+
18
+ ## Usage
19
+
20
+ ### Setup your Firebase
21
+
22
+ Sign up for a firebase account and create a new firebase of your liking.
23
+ In the following code samples, we will use the following as our base url:
24
+
25
+ + https://zerodarkthirty.firebaseio.com
26
+
27
+ Then you can specify an entry point into the data using the following call:
28
+
29
+ ```ruby
30
+ ref = Basilik::Load.new( 'https://zerodarkthirty.firebaseio.com' )
31
+ ```
32
+
33
+ NOTE: You don't have to start a the root, but usually a good idea since this api
34
+ offers ways to traverse the hierarchy up or down. But more on this later...
35
+
36
+
37
+ ### Populating firebase
38
+
39
+ Firebase supports the following data types:
40
+
41
+ + String
42
+ + Number
43
+ + Boolean
44
+ + Array
45
+ + Hash
46
+
47
+ #### Adding primitive types
48
+
49
+ ```ruby
50
+ data = {
51
+ a: 0,
52
+ b: %s(Hello World),
53
+ c: 10.5
54
+ }
55
+ ref.set( data )
56
+ ```
57
+
58
+ Yields:
59
+
60
+ + a:0
61
+ + b:"Hello World"
62
+ + c:10.5
63
+
64
+ NOTE: Set is a destructive operation and will replace the previous content for the reference it is
65
+ called from.
66
+
67
+ Thus
68
+
69
+ ```ruby
70
+ data = {
71
+ a: 0
72
+ }
73
+ ref.set( data )
74
+ ```
75
+
76
+ Yields
77
+ + a:0
78
+
79
+ Hence replacing the previously assigned content.
80
+
81
+
82
+ #### Adding arrays
83
+
84
+ ```ruby
85
+ ref.set( %w(Hello World) )
86
+ ```
87
+
88
+ Yields:
89
+
90
+ + 0:"Hello"
91
+ + 1:"World"
92
+
93
+
94
+ #### Adding arrays (ordered data)
95
+
96
+ The preferred method to construct lists in your firebase is to use the push operation, which
97
+ will automatically provide ordering to your list.
98
+
99
+ ```ruby
100
+ ref.push( "BumbleBee" )
101
+ ref.push( "Tuna" )
102
+ ```
103
+
104
+ Yields:
105
+
106
+ + -IrMr3Yp1mozVNzDePKy: "BumbleBee"
107
+ + -IrMr3cM6XjTpNebsYRh: "Tuna"
108
+
109
+ NOTE: The list indexes will be autogenerated by firebase to ensure correct ordering on retrieval.
110
+
111
+
112
+ #### Adding hashes
113
+
114
+ ```ruby
115
+ data = {
116
+ a: {
117
+ a_1: %s(Hello World),
118
+ a_2: 10.5
119
+ },
120
+ b: {
121
+ b_1: 10,
122
+ b_2: true
123
+ }
124
+ }
125
+ ref.set( data )
126
+ ```
127
+
128
+ Yields:
129
+
130
+ + a:
131
+ + a_1:"Hello World"
132
+ + a_2_:10.5
133
+ + b:
134
+ + b_1:10
135
+ + b_2:true
136
+
137
+
138
+ ### Reading data
139
+
140
+ Fetching data in the hierarchy is done via the read operation.
141
+
142
+ ```ruby
143
+ # Setup...
144
+ data = {
145
+ a: {
146
+ a_1: %s(Hello World),
147
+ a_2: 10.5
148
+ },
149
+ b: {
150
+ b_1: 10,
151
+ b_2: true
152
+ }
153
+ }
154
+ ref.set( data )
155
+ ```
156
+
157
+ ```ruby
158
+ ref.child( 'a/a_2' ).read # => 10.5
159
+ a_val = ref.child( :a ).read
160
+ a_val.a_1 # => 'Hello World'
161
+ a_val[:a_1] # => 'Hello World' or use hash indexing...
162
+ a_val.a_2 # => 10.5
163
+ ```
164
+
165
+ ### Updating data
166
+
167
+ You can use the #update on a reference to modify nodes in the hierarchy
168
+
169
+ ```ruby
170
+ # Setup...
171
+ data = {
172
+ a: {
173
+ a_1: %s(Hello World),
174
+ a_2: {
175
+ a_2_1: 10.5,
176
+ a_2_2: "Word!"
177
+ }
178
+ },
179
+ b: {
180
+ b_1: 10,
181
+ b_2: true
182
+ }
183
+ }
184
+ ref.set( data )
185
+ ```
186
+
187
+ ```ruby
188
+ ref.child( :a ).update( a_1:"BumbleBee Tuna" )
189
+ ref.child( 'a/a_2' ).update( a_2_2:"You bet!" )
190
+ ref.child( 'a' ).child( 'a_3' ).update( a_3_1:"You better!" )
191
+ ```
192
+
193
+ Yields:
194
+
195
+ + a
196
+ + a_1:"BumbleBee Tuna"
197
+ + a_2
198
+ + a_2_1: 10.5
199
+ + a_2_2: "You bet!"
200
+ + a_3
201
+ + a_3_1: "You better!"
202
+
203
+ Note: the last call inserts a branch new node in the hierarchy. We could have use set here as well to
204
+ perform the insert.
205
+
206
+ You can leverage #inc/#dec to increment/decrement counter like data.
207
+
208
+ IMPORTANT! Sadly Firebase currently does not offer transactions using their REST api, hence there is
209
+ no guarantees about the atomicity of read/write operations ;-(
210
+
211
+ ### Deleting data
212
+
213
+ Use the #remove operation to delete nodes at any level in the hierarchy.
214
+
215
+ ```ruby
216
+ # Setup...
217
+ data = {
218
+ a: {
219
+ a_1: %s(Hello World),
220
+ a_2: {
221
+ a_2_1: 10.5,
222
+ a_2_2: "Word!"
223
+ }
224
+ },
225
+ b: {
226
+ b_1: 10,
227
+ b_2: true
228
+ }
229
+ }
230
+ ref.set( data )
231
+ ref.child( 'a/a_2/a_2_2' ).remove
232
+ ref.child( :b ).remove
233
+ ```
234
+
235
+ NOTE: Calling remove on the root ref will delete the entire hierarchy.
236
+
237
+ ### Traversing the data
238
+
239
+ You can traverse the hierarchy using the #child or #parent. These calls can be chained.
240
+
241
+ ```ruby
242
+ data = {
243
+ a: {
244
+ a_1: %s(Hello World),
245
+ a_2: {
246
+ a_2_1: 10.5,
247
+ a_2_2: "Word!"
248
+ }
249
+ },
250
+ b: {
251
+ b_1: 10,
252
+ b_2: true
253
+ }
254
+ }
255
+ ref.set( data )
256
+ ```
257
+
258
+ ```ruby
259
+ a_2_2_ref = ref.child( 'a/a_2/a_2_2' )
260
+ a_2_2_ref = ref.child( :a ).child( :a_2 ).child( :a_2_2 ) # or...
261
+ a_2_2_ref.name #=> 'a_2_2'
262
+
263
+ a_2_ref = a_2_2_ref.parent
264
+ a_2_ref.name # => 'a_2'
265
+
266
+ a_ref = a_2_2_ref.parent.parent
267
+ a_ref.name # => 'a'
268
+ ```
269
+
270
+ ### Priorities
271
+
272
+ Firebase provides for setting priorities on ordered list in order to affect the retrieval. By default priority is null.
273
+ Setting priority affects the retrieval as follows (See firebase web site for details!):
274
+
275
+ + Children with no priority are retrieved first ordered lex asc by name
276
+ + Children with number priority are next, ordered lex asc priority, name
277
+ + Children with a non numeric priority come last, ordered lex asc priority, name
278
+
279
+ ```ruby
280
+ a_ref = ref.push( {a:1, b:2} )
281
+ b_ref = ref.push( {c:1, d:2} )
282
+ a_ref.set_priority( 20 )
283
+ b_ref.set_priority( 10 )
284
+ a_ref.parent.read #=> {-IrNhTASqxqEpNMw8NGq: {c: 1, d: 2}, -IrNhT2vsoQ1WlgSG6op: {a: 1, b: 2} }
285
+ ```
286
+
287
+ ### Auth and rules
288
+
289
+ You can secure you firebase store using a secret token and grant access for permissions on the store using rules.
290
+ Please refer to the firebase docs for details.
291
+
292
+ ```ruby
293
+ ref = Basilik::Load.new( 'https://bozo.firebaseio.com', my_secret_token )
294
+ ref.set( tmp: { a: 0, b: 1 } )
295
+ ref.set_rules(
296
+ { '.read' => true, '.write' => false,
297
+ "tmp" => { '.read' => true, '.write' => false }
298
+ }
299
+ )
300
+ res = ref.child(:tmp).read # => { a: 0, b: 1 }
301
+ ref.set( tmp: {d:0} ) } # => Basilik::Action::PermissionDeniedError
302
+ ```
303
+
304
+ ## Contact
305
+
306
+ Fernand Galiana
307
+
308
+ - http://github.com/derailed
309
+ - http://twitter.com/kitesurfer
310
+ - <fernand.galiana@gmail.com>
311
+
312
+ ## License
313
+
314
+ Basilik is released under the [MIT](http://opensource.org/licenses/MIT) license.
315
+
316
+
317
+ ## History
318
+ 0.0.1:
319
+ - Initial drop
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+
3
+ Bundler.require
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
8
+
9
+ require 'rspec/core/rake_task'
10
+ RSpec::Core::RakeTask.new(:spec) do |t|
11
+ t.verbose = false
12
+ t.ruby_opts = "-I./spec"
13
+ end
14
+
15
+ desc 'Cleanup build artifacts'
16
+ task :clean do
17
+ cov = File.expand_path( File.join( %w(.. coverage) ), __FILE__ )
18
+ FileUtils.rm_r( cov ) if File.exists?( cov )
19
+ end
20
+
21
+ task default: :spec
data/basilik.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "basilik/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "basilik"
7
+ s.version = Basilik::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+
10
+ s.authors = [
11
+ "Fernand Galiana"
12
+ ]
13
+
14
+ s.email = ["fernand.galiana@gmail.com"]
15
+ s.homepage = "https://github.com/derailed/basilik"
16
+ s.summary = %q{Ruby implementation of Firebase framework}
17
+ s.description = %q{Ruby implementation of Firebase framework}
18
+ s.rubyforge_project = "firebase"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+
25
+ s.add_dependency 'map' , '~> 6.3.0'
26
+ s.add_dependency 'typhoeus', '~> 0.6.2'
27
+ end
data/examples/a.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'basilik'
2
+
3
+ ref = Basilik::Load.new( ENV['fb_url'] )
4
+ ref.remove
5
+ data = {
6
+ a: 0,
7
+ b: %s(Hello World),
8
+ c: 10.5
9
+ }
10
+ ref.set( data )
data/examples/b.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'basilik'
2
+
3
+ ref = Basilik::Load.new( ENV['fb_url'] )
4
+ ref.remove
5
+ ref.set( %w(Hello World) )
data/examples/c.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'basilik'
2
+
3
+ ref = Basilik::Load.new( ENV['fb_url'] )
4
+ ref.remove
5
+ ref.push( "Bumblebee" )
6
+ ref.push( "Tuna" )
data/examples/d.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'basilik'
2
+
3
+ ref = Basilik::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 )
data/examples/e.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'basilik'
2
+
3
+ ref = Basilik::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 'basilik'
2
+
3
+ ref = Basilik::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 'basilik'
2
+
3
+ ref = Basilik::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 'basilik'
2
+
3
+ ref = Basilik::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 'basilik'
2
+
3
+ ref = Basilik::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
@@ -0,0 +1,10 @@
1
+ require 'basilik'
2
+ require 'yaml'
3
+
4
+ ref = Basilik::Load.new( ENV['fb_url'] )
5
+ ref.remove
6
+ a_ref = ref.push( {a:1, b:2} )
7
+ b_ref = ref.push( {c:1, d:2} )
8
+ a_ref.set_priority( 20 )
9
+ b_ref.set_priority( 10 )
10
+ puts "A", a_ref.parent.read.to_yaml