Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructuring the Gem #85

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.3.8
* Major version change as new class added to handle request.
* Classes separated in different files.
* Syntax for Hashes changed from hashrockets to symbol.
* Alias for request methods defined to match HTTP methods
* New class Database defined so that other Firebase services can be added in future and make Client deprecated.
* Rubocop fixes.

## 0.2.8

* Fix [auth token expiration](https://github.com/oscardelben/firebase-ruby/pull/84) on longer lived Firebase objects.
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ gem install firebase
```ruby
base_uri = 'https://<your-firebase>.firebaseio.com/'

firebase = Firebase::Database.new(base_uri)

or

firebase = Firebase::Client.new(base_uri)

response = firebase.push("todos", { :name => 'Pick the milk', :'.priority' => 1 })
Expand Down Expand Up @@ -74,10 +78,20 @@ firebase.update('', {
So far, supported methods are:

```ruby
set(path, data, query_options)
get(path, query_options)

set(path, data, query_options)
or
put(path, data, query_options)

push(path, data, query_options)
or
post(path, data, query_options)

delete(path, query_options)
or
destroy(path, query_options)

update(path, data, query_options)
```

Expand Down
48 changes: 19 additions & 29 deletions firebase.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,25 @@ lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'firebase/version'

Gem::Specification.new do |s|
s.name = "firebase"
s.version = Firebase::VERSION

s.require_paths = ["lib"]
s.authors = ["Oscar Del Ben", "Vincent Woo"]
s.date = "2018-01-28"
s.description = "Firebase wrapper for Ruby"
s.email = "info@oscardelben.com"
s.extra_rdoc_files = [
"CHANGELOG.md",
"LICENSE.txt",
"README.md"
]
s.files = [
"lib/firebase.rb",
"lib/firebase/response.rb",
"lib/firebase/server_value.rb",
"lib/firebase/version.rb"
]
s.homepage = "http://github.com/oscardelben/firebase-ruby"
s.licenses = ["MIT"]
s.summary = "Firebase wrapper for Ruby"
Gem::Specification.new do |spec|
spec.name = 'firebase'
spec.version = Firebase::VERSION
spec.require_paths = ['lib']
spec.authors = ['Oscar Del Ben', 'Vincent Woo', 'Edwin Rozario']
spec.description = 'Firebase wrapper for Ruby'
spec.email = 'info@oscardelben.com'
spec.extra_rdoc_files = %w[CHANGELOG.md LICENSE.txt README.md]
spec.files = `git ls-files lib/`.split($/)
spec.homepage = 'http://github.com/oscardelben/firebase-ruby'
spec.licenses = ['MIT']
spec.summary = 'Firebase wrapper for Ruby'

s.add_runtime_dependency 'httpclient', '>= 2.5.3'
s.add_runtime_dependency 'json'
s.add_runtime_dependency 'googleauth'
s.add_development_dependency 'rake'
s.add_development_dependency 'rdoc'
s.add_development_dependency 'rspec'
spec.add_runtime_dependency 'httpclient', '>= 2.5.3'
spec.add_runtime_dependency 'json'
spec.add_runtime_dependency 'googleauth'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rdoc'
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'pry'
end

99 changes: 8 additions & 91 deletions lib/firebase.rb
Original file line number Diff line number Diff line change
@@ -1,94 +1,11 @@
# frozen_string_literal: true

require 'firebase/response'
require 'firebase/request'
require 'firebase/server_value'
require 'googleauth'
require 'httpclient'
require 'json'
require 'uri'

module Firebase
class Client
attr_reader :auth, :request

def initialize(base_uri, auth=nil)
if base_uri !~ URI::regexp(%w(https))
raise ArgumentError.new('base_uri must be a valid https uri')
end
base_uri += '/' unless base_uri.end_with?('/')
@request = HTTPClient.new({
:base_url => base_uri,
:default_header => {
'Content-Type' => 'application/json'
}
})
if auth && valid_json?(auth)
# Using Admin SDK service account
@credentials = Google::Auth::DefaultCredentials.make_creds(
json_key_io: StringIO.new(auth),
scope: %w(https://www.googleapis.com/auth/firebase.database https://www.googleapis.com/auth/userinfo.email)
)
@credentials.apply!(@request.default_header)
@expires_at = @credentials.issued_at + 0.95 * @credentials.expires_in
else
# Using deprecated Database Secret
@secret = auth
end
end

# Writes and returns the data
# Firebase.set('users/info', { 'name' => 'Oscar' }) => { 'name' => 'Oscar' }
def set(path, data, query={})
process :put, path, data, query
end

# Returns the data at path
def get(path, query={})
process :get, path, nil, query
end

# Writes the data, returns the key name of the data added
# Firebase.push('users', { 'age' => 18}) => {"name":"-INOQPH-aV_psbk3ZXEX"}
def push(path, data, query={})
process :post, path, data, query
end

# Deletes the data at path and returs true
def delete(path, query={})
process :delete, path, nil, query
end

# Write the data at path but does not delete ommited children. Returns the data
# Firebase.update('users/info', { 'name' => 'Oscar' }) => { 'name' => 'Oscar' }
def update(path, data, query={})
process :patch, path, data, query
end

private

def process(verb, path, data=nil, query={})
if path[0] == '/'
raise(ArgumentError.new("Invalid path: #{path}. Path must be relative"))
end

if @expires_at && Time.now > @expires_at
@credentials.refresh!
@credentials.apply! @request.default_header
@expires_at = @credentials.issued_at + 0.95 * @credentials.expires_in
end

Firebase::Response.new @request.request(verb, "#{path}.json", {
:body => (data && data.to_json),
:query => (@secret ? { :auth => @secret }.merge(query) : query),
:follow_redirect => true
})
end
require 'firebase/client'

def valid_json?(json)
begin
JSON.parse(json)
return true
rescue JSON::ParserError
return false
end
end
end
end
# Suggestion to slowly replace Client with Database
# So that we can have Firebase::Storeage, Firebase::RealtineDatabase
# in the future
Firebase::Database = Firebase::Client
47 changes: 47 additions & 0 deletions lib/firebase/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

module Firebase
# All Database interactions implemented here
class Client
attr_reader :request

def initialize(base_uri, auth = nil)
@request = Request.new(base_uri, auth)
end

# Writes and returns the data
# Firebase.set('users/info', { 'name' => 'Oscar' }) => { 'name' => 'Oscar' }
def set(path, data, query = {})
request.execute(:put, path, data, query)
end

# Returns the data at path
def get(path, query = {})
request.execute(:get, path, nil, query)
end

# Writes the data, returns the key name of the data added
# Firebase.push('users', { 'age' => 18}) => {"name":"-INOQPH-aV_psbk3ZXEX"}
def push(path, data, query = {})
request.execute(:post, path, data, query)
end

# Deletes the data at path and returs true
def delete(path, query = {})
request.execute(:delete, path, nil, query)
end

# Write the data at path but does not delete ommited
# children. Returns the data
# Firebase.update('users/info',
# { 'name' => 'Oscar' }) => { 'name' => 'Oscar' }
def update(path, data, query = {})
request.execute(:patch, path, data, query)
end

# Aliasing methods to match usual Ruby/Rails http methods
alias post push
alias put set
alias destroy delete
end
end
65 changes: 65 additions & 0 deletions lib/firebase/request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

require 'uri'
require 'httpclient'
require 'googleauth'
require 'json'

module Firebase
# API requests to firebase API implemented here
class Request
attr_reader :http_client, :auth

def initialize(uri, auth, headers = { 'Content-Type' => 'application/json' })
raise ArgumentError.new('base_uri must be a valid https uri') if uri !~ URI.regexp(%w(https))
uri += '/' unless uri.end_with?('/')

@http_client = HTTPClient.new(base_url: uri,
default_header: headers)

if valid_auth?(auth)
# Using Admin SDK private key
@credentials = Google::Auth::DefaultCredentials.make_creds(
json_key_io: StringIO.new(auth),
scope: %w(https://www.googleapis.com/auth/firebase.database https://www.googleapis.com/auth/userinfo.email)
)

@credentials.apply!(@http_client.default_header)
@expires_at = @credentials.issued_at + 0.95 * @credentials.expires_in
else
# Using deprecated Database Secret
@auth = auth
end
end

def execute(method, path, data = nil, query = {})
raise ArgumentError.new("Invalid path: #{path}. Path must be relative") if path.start_with? '/'

if @expires_at && Time.now > @expires_at
@credentials.refresh!
@credentials.apply! http_client.default_header
@expires_at = @credentials.issued_at + 0.95 * @credentials.expires_in
end

params = { body: (data && data.to_json),
query: (@auth ? { auth: @auth }.merge(query) : query),
follow_redirect: true }

http_call = http_client.request(method, "#{path}.json", params)
Firebase::Response.new(http_call)
end

private

def valid_auth?(auth)
return false unless auth

JSON.parse(auth)
return true
rescue TypeError
return false
rescue JSON::ParserError
return false
end
end
end
5 changes: 4 additions & 1 deletion lib/firebase/response.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# frozen_string_literal: true

module Firebase
# Firebase response class
class Response
attr_accessor :response

Expand All @@ -7,7 +10,7 @@ def initialize(response)
end

def body
JSON.parse(response.body, :quirks_mode => true)
JSON.parse(response.body, quirks_mode: true)
end

def raw_body
Expand Down
4 changes: 3 additions & 1 deletion lib/firebase/server_value.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

module Firebase
class ServerValue
TIMESTAMP = { ".sv" => 'timestamp' }
TIMESTAMP = { ".sv" => 'timestamp' }.freeze
end
end
4 changes: 3 additions & 1 deletion lib/firebase/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module Firebase
VERSION = '0.2.8'.freeze
VERSION = '0.3.8'.freeze
end
Loading