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 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