rest-firebase 0.9.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e5623f3812406296167b73e1b26510a060043d0b
4
- data.tar.gz: 45ddc73ba69941f7d74cdb183b8af4d6784f59f0
3
+ metadata.gz: 38ac75dc25a2212b5493f30523502a0c524e5423
4
+ data.tar.gz: 194f4cafa79ce00c6d33dd9dbdf086ce0c30bda3
5
5
  SHA512:
6
- metadata.gz: ffac8d5aabfb1468a32a7410a495ca0cb4dc0f8b9055c8b498dc5b209d2bc2e5a33027b45b65a7bd6c3f400fc9c9086036d1f727cbf06dc4b458f53e13d7c8e3
7
- data.tar.gz: 11e4cf1a5b78c289e8ce5af68a47c90f19877c7fc9b04a566d28fe87e78e0a26068fcf54b38c35d3c128ad9c940d72ae824805fa1ad845afd148adc2b98407a3
6
+ metadata.gz: 9e9dfc59ecf61bcdd560d72bfe851464f3a183bc514a98b1c5464d58f013cac9d2de2404be278005ed33f821f5becfd4a38984187fbfa83de96d95619ed04a53
7
+ data.tar.gz: 502858f091acd477c0e6ad2ed4c142845899ddaa8b16686ef2df5ff4e2134966bf7a54d3fd8c3e43b16a7f7bbfbc6c039a57d18d39ec66e235e01634195ab9e2
data/CHANGES.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGES
2
2
 
3
+ ## rest-firebase 0.9.1 -- 2014-06-28
4
+
5
+ * Now it would properly send JSON payload and headers.
6
+
3
7
  ## rest-firebase 0.9.0 -- 2014-05-13
4
8
 
5
9
  * Birthday!
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ $LOAD_PATH.unshift(File.expand_path("#{dir}/rest-core/lib"))
10
10
 
11
11
  Gemgem.init(dir) do |s|
12
12
  s.name = 'rest-firebase'
13
- s.version = '0.9.0'
13
+ s.version = '0.9.1'
14
14
  s.homepage = 'https://github.com/CodementorIO/rest-firebase'
15
15
 
16
16
  s.authors = ['Codementor', 'Lin Jen-Shin (godfat)']
