Skip to content

Commit

Permalink
Merge pull request #10 from Fullscreen/add-facebook
Browse files Browse the repository at this point in the history
Add facebook
  • Loading branch information
jcohenho committed Aug 5, 2015
2 parents 926072c + aadc3e6 commit ca44424
Show file tree
Hide file tree
Showing 15 changed files with 296 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ If it does, then replace your calls to `followers_count` with `follower_count` (
## 0.2.1 - 2014-10-20

* [ENHANCEMENT] Requiring 'net' auto-loads Net::Twitter and Net::Instagram

## 0.2.2 - 2015-08-04

* [FEATURE] Add `Facebook::Page` supporting `find_by` and `find_by!`.
64 changes: 63 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Net - a Ruby client for social networks API
===========================================

Net helps you write apps that need to interact with Twitter and Instagram.
Net helps you write apps that need to interact with Twitter, Instagram and Facebook.


After [configuring your Twitter app](#configuring-your-twitter-app), you can run commands like:
Expand All @@ -19,6 +19,14 @@ user.username #=> "fullscreen_inc"
user.follower_count #=> 7025
```

After [configuring your Facebook app](#configuring-your-facebook-app), you can run commands like:

```ruby
page = Net::Facebook::Page.find_by username: 'fullscreeninc'
page.username #=> "fullscreeninc"
page.likes #=> 30094
```

How to install
==============

Expand Down Expand Up @@ -73,6 +81,21 @@ user.follower_count #=> 7025

*The methods above require a configured Instagram app (see below).*

Net::Facebook::Page
--------------------

Use [Net::Facebook::Page]() to:

* retrieve a Facebook page by username
* access the number of likes of a Facebook user

```ruby
page = Net::Facebook::Page.find_by username: 'fullscreeninc'
page.likes #=> 7025
```

*The methods above require a configured Facebook app (see below).*

Configuring your Twitter app
============================

Expand Down Expand Up @@ -147,6 +170,45 @@ end
so use the approach that you prefer.
If a variable is set in both places, then `Net::Instagram.configure` takes precedence.

Configuring your Facebook app
============================

In order to use Net you must create an app in the [Facebook Application Manager](https://developers.facebook.com/apps/).

Once the app is created, copy the API key and secret and add them to your
code with the following snippet of code (replacing with your own key and secret)
:

```ruby
Net::Facebook.configure do |config|
config.client_id = 'abcdefg'
config.client_secret = 'abcdefg'
end
```

Configuring with environment variables
--------------------------------------

As an alternative to the approach above, you can configure your app with
variables. Setting the following environment variables:

```bash
export FACEBOOK_CLIENT_ID='abcd'
export FACEBOOK_CLIENT_SECRET='efgh'
```

is equivalent to configuring your app with the initializer:

```ruby
Net::Facebook.configure do |config|
config.client_id = 'abcd'
config.client_secret = 'efgh'
end
```

so use the approach that you prefer.
If a variable is set in both places, then `Net::Facebook.configure` takes precedence.

How to test
===========

Expand Down
1 change: 1 addition & 0 deletions lib/net.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "net/version"
require "net/twitter"
require "net/instagram"
require "net/facebook"

module Net
end
11 changes: 11 additions & 0 deletions lib/net/facebook.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'net/facebook/config'
require 'net/facebook/models'
require 'net/facebook/errors'

module Net
module Facebook
extend Config
include Errors
include Models
end
end
14 changes: 14 additions & 0 deletions lib/net/facebook/api/configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Net
module Facebook
module Api
class Configuration
attr_accessor :client_id, :client_secret

def initialize
@client_id = ENV['FACEBOOK_CLIENT_ID']
@client_secret = ENV['FACEBOOK_CLIENT_SECRET']
end
end
end
end
end
60 changes: 60 additions & 0 deletions lib/net/facebook/api/request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require 'net/facebook/errors/response_error'
require 'active_support'
require 'active_support/core_ext'

module Net
module Facebook
module Api
class Request
def initialize(attrs = {})
@host = 'graph.facebook.com'
@query = attrs[:params] if attrs[:params]
@path = attrs.fetch :path, "/v2.3/#{@query}"
@method = attrs.fetch :method, :get
end

def run
case response = run_http_request
when Net::HTTPOK
JSON.parse(response.body)
else
raise Errors::ResponseError, response
end
end

private
def run_http_request
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request http_request
end
end

def http_request
http_class = "Net::HTTP::#{@method.capitalize}".constantize
@http_request ||= http_class.new(uri.request_uri)
end

def uri
@uri ||= URI::HTTPS.build host: @host, path: @path, query: query
end

def query
{}.tap do |query|
query.merge! access_token: "#{Net::Facebook.configuration.client_id}|#{Net::Facebook.configuration.client_secret}"
end.to_param
end

def as_curl
'curl'.tap do |curl|
curl << " -X #{http_request.method}"
http_request.each_header do |name, value|
curl << %Q{ -H "#{name}: #{value}"}
end
curl << %Q{ -d '#{http_request.body}'} if http_request.body
curl << %Q{ "#{@uri.to_s}"}
end
end
end
end
end
end
16 changes: 16 additions & 0 deletions lib/net/facebook/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'net/facebook/api/configuration'

module Net
module Facebook
module Config
def configure
yield configuration if block_given?
end

def configuration
@configuration ||= Api::Configuration.new
end
end
end
end

2 changes: 2 additions & 0 deletions lib/net/facebook/errors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require 'net/facebook/errors/response_error'
require 'net/facebook/errors/unknown_user'
14 changes: 14 additions & 0 deletions lib/net/facebook/errors/response_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Net
module Facebook
module Errors
class ResponseError < StandardError
attr_reader :response

def initialize(response = {})
@response = response
super response
end
end
end
end
end
11 changes: 11 additions & 0 deletions lib/net/facebook/errors/unknown_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Net
module Facebook
module Errors
class UnknownUser < StandardError
def message
'Unknown user'
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/net/facebook/models.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'net/facebook/models/page'
55 changes: 55 additions & 0 deletions lib/net/facebook/models/page.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require 'net/facebook/api/request'
require 'net/facebook/errors'

module Net
module Facebook
module Models
class Page
attr_reader :username, :likes

def initialize(attrs = {})
@username = attrs['username']
@likes = attrs['likes']
end


# Returns the existing Facebook page matching the provided attributes or
# nil when the page is not found.
#
# @return [Net::Facebook::Models::Page] the Facebook page.
# @ return [nil] when the page cannot be found.
# @param [Hash] params the attributes to find a page by.
# @option params [String] :username The Facebook page’s username
# (case-insensitive).
def self.find_by(params = {})
find_by! params
rescue Errors::UnknownUser
nil
end

# Returns the existing Facebook page matching the provided attributes or
# raises an error when the page is not found.
#
# @return [Net::Facebook::Models::Page] the Facebook page.
# @param [Hash] params the attributes to find a page by.
# @option params [String] :username The Facebook page’s username
# (case-insensitive).
# @raise [Net::Errors::UnknownUser] if the page cannot be found.
def self.find_by!(params = {})
find_by_username! params[:username]
end

private

def self.find_by_username!(username)
request = Api::Request.new params: username
new request.run
rescue Errors::ResponseError => error
case error.response
when Net::HTTPNotFound then raise Errors::UnknownUser
end
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/net/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Net
VERSION = "0.2.1"
VERSION = "0.2.2"
end
42 changes: 42 additions & 0 deletions spec/net/facebook/models/pages_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'spec_helper'

describe Net::Facebook::Page do
let(:unknown_username) { 'qeqwe09qlkmhkjh' }
let(:existing_username) { 'Fullscreeninc' }

describe '.find_by' do
subject(:page) { Net::Facebook::Page.find_by username: username }

context 'given an existing (case-insensitive) username' do
let (:username) { existing_username }

it 'returns an object representing the page for that user' do
expect(page.username).to eq 'fullscreeninc'
expect(page.likes).to be_an Integer
end
end

context 'given an unknown username' do
let(:username) { unknown_username }
it { expect(page).to be_nil }
end
end

describe '.find_by!' do
subject(:page) { Net::Facebook::Page.find_by! username: username }

context 'given an existing (case-insensitive) username' do
let(:username) { existing_username }

it 'returns an object representing the page for that user' do
expect(page.username).to eq 'fullscreeninc'
expect(page.likes).to be_an Integer
end
end

context 'given an unknown username' do
let(:username) { unknown_username }
it { expect{page}.to raise_error Net::Facebook::UnknownUser }
end
end
end
1 change: 1 addition & 0 deletions spec/support/vcr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
interaction.response.headers['X-Rate-Limit-Reset'].first
end
end
c.ignore_hosts 'graph.facebook.com'
end

0 comments on commit ca44424

Please sign in to comment.