fogli 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +14 -0
- data/LICENSE +21 -0
- data/README.md +168 -0
- data/Rakefile +37 -0
- data/VERSION +1 -0
- data/examples/README.md +6 -0
- data/examples/me/README.md +18 -0
- data/examples/me/me.rb +30 -0
- data/lib/fogli.rb +46 -0
- data/lib/fogli/album.rb +8 -0
- data/lib/fogli/categorized_object.rb +9 -0
- data/lib/fogli/comment.rb +5 -0
- data/lib/fogli/event.rb +9 -0
- data/lib/fogli/exception.rb +15 -0
- data/lib/fogli/facebook_graph.rb +125 -0
- data/lib/fogli/facebook_object.rb +225 -0
- data/lib/fogli/facebook_object/connection_proxy.rb +80 -0
- data/lib/fogli/facebook_object/connection_scope.rb +123 -0
- data/lib/fogli/facebook_object/connections.rb +56 -0
- data/lib/fogli/facebook_object/properties.rb +81 -0
- data/lib/fogli/facebook_object/scope_methods.rb +49 -0
- data/lib/fogli/group.rb +8 -0
- data/lib/fogli/link.rb +8 -0
- data/lib/fogli/named_object.rb +8 -0
- data/lib/fogli/note.rb +7 -0
- data/lib/fogli/oauth.rb +167 -0
- data/lib/fogli/page.rb +15 -0
- data/lib/fogli/photo.rb +8 -0
- data/lib/fogli/post.rb +18 -0
- data/lib/fogli/status.rb +7 -0
- data/lib/fogli/user.rb +36 -0
- data/lib/fogli/util/module_attributes.rb +61 -0
- data/lib/fogli/util/options.rb +32 -0
- data/lib/fogli/video.rb +7 -0
- data/test/fogli/facebook_graph_test.rb +124 -0
- data/test/fogli/facebook_object/connection_proxy_test.rb +42 -0
- data/test/fogli/facebook_object/connection_scope_test.rb +91 -0
- data/test/fogli/facebook_object/connections_test.rb +50 -0
- data/test/fogli/facebook_object/properties_test.rb +79 -0
- data/test/fogli/facebook_object/scope_methods_test.rb +69 -0
- data/test/fogli/facebook_object_test.rb +178 -0
- data/test/fogli/oauth_test.rb +56 -0
- data/test/fogli/post_test.rb +18 -0
- data/test/fogli/user_test.rb +25 -0
- data/test/fogli/util/options_test.rb +38 -0
- data/test/fogli_test.rb +16 -0
- data/test/test_helper.rb +14 -0
- metadata +150 -0
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "rest-client", "~> 1.5.1"
|
4
|
+
gem "json_pure", "~> 1.2.0"
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem "sinatra" # for examples
|
8
|
+
|
9
|
+
gem "yard"
|
10
|
+
gem "bluecloth"
|
11
|
+
gem "contest", ">= 0.1.2"
|
12
|
+
gem "mocha"
|
13
|
+
gem "jeweler", "~> 1.4.0"
|
14
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2010 Mitchell Hashimoto
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# Fogli
|
2
|
+
|
3
|
+
Fogli is a **F**acebook **O**pen **G**raph **Li**brary.
|
4
|
+
|
5
|
+
## Why?
|
6
|
+
|
7
|
+
Facebook introduced the Graph API in April, 2010. This API is intended
|
8
|
+
to replace their existing "RESTful API" in the future. Mature Facebook
|
9
|
+
libraries such as [Facebooker](http://github.com/mmangino/facebooker) are
|
10
|
+
heavily tied to the RESTful API and have not started supporting the Open
|
11
|
+
Graph.
|
12
|
+
|
13
|
+
At the time of Fogli's creation, there were a handful of other libraries
|
14
|
+
claiming to be Facebook Graph libraries, but I found them unsatisfactory
|
15
|
+
since they did not meet any or all of the following requirements:
|
16
|
+
|
17
|
+
* Minimizes query calls
|
18
|
+
* Strong feature support
|
19
|
+
* Intuitive object model
|
20
|
+
* Independent library; not tied to any web framework
|
21
|
+
|
22
|
+
Fogli aims to expose the objects of the Facebook Graph through an intuitive
|
23
|
+
object oriented interface while minimizing the number of queries needed
|
24
|
+
to access data through lazy loading and caching. Fogli is not tied to any
|
25
|
+
web framework and can run standalone perfectly fine.
|
26
|
+
|
27
|
+
## Supported Features
|
28
|
+
|
29
|
+
Below is a list of supported Facebook Graph features:
|
30
|
+
|
31
|
+
* Authorization via OAuth
|
32
|
+
* Reading objects (`User`, `Page`, etc.)
|
33
|
+
* Reading object connections
|
34
|
+
* Deleting objects
|
35
|
+
* Scoping top level objects by `fields`
|
36
|
+
* Scoping connections by `limit`, `offset`, `since`, `until`, and `fields`
|
37
|
+
* Liking/unliking posts
|
38
|
+
|
39
|
+
The list below is a list of unsupported features, but development is
|
40
|
+
planned in the near future:
|
41
|
+
|
42
|
+
* More support for publishing (posting comments, attending events, etc.)
|
43
|
+
* Search
|
44
|
+
* Real time updates
|
45
|
+
* Analytics
|
46
|
+
|
47
|
+
Have a feature request? Submit it on the [GitHub Issues](https://github.com/mitchellh/fogli/issues)
|
48
|
+
page, or fork and send me a patch!
|
49
|
+
|
50
|
+
## Getting Started
|
51
|
+
|
52
|
+
Install Fogli:
|
53
|
+
|
54
|
+
gem install fogli
|
55
|
+
|
56
|
+
Next, you can do a few things:
|
57
|
+
|
58
|
+
* Open an IRB session and begin playing. Fogli isn't tied to any framework,
|
59
|
+
so you can see it work right away:
|
60
|
+
|
61
|
+
>> require "fogli"
|
62
|
+
>> m = Fogli::User["mitchellh"]
|
63
|
+
>> m.name
|
64
|
+
=> "Mitchell Hashimoto"
|
65
|
+
|
66
|
+
* Run the examples in the `examples/` directory to see how to access basic
|
67
|
+
connections and also use {Fogli::OAuth OAuth} to access authorized data.
|
68
|
+
|
69
|
+
* Read the documentation here! For more specific, class by class documentation,
|
70
|
+
please read [the source-generated documentation](http://mitchellh.github.com/fogli/).
|
71
|
+
|
72
|
+
## Reading Data and Accessing Connections
|
73
|
+
|
74
|
+
Reading public information is straightforward and requires no configuration:
|
75
|
+
|
76
|
+
u = Fogli::User["mitchellh"]
|
77
|
+
p u.first_name # "Mitchell"
|
78
|
+
p u.last_name # "Hashimoto"
|
79
|
+
|
80
|
+
Accessing connections (relationships to data) is also intuitive and
|
81
|
+
easy:
|
82
|
+
|
83
|
+
u.feed.each do |item|
|
84
|
+
p item
|
85
|
+
end
|
86
|
+
|
87
|
+
## Authentication, Authorization, and Accessing Private Data
|
88
|
+
|
89
|
+
To access private data, Facebook requires that the you gain an `access_token`
|
90
|
+
by asking the user to authorize your application. This is a two-step process.
|
91
|
+
The example before uses [Sinatra](http://www.sinatrarb.com/) with Fogli to
|
92
|
+
authorize a user and print his or her email:
|
93
|
+
|
94
|
+
# Set these configuration values. The keys are retrieved from
|
95
|
+
# registering an application with Facebook. These can all be
|
96
|
+
# set on the actual method calls later as well.
|
97
|
+
Fogli.client_id = "..."
|
98
|
+
Fogli.client_secret = "..."
|
99
|
+
Fogli.redirect_uri = "http://my-website.com/verify"
|
100
|
+
|
101
|
+
get "/" do
|
102
|
+
# Redirect the user to authorized, asking for email permissions
|
103
|
+
redirect Fogli::OAuth.authorize(:scope => "email")
|
104
|
+
end
|
105
|
+
|
106
|
+
get "/verify"
|
107
|
+
# Facebook redirects back to this page with a GET parameter `code`
|
108
|
+
# which is used to get the access token. This token should also be
|
109
|
+
# stored in a cookie or some session storage to be set on subsequent pages.
|
110
|
+
Fogli.access_token = Fogli::OAuth.access_token(:code => params[:code])
|
111
|
+
|
112
|
+
# Print authorized data to prove we're allowed!
|
113
|
+
Fogli::User[:me].email
|
114
|
+
end
|
115
|
+
|
116
|
+
Checking if a user is already authenciated is easy as well:
|
117
|
+
|
118
|
+
# Set from cookies, perhaps
|
119
|
+
Fogli.access_token = cookies[:access_token]
|
120
|
+
|
121
|
+
# Verify its valid
|
122
|
+
if Fogli::User.authorized?
|
123
|
+
# valid!
|
124
|
+
else
|
125
|
+
# reauthenticate
|
126
|
+
end
|
127
|
+
|
128
|
+
## Accessing Connections with Scopes
|
129
|
+
|
130
|
+
Facebook data connections are typically relationships to massive amounts
|
131
|
+
of data, most of which you're not interested in. By scoping the data, you
|
132
|
+
can limit the data to only what you want, and optimize the queries made by
|
133
|
+
Fogli in the process:
|
134
|
+
|
135
|
+
# Assuming we're authenticated (above)
|
136
|
+
u = Fogli::User[:me]
|
137
|
+
|
138
|
+
# We just want feed times since yesterday, and we're only interested
|
139
|
+
# in 10 of them:
|
140
|
+
u.feed.since("yesterday").limit(10).each do |item|
|
141
|
+
# Do something with the item
|
142
|
+
end
|
143
|
+
|
144
|
+
# Another example: We want to access all the user's friends, but only
|
145
|
+
# want their first and last name:
|
146
|
+
u.friends.fields(:first_name, :last_name).each do |friend|
|
147
|
+
p "Friend: #{friend.first_name} #{friend.last_name}"
|
148
|
+
end
|
149
|
+
|
150
|
+
## Lazy Loading and Caching
|
151
|
+
|
152
|
+
Everything in Fogli is lazy-loaded. This means that data is loaded on
|
153
|
+
demand and no queries are made until you need the data. So, how many
|
154
|
+
HTTP queries do you think `User[:me].feed.since("yesterday")` takes?
|
155
|
+
Since no property was ever access on the user, only 1 query is used
|
156
|
+
(to get the `feed` items since yesterday).
|
157
|
+
|
158
|
+
Additionally, once the data is loaded, it is cached to minimize the
|
159
|
+
number of queries needed:
|
160
|
+
|
161
|
+
# This is also only one query, the entire script, even though the
|
162
|
+
# items are accessed 4 times.
|
163
|
+
items = Fogli::User[:me].feed.since("yesterday")
|
164
|
+
items.each {}
|
165
|
+
items.each {}
|
166
|
+
items.each {}
|
167
|
+
items.each {}
|
168
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |gem|
|
6
|
+
gem.name = "fogli"
|
7
|
+
gem.summary = "An efficient, simple, and intuitive Facebook Open Graph library."
|
8
|
+
gem.description = "An efficient, simple, and intuitive Facebook Open Graph library."
|
9
|
+
gem.email = "mitchell.hashimoto@gmail.com"
|
10
|
+
gem.homepage = "http://github.com/mitchellh/fogli"
|
11
|
+
gem.authors = ["Mitchell Hashimoto"]
|
12
|
+
|
13
|
+
gem.add_dependency('rest-client', "~> 1.5.1")
|
14
|
+
gem.add_dependency('json_pure', "~> 1.2.0")
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
task :default => :test
|
22
|
+
|
23
|
+
Rake::TestTask.new do |t|
|
24
|
+
t.libs << "libs"
|
25
|
+
t.libs << "test"
|
26
|
+
t.pattern = 'test/**/*_test.rb'
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'yard'
|
31
|
+
YARD::Rake::YardocTask.new do |t|
|
32
|
+
t.options = ['--main', 'README.md', '--markup', 'markdown']
|
33
|
+
t.options += ['--title', 'Fogli Documentation']
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
puts "Yard not available. Install it with: gem install yard bluecloth"
|
37
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/examples/README.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Fogli "Me" Example
|
2
|
+
|
3
|
+
The "Me" example shows how to use Fogli to access data about the
|
4
|
+
`me` pseudo-user on Facebook which represents the currently authorized
|
5
|
+
user.
|
6
|
+
|
7
|
+
## Highlights
|
8
|
+
|
9
|
+
* OAuth authentication
|
10
|
+
* Accessing authorized data
|
11
|
+
|
12
|
+
## Running
|
13
|
+
|
14
|
+
To run the example, make sure you have [Sinatra](http://www.sinatrarb.com)
|
15
|
+
installed, then enter this directory and run the main file:
|
16
|
+
|
17
|
+
$ ruby me.rb
|
18
|
+
|
data/examples/me/me.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
|
4
|
+
# Make sure we load the most recent fogli that this is packaged with
|
5
|
+
# if its available.
|
6
|
+
$:.unshift(File.join(File.dirname(__FILE__), *%W[.. .. lib]))
|
7
|
+
require 'fogli'
|
8
|
+
|
9
|
+
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#
|
10
|
+
# IMPORTANT: Set your app configuration details here:
|
11
|
+
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#
|
12
|
+
Fogli.client_id = "132862110062471"
|
13
|
+
Fogli.client_secret = "3f2f371b6f01c449eb3bcfc841b1b9c1"
|
14
|
+
|
15
|
+
# No need to edit this:
|
16
|
+
Fogli.redirect_uri = "http://localhost:4567/verify"
|
17
|
+
|
18
|
+
get "/" do
|
19
|
+
# Authorize the user so we can get an access token
|
20
|
+
redirect Fogli::OAuth.authorize(:scope => "email")
|
21
|
+
end
|
22
|
+
|
23
|
+
get "/verify" do
|
24
|
+
# Get and store the access token, then print out their user
|
25
|
+
# information to verify it worked
|
26
|
+
Fogli.access_token = Fogli::OAuth.access_token(:code => params[:code])
|
27
|
+
|
28
|
+
# Output authorized information to verify it worked
|
29
|
+
Fogli::User[:me].email
|
30
|
+
end
|
data/lib/fogli.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Try to load the Rails ActiveSupport module accessors
|
2
|
+
# But fall back to our own if it doesn't exist.
|
3
|
+
begin
|
4
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
5
|
+
rescue LoadError
|
6
|
+
require 'fogli/util/module_attributes'
|
7
|
+
end
|
8
|
+
|
9
|
+
module Fogli
|
10
|
+
# The configuration options below only need to be set if you
|
11
|
+
# wish to retrieve authorized information via the Graph API.
|
12
|
+
# The configuration keys should be self explanatory.
|
13
|
+
mattr_accessor :client_id
|
14
|
+
mattr_accessor :client_secret
|
15
|
+
mattr_accessor :redirect_uri
|
16
|
+
mattr_accessor :access_token
|
17
|
+
|
18
|
+
# Logger. Set this to anything which has the same API as the Ruby
|
19
|
+
# standard library logger, or `nil` to disable logging (default)
|
20
|
+
mattr_accessor :logger
|
21
|
+
|
22
|
+
autoload :Exception, 'fogli/exception'
|
23
|
+
autoload :FacebookGraph, 'fogli/facebook_graph'
|
24
|
+
autoload :FacebookObject, 'fogli/facebook_object'
|
25
|
+
|
26
|
+
# User-friendly models
|
27
|
+
autoload :Album, 'fogli/album'
|
28
|
+
autoload :CategorizedObject, 'fogli/categorized_object'
|
29
|
+
autoload :Comment, 'fogli/comment'
|
30
|
+
autoload :Event, 'fogli/event'
|
31
|
+
autoload :Group, 'fogli/group'
|
32
|
+
autoload :Link, 'fogli/link'
|
33
|
+
autoload :NamedObject, 'fogli/named_object'
|
34
|
+
autoload :Note, 'fogli/note'
|
35
|
+
autoload :OAuth, 'fogli/oauth'
|
36
|
+
autoload :Page, 'fogli/page'
|
37
|
+
autoload :Photo, 'fogli/photo'
|
38
|
+
autoload :Post, 'fogli/post'
|
39
|
+
autoload :Status, 'fogli/status'
|
40
|
+
autoload :User, 'fogli/user'
|
41
|
+
autoload :Video, 'fogli/video'
|
42
|
+
|
43
|
+
module Util
|
44
|
+
autoload :Options, 'fogli/util/options'
|
45
|
+
end
|
46
|
+
end
|
data/lib/fogli/album.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
module Fogli
|
2
|
+
# A categorized object. In addition to simple objects such as
|
3
|
+
# {NamedObject}s, Facebook also has simple objects which only have a
|
4
|
+
# name and category in addition to an ID. This object represents
|
5
|
+
# such an object.
|
6
|
+
class CategorizedObject < NamedObject
|
7
|
+
property :category
|
8
|
+
end
|
9
|
+
end
|
data/lib/fogli/event.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
module Fogli
|
2
|
+
class Event < FacebookObject
|
3
|
+
property :owner, :name, :description, :start_time, :end_time, :location,
|
4
|
+
:venue, :privacy
|
5
|
+
|
6
|
+
connection :feed, :class => :Post
|
7
|
+
conncetion :noreply, :maybe, :invited, :attending, :declined, :class => :User
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Fogli
|
2
|
+
# An exception from a call to the Facebook Graph API. This will
|
3
|
+
# always contain the exception type and the message given.
|
4
|
+
class Exception < ::Exception
|
5
|
+
attr_reader :type
|
6
|
+
attr_reader :message
|
7
|
+
|
8
|
+
def initialize(type, message)
|
9
|
+
@type = type
|
10
|
+
@message = "[#{type}] #{message}"
|
11
|
+
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'restclient'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Fogli
|
6
|
+
# The most basic level access to the Facebook Graph. This class only
|
7
|
+
# has access to the `get`, `post`, etc. methods to query the
|
8
|
+
# Facebook Graph directly. This class is used by every other class
|
9
|
+
# to access the graph. This class also will automatically insert the
|
10
|
+
# Facebook `access_token` if it has been specified, and handles
|
11
|
+
# changing the HTTP method to HTTPS in that case.
|
12
|
+
#
|
13
|
+
# **Note:** Most users should never have to use this class
|
14
|
+
# directly. Instead, use one of the models, such as {User}, to
|
15
|
+
# access your data.
|
16
|
+
#
|
17
|
+
# # Requesting Data
|
18
|
+
#
|
19
|
+
# Getting data from the Facebook graph is simple:
|
20
|
+
#
|
21
|
+
# Fogli::FacebookGraph.get("/mitchellh")
|
22
|
+
#
|
23
|
+
# If you have an access token, {FacebookGraph} will add it to the
|
24
|
+
# query string without you having to do anything:
|
25
|
+
#
|
26
|
+
# Fogli.access_token = "..."
|
27
|
+
# Fogli::FacebookGraph.get("/me")
|
28
|
+
#
|
29
|
+
class FacebookGraph
|
30
|
+
GRAPH_DOMAIN = "graph.facebook.com"
|
31
|
+
|
32
|
+
class << self
|
33
|
+
# Override default HTTParty behavior to go through our request
|
34
|
+
# method to make sure that the access token is properly set if
|
35
|
+
# needed.
|
36
|
+
[:get, :post, :delete, :head].each do |method|
|
37
|
+
# A requester, where the arguments go through the {request}
|
38
|
+
# method, which handles automatically adding the
|
39
|
+
# {Fogli.access_token} if it is specified, and also handles
|
40
|
+
# the URL relative to the given path.
|
41
|
+
define_method(method) do |*args|
|
42
|
+
Fogli.logger.debug("Fogli #{method}: #{args.inspect}") if Fogli.logger
|
43
|
+
request(method, *args)
|
44
|
+
end
|
45
|
+
|
46
|
+
# A raw requester, which just directly requests with the given
|
47
|
+
# arguments.
|
48
|
+
define_method("raw_#{method}".to_sym) do |*args|
|
49
|
+
Fogli.logger.debug("Fogli raw #{method}: #{args.inspect}") if Fogli.logger
|
50
|
+
error_check { RestClient.send(method, *args) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Issues the specified request type with the given URL and
|
55
|
+
# options. This method will inject the Facebook `access_token`
|
56
|
+
# if it is available, and will properly change the method to
|
57
|
+
# "https" if needed.
|
58
|
+
def request(type, url, params=nil)
|
59
|
+
params ||= {}
|
60
|
+
|
61
|
+
if Fogli.access_token
|
62
|
+
params ||= {}
|
63
|
+
params.merge!(:access_token => Fogli.access_token)
|
64
|
+
end
|
65
|
+
|
66
|
+
method = "http"
|
67
|
+
method = "https" if params[:access_token]
|
68
|
+
|
69
|
+
url = "#{method}://#{GRAPH_DOMAIN}#{url}"
|
70
|
+
if !params.empty? && [:get, :delete].include?(type)
|
71
|
+
# For GET and DELETE, we're responsible for appending any
|
72
|
+
# query parameters onto the end of the URL
|
73
|
+
params = params.inject([]) do |acc, data|
|
74
|
+
k, v = data
|
75
|
+
acc << "#{k}=#{CGI.escape(v.to_s)}"
|
76
|
+
acc
|
77
|
+
end
|
78
|
+
|
79
|
+
url += "?#{params.join("&")}"
|
80
|
+
params = {}
|
81
|
+
end
|
82
|
+
|
83
|
+
error_check { RestClient.send(type, url, params) }
|
84
|
+
end
|
85
|
+
|
86
|
+
# Yields a block, checking for any errors in a request. If no
|
87
|
+
# errors are detected, decodes JSON and returns the result.
|
88
|
+
def error_check
|
89
|
+
response = begin
|
90
|
+
yield
|
91
|
+
rescue RestClient::Exception => e
|
92
|
+
e.response
|
93
|
+
end
|
94
|
+
|
95
|
+
data = parse_response(response)
|
96
|
+
if data.is_a?(Hash) && data["error"]
|
97
|
+
data = data["error"]
|
98
|
+
raise Exception.new(data["type"], data["message"])
|
99
|
+
elsif response.code.to_i == 500
|
100
|
+
raise Exception.new("Unknown", "Internal server error")
|
101
|
+
end
|
102
|
+
|
103
|
+
data
|
104
|
+
rescue NoMethodError
|
105
|
+
data
|
106
|
+
end
|
107
|
+
|
108
|
+
# Parses a response depending on the content type it sent back.
|
109
|
+
def parse_response(response)
|
110
|
+
type = response.headers[:content_type]
|
111
|
+
return response.body if type.include?("text/plain")
|
112
|
+
return JSON.parse(response.body)
|
113
|
+
rescue JSON::ParserError
|
114
|
+
response.body
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Shortcut methods to access the class-level methods.
|
119
|
+
[:get, :post, :delete, :head].each do |method|
|
120
|
+
define_method(method) do |*args|
|
121
|
+
self.class.send(method, *args)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|