data/doc/intro.md ADDED
@@ -0,0 +1,150 @@
1
+
2
+ # Codementor introduces you a new Firebase client for Ruby
3
+
4
+ ## Why we pick Firebase
5
+
6
+ Here at Codementor we implemented all the realtime facilities with
7
+ [Firebase][], which is a great tool and service for realtime communication,
8
+ especially for their JavaScript library which could handle all those edge
9
+ cases like whenever the clients disconnected unexpectedly, how we could
10
+ process the data offline and when we have a chance to reconnect, reconnect
11
+ and resend the offline data, etc, which are definitely common enough and we
12
+ shall not ignore them.
13
+
14
+ [Firebase]: https://www.firebase.com/
15
+
16
+ ## Why we need a Firebase client for Ruby
17
+
18
+ However, our server is written in Ruby, and we definitely need someway to let
19
+ the server communicate with the clients (browsers). For example, whenever
20
+ we want to programmatically broadcast some messages to certain users, it
21
+ would be much easier to do this from the server. Picking a Firebase client
22
+ for Ruby would be the most straightforward choice.
23
+
24
+ ## Existing Firebase client for Ruby did not fit our need
25
+
26
+ Unfortunately, eventually we realized that the existing Firebase client for
27
+ Ruby, namely [firebase-ruby][], did not fit our need. The main reason is that
28
+ it did not support the [streaming feature from Firebase][streaming], which is
29
+ extremely important whenever we want the clients periodically notify the
30
+ server, (e.g. online presence) since the server needs to know the status in
31
+ order to do some other stuffs underneath in realtime. We could probably
32
+ implement this on our server, but why not just use Firebase whenever it's
33
+ already implemented, and we're using it?
34
+
35
+ [firebase-ruby]: https://github.com/oscardelben/firebase-ruby
36
+ [streaming]: https://www.firebase.com/docs/rest-api.html#streaming-from-the-rest-api
37
+
38
+ ## [rest-firebase][]
39
+
40
+ Therefore we implemented our own Firebase client for Ruby, that is
41
+ [rest-firebase][]. It was built on top of [rest-core][], thus it has all
42
+ the advantages from rest-core, just like firebase-ruby was built on top
43
+ of [typhoeus][]. The highlights for rest-firebase are:
44
+
45
+ * Concurrent/asynchronous requests
46
+ * Streaming requests
47
+ * Generate Firebase JWT for you (auto-refresh is WIP)
48
+
49
+ [rest-firebase]: https://github.com/CodementorIO/rest-firebase
50
+ [rest-core]: https://github.com/godfat/rest-core
51
+ [typhoeus]: https://github.com/typhoeus/typhoeus
52
+
53
+ ### Concurrent/asynchronous requests
54
+
55
+ At times we want to notify two users at the same time, instead of preparing
56
+ two requests and wait for two requests to be done, we could simply do this:
57
+ (not a working example, just try to demonstrate, see [README.md][] for
58
+ working example)
59
+
60
+ ``` ruby
61
+ f = RestFirebase.new
62
+ f.put("users/#{a.id}", :message => 'Hi')
63
+ f.put("users/#{b.id}", :message => 'Oh')
64
+ ```
65
+
66
+ All requests are non-blocking, and it would only block when we try to look at
67
+ the response. Therefore the above requests would be processed concurrently and
68
+ asynchronously. To learn more about this, check [Concurrent HTTP Requests][].
69
+
70
+ Also, consequently, if you're not waiting for the requests to be done
71
+ somewhere, you might want to wait `at_exit` to make sure all
72
+ requests are properly done like this:
73
+
74
+ ``` ruby
75
+ at_exit do
76
+ RestFirebase.shutdown
77
+ end
78
+ ```
79
+
80
+ Which would also shutdown the [thread pool][] if you're using it.
81
+
82
+ [README.md]: https://github.com/CodementorIO/rest-firebase/blob/master/README.md
83
+ [Concurrent HTTP Requests]: https://github.com/CodementorIO/rest-firebase/blob/master/README.md#concurrent-http-requests
84
+ [thread pool]: https://github.com/godfat/rest-core#thread-pool--connection-pool
85
+
86
+ ### Streaming requests
87
+
88
+ To receive the online presence events, we have a specialized daemon to listen
89
+ on the presence node from Firebase. Something like below:
90
+
91
+ ``` ruby
92
+ es = RestFirebase.new.event_source('presence')
93
+ es.onerror do |error|
94
+ Codementor.handle_error(error) unless error.kind_of?(EOFError)
95
+ end
96
+
97
+ es.onreconnect do
98
+ firebase.auth = nil # refresh auth
99
+ !!@start # don't reconnect if we're closing
100
+ end
101
+
102
+ es.onmessage do |event, data|
103
+ next unless event == 'put'
104
+ next unless username = data['path'][%r{^/(\w+)/web$}, 1]
105
+ onpresence(username, data['data'])
106
+ end
107
+
108
+ es.start
109
+ sleep(1) while @start
110
+
111
+ es.close
112
+ ```
113
+
114
+ `onpresence` is the one doing our business logic.
115
+
116
+ ### Generate Firebase JWT for you (auto-refresh is WIP)
117
+
118
+ We could use Firebase JWT instead of our secret in order to make authorized
119
+ requests. This would be much secure than simply use the secret, which would
120
+ never expire unless we explicitly ask for. Checkout
121
+ [Authenticating Your Server][] for more detail. [rest-firebase][] could
122
+ generate one for you automatically by passing your secret to it like this:
123
+
124
+ ``` ruby
125
+ f = RestFirebase.new :secret => 'secret',
126
+ :d => {:auth_data => 'something'}
127
+ f.get('presence') # => attach JWT for auth in the request automatically
128
+ f.auth # => the JWT
129
+ f.auth = nil # => remove old JWT
130
+ f.auth # => generate a fresh new JWT
131
+ ```
132
+
133
+ Read the above document for what `:d` means here. Note that this JWT
134
+ would expire after 24 hours. Every time you initialize a new `RestFirebase`
135
+ it would generate a fresh new JWT, but if you want to keep using the same
136
+ instance, you would probably need to refresh the JWT by yourselves, just like
137
+ what we did when we tried to reconnect it in the streaming example.
138
+
139
+ [Authenticating Your Server]: https://www.firebase.com/docs/security/custom-login.html#authenticating-your-server
140
+
141
+ ## Summary
142
+
143
+ In order to take the full advantage of using Firebase with Ruby, we introduce
144
+ you [rest-firebase][], which highlights:
145
+
146
+ * Concurrent/asynchronous requests
147
+ * Streaming requests
148
+ * Generate Firebase JWT for you (auto-refresh is WIP)
149
+
150
+ Please feel free to try it and use it. It's released under Apache License 2.0.
data/lib/rest-firebase.rb CHANGED
@@ -7,7 +7,8 @@ RestFirebase = RC::Builder.client(:d, :secret, :auth) do
7
7
  use RC::Timeout , 10
