fogli 0.1.0
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.
- 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
|