8
8
 
9
9
  use RC::DefaultSite , 'https://SampleChat.firebaseIO-demo.com/'
10
- use RC::DefaultHeaders, {'Accept' => 'application/json'}
10
+ use RC::DefaultHeaders, {'Accept' => 'application/json',
11
+ 'Content-Type' => 'application/json'}
11
12
  use RC::DefaultQuery , nil
12
13
 
13
14
  use RC::FollowRedirect, 1
@@ -74,9 +75,14 @@ module RestFirebase::Client
74
75
  end
75
76
 
76
77
  def request env, app=app
77
- super(env.merge(REQUEST_PATH => "#{env[REQUEST_PATH]}.json",
78
- REQUEST_PAYLOAD => Json.encode(env[REQUEST_PAYLOAD])),
79
- app)
78
+ path = "#{env[REQUEST_PATH]}.json"
79
+ payload = if env[REQUEST_PAYLOAD]
80
+ {REQUEST_PAYLOAD => Json.encode(env[REQUEST_PAYLOAD])}
81
+ else
82
+ {}
83
+ end
84
+
85
+ super(env.merge(REQUEST_PATH => path).merge(payload), app)
80
86
  end
81
87
 
82
88
  def generate_auth opts={}
@@ -1,16 +1,16 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: rest-firebase 0.9.0 ruby lib
2
+ # stub: rest-firebase 0.9.1 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "rest-firebase"
6
- s.version = "0.9.0"
6
+ s.version = "0.9.1"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib"]
10
10
  s.authors = [
11
11
  "Codementor",
12
12
  "Lin Jen-Shin (godfat)"]
13
- s.date = "2014-05-13"
13
+ s.date = "2014-06-28"
14
14
  s.description = "Ruby Firebase REST API client built on top of [rest-core][].\n\n[rest-core]: https://github.com/godfat/rest-core"
15
15
  s.email = ["help@codementor.io"]
16
16
  s.files = [
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  "README.md",
24
24
  "Rakefile",
25
25
  "TODO.md",
26
+ "doc/intro.md",
26
27
  "lib/rest-firebase.rb",
27
28
  "rest-firebase.gemspec",
28
29
  "task/README.md",
data/test/test_api.rb CHANGED
@@ -14,6 +14,9 @@ describe RestFirebase do
14
14
 
15
15
  path = 'https://a.json?auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9%0A.eyJ2IjowLCJpYXQiOjAsImQiOm51bGx9%0A.C9JtzZhiCrsClNdAQcE7Irngr2BZJCH4x1p-IHxfrAo%3D%0A'
16
16
 
17
+ json = '{"status":"ok"}'
18
+ rbon = {'status' => 'ok'}
19
+
17
20
  def firebase
18
21
  RestFirebase.new(:secret => 'nnf')
19
22
  end
@@ -24,12 +27,15 @@ describe RestFirebase do
24
27
  end
25
28
 
26
29
  should 'put {"status":"ok"}' do
27
- json = '{"status":"ok"}'
28
- rbon = {'status' => 'ok'}
29
30
  stub_request(:put, path).with(:body => json).to_return(:body => json)
30
31
  firebase.put('https://a', rbon).should.eq rbon
31
32
  end
32
33
 
34
+ should 'have no payload for delete' do
35
+ stub_request(:delete, path).with(:body => nil).to_return(:body => json)
36
+ firebase.delete('https://a').should.eq rbon
37
+ end
38
+
33
39
  should 'parse event source' do
34
40
  stub_request(:get, path).to_return(:body => <<-SSE)
35
41
  event: put
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest-firebase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Codementor
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-13 00:00:00.000000000 Z
12
+ date: 2014-06-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-core
@@ -44,6 +44,7 @@ files:
44
44
  - README.md
45
45
  - Rakefile
46
46
  - TODO.md
47
+ - doc/intro.md
47
48
  - lib/rest-firebase.rb
48
49
  - rest-firebase.gemspec
49
50
  - task/README.md