├── .bundle
└── config
├── .gitignore
├── .rspec
├── Gemfile
├── LICENSE
├── Manifest
├── README.textile
├── Rakefile
├── TODO.list
├── fbgraph.gemspec
├── lib
├── fbgraph.rb
└── fbgraph
│ ├── authorization.rb
│ ├── base.rb
│ ├── cacert.pem
│ ├── canvas.rb
│ ├── client.rb
│ ├── fql.rb
│ ├── logger.rb
│ ├── realtime.rb
│ ├── result.rb
│ ├── search.rb
│ ├── selection.rb
│ ├── timeline.rb
│ └── version.rb
└── spec
├── lib
└── fbauth
│ ├── authorization_spec.rb
│ ├── base_spec.rb
│ ├── canvas_spec.rb
│ ├── client_spec.rb
│ ├── realtime_spec.rb
│ ├── search_spec.rb
│ └── selection_spec.rb
├── spec_helper.rb
└── support
└── fbgraph_spec_helper.rb
/.bundle/config:
--------------------------------------------------------------------------------
1 | ---
2 | BUNDLE_DISABLE_SHARED_GEMS: '1'
3 | BUNDLE_PATH: vendor/bundler/
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Gemfile.lock
2 | *.log
3 | .DS_Store
4 | doc
5 | tmp
6 | pkg
7 | *.gem
8 | *.pid
9 | coverage
10 | coverage.data
11 | build/*
12 | *.pbxuser
13 | *.mode1v3
14 | .project
15 | .svn
16 | profile
17 | vendor/*
18 | gemspec/*
19 | .rvmrc
20 | .rbenv-version
21 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --format progress
3 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 20010-2012 Nicolas Santa
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/Manifest:
--------------------------------------------------------------------------------
1 | Manifest
2 | README
3 | README.textile
4 | Rakefile
5 | TODO.list
6 | fbgraph.gemspec
7 | lib/fbgraph.rb
8 | lib/fbgraph/authorization.rb
9 | lib/fbgraph/base.rb
10 | lib/fbgraph/canvas.rb
11 | lib/fbgraph/client.rb
12 | lib/fbgraph/realtime.rb
13 | lib/fbgraph/search.rb
14 | lib/fbgraph/selection.rb
15 | specs/lib/fbauth/authorization_spec.rb
16 | specs/lib/fbauth/base_spec.rb
17 | specs/lib/fbauth/client_spec.rb
18 | specs/lib/fbauth/realtime_spec.rb
19 | specs/lib/fbauth/search_spec.rb
20 | specs/lib/fbauth/selection_spec.rb
21 | specs/spec_helper.rb
22 |
--------------------------------------------------------------------------------
/README.textile:
--------------------------------------------------------------------------------
1 | h2. FBGRaph
2 |
3 | p. Facebook Open Graph API Gem for Rails 3.
4 |
5 |
6 | h2. Resources
7 |
8 | * "View RDoc on RDoc.info":http://rdoc.info/projects/nsanta/fbgraph
9 |
10 | * "View Source on GitHub":http://github.com/nsanta/fbgraph
11 |
12 | * "Report Issues on GitHub":http://github.com/nsanta/fbgraph/issues
13 |
14 |
15 | h2. Installation
16 |
17 | notextile. gem install fbgraph
18 |
19 | p. Be sure to require it
20 |
21 | notextile. require "fbgraph"
22 |
23 | p. or add this line into Gemfile for Rails 3
24 |
25 | notextile. gem "fbgraph"
26 |
27 |
28 | h2. Example Apps
29 |
30 | "Rails 3 Example":http://github.com/nsanta/fbgraph_example
31 |
32 | h2. Usage
33 |
34 | p. FBGraph supports most (no analytics yet) features of Facebook Open Graph API: developers.facebook.com/docs/reference/api/
35 |
36 | **IMPORTANT!!** Facebook object IDs can be very large numbers--too large to fit in a regular SQL "INTEGER" column. If you use an integer column, your database will likely just store the largest number allowed resulting in a bug that may confound you beyond belief.
37 |
38 | **IF YOU PLAN TO STORE FACEBOOK GRAPH OBJECT IDS IN YOUR DATABASE, YOU MUST USE A BIGINT COLUMN, NOT A STANDARD INTEGER COLUMN!**
39 |
40 | h3. Initialization
41 |
42 | p. Without a token (for authorization)
43 |
44 | notextile. client = FBGraph::Client.new(:client_id => 'client_id',:secret_id =>'secret_id')
45 |
46 | p. With a token
47 |
48 | notextile. client = FBGraph::Client.new(:client_id => 'client_id',:secret_id =>'secret_id' ,:token => token)
49 |
50 | p. All methods are chainable
51 |
52 | Examples:
53 |
54 | notextile. client.selection.me.photos.until(Time.now.to_s).since(3.days.ago).limit(10).info!
55 |
56 | notextile. client.selection.user('id').videos.offset(10).info!
57 |
58 | notextile. client.search.query('q').on('users').limit(20).info!
59 |
60 | h3. Rails config file
61 |
62 | h2. TODO
63 |
64 | h3. Authorization
65 |
66 | h4. client.authorization.authorize_url
67 |
68 | p. returns the authorize url
69 |
70 | notextile. redirect_to client.authorization.authorize_url(:redirect_uri => callback_url , :scope => 'email,user_photos,friends_photos')
71 |
72 | h4. client.authorization.process_callback
73 |
74 | p. process the callback and returns the access token
75 |
76 | notextile. access_token = client.authorization.process_callback(params[:code], :redirect_uri => callback_url)
77 |
78 | h3. Exchange Sessions
79 |
80 | h2. TODO
81 |
82 | h3. Canvas
83 |
84 | Facebook send a signed_request as a parameter. Can be decoded with the method parse_signed_request of FBGraph::Canvas module
85 |
86 | > FBGraph::Canvas.parse_signed_request(app_secret, params[:signed_request])
87 |
88 | h3. Selection
89 |
90 | h4. Accessing objects with connection types.
91 |
92 | p. All objects and their connections can be accesed
93 |
94 | Examples:
95 |
96 | notextile. client.selection.me.home.info!
97 |
98 | notextile. client.selection.user('id').photos.info!
99 |
100 | notextile. client.selection.photo('id').comments.info!
101 |
102 | notextile. client.selection.page('id').info!
103 |
104 | p. Also you can get results of more than 1 objects
105 |
106 | Example:
107 |
108 | notextile. client.selection.user([id1,id2,id3]).info!
109 |
110 |
111 | h4. client.selection.info!
112 |
113 | p. request with GET for information and return the response parsed with JSON. You can disable the parsing passing false as a first and unique parameter
114 |
115 | notextile. user_info = client.selection.me.info!
116 |
117 |
118 | h3. Publishing
119 |
120 | h4. client.selection.publish!
121 |
122 | p. request with POST for publishing and return the response parsed with JSON. You can disable the parsing passing false as a first and unique parameter
123 |
124 | notextile. client.selection.post('id').comments.params(:message => 'comment test').publish!
125 |
126 | p. OR
127 |
128 | notextile. client.selection.post('id').comments.publish!(:message => 'comment test')
129 |
130 |
131 | h3. Deletion
132 |
133 | h4. client.selection.delete!
134 |
135 | p. request with DELETE for deletion and return the response parsed with JSON. You can disable the parsing passing false as a first and unique parameter
136 |
137 | notextile. client.selection.post('id').delete!
138 |
139 |
140 | h3. Picture
141 |
142 |
143 | h4. client.selection.picture
144 |
145 | p. return the url of the object picture
146 |
147 | notextile. client.selection.me.picture
148 |
149 |
150 | h3. Paging
151 |
152 | h4. client.selection.limit
153 |
154 |
155 | notextile. client.selection.me.photos.limit(3).info!
156 |
157 | h4. client.selection.offset
158 |
159 |
160 | notextile. client.selection.me.photos.offset(10).info!
161 |
162 | h4. client.selection.until
163 |
164 |
165 | notextile. client.selection.me.photos.until(Time.now.to_s).info!
166 |
167 | h4. client.selection.since
168 |
169 |
170 | notextile. client.selection.me.photos.since(3.days.ago).info!
171 |
172 |
173 | h3. Search
174 |
175 | h4. client.search.query('query').info!
176 |
177 | p. Get the search results
178 |
179 | notextile. results = client.search.query('facebook').info!
180 |
181 |
182 | h4. client.search.query('query')on('type').info!
183 |
184 | p. Get the search results by type
185 |
186 | notextile. results = client.search.query('facebook').on('home').info!
187 |
188 | h3. RealTime Updates
189 |
190 | h4. client.realtime.user
191 |
192 | h4. client.realtime.permissions
193 |
194 | h4. client.realtime.errors
195 |
196 | p. Set the object to be subscribed, modified or unsubscribed
197 |
198 | h4. client.realtime.fields('email,picture')
199 |
200 | p. Set the objects fields
201 |
202 |
203 | h4. client.realtime.callback_url(url)
204 |
205 | p. Set the callback url
206 |
207 |
208 | h4. client.realtime.verify_token(token)
209 |
210 | p. Set the verify token (optional)
211 |
212 | h4. client.realtime.subscribe!
213 |
214 | p. Send the request for add/modify a subscription for realtime Updates.
215 |
216 |
217 | Examples:
218 |
219 | notextile. results = client.realtime.user.fields('email,picture').callback_url(url).verify_token('token').subscribe!
220 |
221 | notextile. results = client.realtime.permissions.fields('read_stream').callback_url(url).subscribe!
222 |
223 | If you want delete a subscirpition, you can use the delete! method.
224 |
225 | Examples:
226 |
227 | notextile. results = client.realtime.user.delete!
228 |
229 |
230 | h3. FQL
231 |
232 | h4. client.fql.query("SELECT name FROM user WHERE uid = me()")
233 |
234 |
235 | h3. Timeline
236 |
237 | h4. client.timeline.action('namespace', 'run').param(:location => [location object URL])
238 |
239 | h4. client.timeline.reads.param(:article => [article object URL] )
240 |
241 |
242 | h3. Analytics
243 |
244 | h4. TODO
245 |
246 | h3. Advanced
247 |
248 | h4. not documented yet
249 |
250 |
251 | h2. Credits
252 |
253 | Examples:
254 |
255 | notextile. results = client.selection.user(USER_ID).payments.info!(:status => STATUS).
256 |
257 | notextile. results = client.selection.order(ORDER_ID).publish!(:status => STATUS)
258 |
259 |
260 | h2. Contributions
261 |
262 | p. Just do a pull request with the repo in sync.
263 |
264 |
265 |
266 | h2. Maintainers
267 |
268 | "Nicolas Santa":http://github.com/nsanta
269 |
270 | "Matt Lightner (via RedRadiant)":http://github.com/redradiant
271 |
272 | "Victor Costan":http://github.com/pwnall
273 |
274 | h2. Contributors List
275 |
276 | "Mark Bates":http://github.com/markbates
277 |
278 | "Florent Guilleux":http://github.com/Florent2
279 |
280 | "Jan De Poorter":http://github.com/DefV
281 |
282 | "Thilo-Alexander Ginkel":http://github.com/ginkel
283 |
284 | "Matias Käkelä":http://github.com/massive
285 |
286 | "Max De Marzi":http://github.com/maxdemarzi
287 |
288 | "Peter Boling":https://github.com/pboling
289 |
290 | "Roberto Miranda":https://github.com/robertomiranda
291 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | #!/usr/bin/env rake
3 | require "bundler/gem_tasks"
4 | require 'rake'
5 |
6 | require 'rspec/core'
7 | require 'rspec/core/rake_task'
8 | RSpec::Core::RakeTask.new(:spec) do |spec|
9 | spec.pattern = FileList['spec/**/*_spec.rb']
10 | end
11 |
12 | RSpec::Core::RakeTask.new(:rcov) do |spec|
13 | spec.pattern = 'specs/**/*_spec.rb'
14 | spec.rcov = true
15 | end
16 |
17 | task :default => :spec
18 |
19 | require 'rdoc/task'
20 | Rake::RDocTask.new do |rdoc|
21 | require File.expand_path('../lib/fbgraph/version', __FILE__)
22 | rdoc.rdoc_dir = 'rdoc'
23 | rdoc.title = "SanitizeEmail #{FBGraph::VERSION}"
24 | rdoc.options << '--line-numbers'
25 | rdoc.rdoc_files.include('README*')
26 | rdoc.rdoc_files.include('lib/**/*.rb')
27 | end
28 |
29 | Bundler::GemHelper.install_tasks
30 |
--------------------------------------------------------------------------------
/TODO.list:
--------------------------------------------------------------------------------
1 | - Tests
2 | - README
3 | - Documentation
4 | - Analytics
5 | - Integrate with facebooker
6 | - Pluginizable
7 |
8 |
--------------------------------------------------------------------------------
/fbgraph.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 | require File.expand_path('../lib/fbgraph/version', __FILE__)
3 |
4 | Gem::Specification.new do |s|
5 | s.name = "fbgraph"
6 | s.version = FBGraph::VERSION
7 |
8 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9 | s.authors = ["Nicolas Santa"]
10 | s.date = "2012-04-27"
11 | s.description = "A Gem for Facebook Open Graph API"
12 | s.email = "nicolas55ar@gmail.com"
13 | s.extra_rdoc_files = [
14 | "README.textile"
15 | ]
16 | s.files = `git ls-files`.split($\)
17 | s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18 | s.test_files = s.files.grep(%r{^(test|spec|features)/})
19 |
20 | s.extra_rdoc_files = [
21 | "README.textile",
22 | ]
23 | s.files = [
24 | ".bundle/config",
25 | "Gemfile",
26 | "Manifest",
27 | "README.textile",
28 | "Rakefile",
29 | "TODO.list",
30 | "fbgraph.gemspec",
31 | "lib/fbgraph.rb",
32 | "lib/fbgraph/authorization.rb",
33 | "lib/fbgraph/base.rb",
34 | "lib/fbgraph/cacert.pem",
35 | "lib/fbgraph/canvas.rb",
36 | "lib/fbgraph/client.rb",
37 | "lib/fbgraph/fql.rb",
38 | "lib/fbgraph/logger.rb",
39 | "lib/fbgraph/realtime.rb",
40 | "lib/fbgraph/result.rb",
41 | "lib/fbgraph/search.rb",
42 | "lib/fbgraph/selection.rb",
43 | "lib/fbgraph/timeline.rb",
44 | "spec/lib/fbauth/authorization_spec.rb",
45 | "spec/lib/fbauth/base_spec.rb",
46 | "spec/lib/fbauth/canvas_spec.rb",
47 | "spec/lib/fbauth/client_spec.rb",
48 | "spec/lib/fbauth/realtime_spec.rb",
49 | "spec/lib/fbauth/search_spec.rb",
50 | "spec/lib/fbauth/selection_spec.rb",
51 | "spec/spec_helper.rb"
52 | ]
53 | s.homepage = "http://github.com/nsanta/fbgraph"
54 | s.licenses = ["MIT"]
55 | s.require_paths = ["lib"]
56 | s.rubygems_version = "1.8.21"
57 | s.summary = "A Gem for Facebook Open Graph API"
58 |
59 | if s.respond_to? :specification_version then
60 | s.specification_version = 3
61 |
62 | if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
63 | s.add_runtime_dependency(%q, [">= 0"])
64 | s.add_runtime_dependency(%q, [">= 1.0.0"])
65 | s.add_runtime_dependency(%q, [">= 0.5.0"])
66 | s.add_runtime_dependency(%q, [">= 0.7.5"])
67 | s.add_runtime_dependency(%q, [">= 1.0.0"])
68 | s.add_runtime_dependency(%q, [">= 0"])
69 | s.add_runtime_dependency(%q, [">= 0"])
70 | s.add_development_dependency(%q, ["~> 0.9.2"])
71 | s.add_development_dependency(%q, ["> 1.0.0"])
72 | s.add_development_dependency(%q, ["~> 1.3.0"])
73 | s.add_development_dependency(%q, ["~> 2.6"])
74 | s.add_development_dependency(%q, [">= 0"])
75 | s.add_development_dependency(%q, [">= 3.9.0"])
76 | else
77 | s.add_dependency(%q, [">= 0"])
78 | s.add_dependency(%q, [">= 1.0.0"])
79 | s.add_dependency(%q, [">= 0.5.0"])
80 | s.add_dependency(%q, [">= 0.7.5"])
81 | s.add_dependency(%q, [">= 1.0.0"])
82 | s.add_dependency(%q, [">= 0"])
83 | s.add_dependency(%q, [">= 0"])
84 | s.add_dependency(%q, ["~> 0.9.2"])
85 | s.add_dependency(%q, ["> 1.0.0"])
86 | s.add_dependency(%q, ["~> 1.3.0"])
87 | s.add_dependency(%q, ["~> 2.6"])
88 | s.add_dependency(%q, [">= 0"])
89 | s.add_dependency(%q, [">= 3.9.0"])
90 | end
91 | else
92 | s.add_dependency(%q, [">= 0"])
93 | s.add_dependency(%q, [">= 1.0.0"])
94 | s.add_dependency(%q, [">= 0.5.0"])
95 | s.add_dependency(%q, [">= 0.7.5"])
96 | s.add_dependency(%q, [">= 1.0.0"])
97 | s.add_dependency(%q, [">= 0"])
98 | s.add_dependency(%q, [">= 0"])
99 | s.add_dependency(%q, ["~> 0.9.2"])
100 | s.add_dependency(%q, ["> 1.0.0"])
101 | s.add_dependency(%q, ["~> 1.3.0"])
102 | s.add_dependency(%q, ["~> 2.6"])
103 | s.add_dependency(%q, [">= 0"])
104 | s.add_dependency(%q, [">= 3.9.0"])
105 | end
106 | end
107 |
108 |
--------------------------------------------------------------------------------
/lib/fbgraph.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require "bundler/setup"
3 | require 'active_support/all'
4 | require 'oauth2'
5 | require 'json'
6 | require 'hashie'
7 | require 'rest_client'
8 | require 'uri'
9 | require "base64"
10 | require "openssl"
11 |
12 | require 'fbgraph/result'
13 | require 'fbgraph/client'
14 | require 'fbgraph/base'
15 | require 'fbgraph/authorization'
16 | require 'fbgraph/selection'
17 | require 'fbgraph/search'
18 | require 'fbgraph/realtime'
19 | require 'fbgraph/canvas'
20 | require 'fbgraph/logger'
21 | require 'fbgraph/fql'
22 | require 'fbgraph/timeline'
23 |
24 | module FBGraph
25 | @config = nil
26 |
27 | class << self
28 | def config
29 | @config ||= load_config(config_path).freeze
30 | end
31 |
32 | def config_path
33 | if defined?(Rails)
34 | File.join(Rails.root , 'config' , 'facebook.yml')
35 | else
36 | 'facebook.yml'
37 | end
38 | end
39 |
40 | def load_config(yaml_file)
41 | return {} unless File.exist?(yaml_file)
42 | cfg = YAML::load(File.open(yaml_file))
43 | if defined? Rails
44 | cfg = cfg[Rails.env]
45 | end
46 | cfg
47 | end
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/lib/fbgraph/authorization.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 |
3 | class Authorization
4 |
5 | def initialize(client)
6 | @client = client
7 | end
8 |
9 | def authorize_url(params = {})
10 | params = { :redirect_uri => FBGraph.config[:canvas_url] }.merge(params)
11 | @client.oauth_client.auth_code.authorize_url(params)
12 | end
13 |
14 |
15 | def process_callback(code, options = {})
16 | # HACK(pwnall): :parse => :query is added because Facebook's tarded OAuth
17 | # endpoint returns ContentType: text/plain instead of
18 | # application/x-www-form-urlencoded
19 | options = { :redirect_uri => FBGraph.config[:canvas_url],
20 | :parse => :query }.merge(options)
21 | @client.auth = @client.oauth_client.auth_code.get_token(code, options)
22 | @client.access_token = @client.auth.token
23 | end
24 |
25 | def upgrade_session!(key)
26 | token = upgrade_session_keys(key).first
27 | @client.access_token = token
28 | end
29 |
30 | def upgrade_session_keys(*keys)
31 | tokens = @client.oauth_client.request(:get, '/oauth/exchange_sessions', {
32 | :client_id => @client.client_id,
33 | :client_secret => @client.secret_id,
34 | :type => 'client_cred',
35 | :sessions => keys.flatten.join(',')
36 | })
37 | JSON.parse(tokens).map { |hash| hash['access_token'] if hash}
38 | end
39 |
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/lib/fbgraph/base.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 |
3 | class Base
4 |
5 | attr_reader :objects , :connection_type , :logger, :fields, :last_result
6 |
7 | def initialize(client)
8 | @client = client
9 | @fields = []
10 | @params = {}
11 | end
12 |
13 | def find(objects)
14 | @objects = objects
15 | return self
16 | end
17 |
18 | def connection(connection_type)
19 | @connection_type = connection_type
20 | return self
21 | end
22 |
23 | def params=(ps)
24 | @params = ps
25 | return self
26 | end
27 |
28 | def params
29 | @params
30 | end
31 |
32 | def param(pm)
33 | @params.merge!(pm)
34 | return self
35 | end
36 |
37 | def with_fields(*new_fields)
38 | @fields.concat(new_fields) if !(new_fields.blank? rescue true)
39 | @fields = sanitized_fields
40 | self
41 | end
42 | alias :fields :with_fields
43 |
44 | def info!(parsed = true, &block)
45 | self.instance_eval(&block) if block_given?
46 | @params.merge!(:fields => sanitized_fields.join(',')) unless sanitized_fields.blank?
47 | @params.merge!(:access_token => @client.access_token) unless @client.access_token.nil?
48 | if @objects.is_a? Array
49 | @params.merge!({:ids => @objects.join(',')})
50 | path = build_open_graph_path(nil,nil, @params)
51 | elsif @objects.is_a? String
52 | path = build_open_graph_path(@objects , @connection_type, @params)
53 | else
54 | raise "No Facebook objects were recognized as selected; unable to build fb graph path."
55 | end
56 | show_log('GET' , path, @params) if @debug
57 | result = @client.consumer[path].get
58 | @last_result = ::FBGraph::Result.new(result, @params)
59 | end
60 |
61 |
62 | def publish!(data = {},parsed = true, &block)
63 | @params.merge!(data)
64 | self.instance_eval(&block) if block_given?
65 | @params.merge!(:fields => sanitized_fields.join(',')) unless sanitized_fields.blank?
66 | @params.merge!(:access_token => @client.access_token) if (@client.access_token)
67 | @path = build_open_graph_path(@objects , @connection_type)
68 | show_log('POST' , @path, @params) if @debug
69 | result = @client.consumer[@path].post(@params)
70 | @last_result = ::FBGraph::Result.new(result, @params)
71 | end
72 |
73 | def delete!(parsed = true, &block)
74 | self.instance_eval(&block) if block_given?
75 | @path = build_open_graph_path(@objects , nil)
76 | @params.merge!(:access_token => @client.access_token) if (@client.access_token)
77 | @params.merge!(:method => :delete)
78 | show_log('DELETE' , @path, @params) if @debug
79 | result = @client.consumer[@path].post(@params)
80 | @last_result = ::FBGraph::Result.new(result, @params)
81 | end
82 |
83 | %w(limit offset until since).each do |paging|
84 | class_eval <<-PAGING
85 | def #{paging}(value)
86 | @params[:#{paging}] = value
87 | self
88 | end
89 | PAGING
90 | end
91 |
92 | def debug=(att)
93 | @debug= att
94 | end
95 |
96 | private
97 |
98 | def sanitized_fields
99 | @fields.flatten.map(&:to_s).compact
100 | end
101 |
102 | def build_open_graph_path(objects, connection_type = nil , params = {})
103 | request = [objects , connection_type].compact.join('/')
104 | request += "?"+params.to_a.map{|p| p.join('=')}.join('&') unless params.empty?
105 | URI.encode(request)
106 | end
107 |
108 | def show_log(ver, path, params)
109 | client.logger.info "FBGRAPH [#{verb}]: #{path}"
110 | client.logger.info "PARAMS: #{params.to_a.map{|p| p.join('=')}.join('&')}"
111 | end
112 |
113 | end
114 | end
115 |
--------------------------------------------------------------------------------
/lib/fbgraph/canvas.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 |
3 | class Canvas
4 |
5 | class << self
6 | def parse_signed_request(secret_id,request)
7 | encoded_sig, payload = request.split('.', 2)
8 | sig = urldecode64(encoded_sig)
9 | data = JSON.parse(urldecode64(payload))
10 | if data['algorithm'].to_s.upcase != 'HMAC-SHA256'
11 | raise "Bad signature algorithm: %s" % data['algorithm']
12 | end
13 | expected_sig = OpenSSL::HMAC.digest('sha256', secret_id, payload)
14 | if expected_sig != sig
15 | raise "Bad signature"
16 | end
17 | data
18 | end
19 |
20 | private
21 |
22 | def urldecode64(str)
23 | encoded_str = str.tr('-_', '+/')
24 | encoded_str += '=' while !(encoded_str.size % 4).zero?
25 | Base64.decode64(encoded_str)
26 | end
27 | end
28 |
29 | end
30 |
31 | end
32 |
--------------------------------------------------------------------------------
/lib/fbgraph/client.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 |
3 | class Client
4 |
5 | attr_accessor :client_id , :secret_id , :facebook_uri , :access_token , :consumer , :auth , :logger
6 |
7 | def initialize(options = {})
8 | @client_id = options[:client_id] || FBGraph.config[:client_id]
9 | @secret_id = options[:secret_id] || FBGraph.config[:secret_id]
10 | @ca_file = options[:ca_file] || FBGraph.config[:ca_file] || default_ca_file
11 | @facebook_uri = options[:facebook_uri] || 'https://graph.facebook.com'
12 | @consumer = RestClient::Resource.new(@facebook_uri, rest_client_ssl_options)
13 | @access_token = options.fetch :token, nil
14 | @auth = OAuth2::AccessToken.new(oauth_client, @access_token)
15 | @logger = options[:logger] || FBGraph::Logger
16 | return true
17 | end
18 |
19 | def set_token(new_token)
20 | @access_token = new_token
21 | @auth = OAuth2::AccessToken.new(oauth_client, @access_token)
22 | new_token
23 | end
24 |
25 | def authorization
26 | FBGraph::Authorization.new(self)
27 | end
28 |
29 | def selection
30 | FBGraph::Selection.new(self)
31 | end
32 |
33 | def search
34 | FBGraph::Search.new(self)
35 | end
36 |
37 | def realtime
38 | FBGraph::Realtime.new(self)
39 | end
40 |
41 | def fql
42 | FBGraph::FQL.new(self)
43 | end
44 |
45 | def timeline
46 | FBGraph::Timeline.new(self)
47 | end
48 |
49 | def oauth_client
50 | OAuth2::Client.new(client_id, secret_id,
51 | :site => { :url => facebook_uri },
52 | :token_url => '/oauth/access_token',
53 | :authorize_url => '/oauth/authorize',
54 | :ssl => oauth_client_ssl_options)
55 | end
56 |
57 | def oauth_client_ssl_options
58 | { :ca_file => @ca_file, :verify => OpenSSL::SSL::VERIFY_PEER }
59 | end
60 |
61 | def rest_client_ssl_options
62 | { :ssl_ca_file => @ca_file, :verify_ssl => OpenSSL::SSL::VERIFY_PEER }
63 | end
64 |
65 | def default_ca_file
66 | File.join(File.dirname(__FILE__), 'cacert.pem')
67 | end
68 | end
69 | end
70 |
71 | # :nodoc: undo the clusterfuck that rest-client has done
72 | if Net::HTTP.method_defined? :__request__
73 | module Net
74 | class HTTP
75 | undef request
76 | alias request __request__
77 | end
78 | end
79 | end
80 |
--------------------------------------------------------------------------------
/lib/fbgraph/fql.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 | class FQL < Base
3 |
4 |
5 | def query(q)
6 | find('fql').param(:q => q).info!
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/lib/fbgraph/logger.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 | class Logger
3 | def self.info(msg)
4 | puts msg
5 | end
6 |
7 | def self.warn(msg)
8 | puts msg
9 | end
10 |
11 | def self.error(msg)
12 | puts msg
13 | end
14 |
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/fbgraph/realtime.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 | class Realtime < Base
3 |
4 | def initialize(client)
5 | @objects = 'subscriptions'
6 | super(client)
7 | end
8 |
9 |
10 | OBJECTS = %w(user permissions errors).freeze
11 |
12 | OBJECTS.each do |object|
13 | class_eval <<-METHOD
14 | def #{object}
15 | @params[:object] = "#{object}"
16 | self
17 | end
18 | METHOD
19 | end
20 |
21 | def fields(fs = "email,picture")
22 | @params[:fields] = fs
23 | self
24 | end
25 |
26 | def callback_url(url)
27 | @params[:callback_url] = url
28 | self
29 | end
30 |
31 | def verify_token(token)
32 | @params[:verify_token] = token
33 | self
34 | end
35 |
36 |
37 | alias_method :subscribe! , :publish!
38 |
39 | private
40 |
41 | def build_open_graph_path(objects,connection_type = nil , params = {})
42 | request = "/" + [objects , connection_type].compact.join('/')
43 | request += "?"+params.to_a.map{|p| p.join('=')}.join('&') unless params.empty?
44 | request
45 | end
46 |
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/lib/fbgraph/result.rb:
--------------------------------------------------------------------------------
1 | require 'hashie/mash'
2 |
3 | module FBGraph
4 | class Result
5 |
6 | attr_accessor :params, :unparsed, :data
7 |
8 | def initialize(result, params = {}, &block)
9 | result = result.respond_to?(:body) ? result.body : result.to_s
10 | @data = Hashie::Mash.new(JSON.parse(result)) rescue result
11 | @unparsed = result
12 | @params = params.symbolize_keys
13 | self
14 | end
15 |
16 | def paging
17 | data.paging
18 | end
19 |
20 | def metadata
21 | data.metadata
22 | end
23 |
24 | # Implement enumerable
25 | def each(&block)
26 | return nil if data.blank?
27 | data.each(&block)
28 | end
29 | include Enumerable
30 |
31 | # Implement Comparable
32 | def <=>(other)
33 | (data <=> other.data) rescue 0
34 | end
35 | include Comparable
36 |
37 | def method_missing(method, *args, &block)
38 | data.send(method, *args, &block) rescue super(method, *args, &block)
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/lib/fbgraph/search.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 | class Search < Base
3 |
4 | def initialize(client)
5 | @objects = 'search'
6 | super(client)
7 | end
8 |
9 | def query(q)
10 | @params = {:q => q}
11 | return self
12 | end
13 |
14 | def on(type)
15 | @params.merge!({:type => type})
16 | return self
17 | end
18 |
19 |
20 |
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/fbgraph/selection.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 | class Selection < Base
3 |
4 | OBJECTS = %w(user album event group link note page photo post status
5 | video comment checkin friendlist thread order application
6 | apprequest subscription).freeze
7 |
8 | CONNECTION_TYPES = %w(home photos comments feed noreply
9 | maybe invited attending declined picture
10 | members tagged links groups albums
11 | statuses videos notes posts events friends
12 | activities interests music books movies television
13 | likes inbox outbox updates accounts checkins
14 | friendlists platformrequests threads participants
15 | former_participants senders messages insights
16 | subscriptions payments apprequests reviews
17 | mutualfriends family).freeze
18 |
19 | OBJECTS.each do |object|
20 | class_eval <<-METHOD
21 | def #{object}(object)
22 | find(object)
23 | self
24 | end
25 | METHOD
26 | end
27 |
28 | CONNECTION_TYPES.each do |object|
29 | class_eval <<-METHOD
30 | def #{object}(connection_id = nil)
31 | connection(['#{object}', connection_id])
32 | self
33 | end
34 | METHOD
35 | end
36 |
37 |
38 | def me
39 | find('me')
40 | end
41 |
42 | def metadata
43 | @params.merge!({:metadata => '1'})
44 | self
45 | end
46 |
47 | def picture(type='square')
48 | params = {:type => type}
49 | params.merge!(:access_token => @client.access_token) unless @client.access_token.blank?
50 | uri = [@client.facebook_uri , build_open_graph_path(@objects , 'picture' , params)].join('/')
51 | end
52 |
53 | end
54 | end
55 |
56 |
--------------------------------------------------------------------------------
/lib/fbgraph/timeline.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 | class Timeline < Base
3 |
4 | BUILT_IN_ACTIONS = {
5 | :listens => :music,
6 | :reads => :news,
7 | :watches => :movie,
8 | }
9 |
10 |
11 | def action(namespace,action)
12 | connection([namespace,action].join(':'))
13 | self
14 | end
15 |
16 | BUILT_IN_ACTIONS.each do |action,obj|
17 | class_eval <<-METHOD
18 | def #{action}
19 | find('me').connection("#{[obj,action].join('.')}")
20 | self
21 | end
22 | METHOD
23 | end
24 |
25 |
26 |
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/lib/fbgraph/version.rb:
--------------------------------------------------------------------------------
1 | module FBGraph
2 | VERSION = '1.10.1'
3 | end
4 |
--------------------------------------------------------------------------------
/spec/lib/fbauth/authorization_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe FBGraph do
4 | describe FBGraph::Authorization do
5 |
6 | before :each do
7 | @client_id = 'client_id'
8 | @secret_id = 'secret_id'
9 | @client = FBGraph::Client.new(:client_id => @client_id,
10 | :secret_id => @secret_id)
11 | @authorization = FBGraph::Authorization.new(@client)
12 | end
13 |
14 | describe 'initialization' do
15 | it 'should set the client' do
16 | @authorization.instance_variable_get("@client").should == @client
17 | end
18 | end
19 |
20 | describe "instance methods" do
21 | describe '.authorize_url' do
22 | it 'should return the authorization url' do
23 | @authorization.authorize_url(:redirect_uri => 'redirect/to/path' ,
24 | :scope => 'email,user_photos,friends_photos').should =~ /redirect_uri=redirect%2Fto%2Fpath/
25 | end
26 | end
27 | describe "process_callback" do
28 | before :each do
29 | @consumer = mock('Consumer' , :token => 'code')
30 | options = {:redirect_uri => 'redirect/to/path', :parse=>:query}
31 | @client.stub!(:oauth_client).and_return(Object.new)
32 | @client.oauth_client.stub!(:auth_code).and_return(Object.new)
33 | @client.oauth_client.auth_code.stub!(:get_token).with(@consumer.token, options).and_return(@consumer)
34 | @token = @authorization.process_callback(@consumer.token, options)
35 | end
36 | it 'should return the access_token' do
37 | @token.should == @consumer.token
38 | end
39 | it 'should set the consumer' do
40 | @client.auth.should == @consumer
41 | end
42 | end
43 | end
44 |
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/spec/lib/fbauth/base_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe FBGraph do
4 | describe FBGraph::Authorization do
5 |
6 | before :each do
7 | @client_id = 'client_id'
8 | @secret_id = 'secret_id'
9 | @client = FBGraph::Client.new(:client_id => @client_id,
10 | :secret_id => @secret_id,
11 | :token => 'token')
12 | @base = FBGraph::Base.new(@client)
13 |
14 | end
15 |
16 | describe 'initialization' do
17 | it 'should set the client' do
18 | @base.instance_variable_get("@client").should == @client
19 | end
20 | it 'should params be empty' do
21 | @base.params.should be_empty
22 | end
23 | end
24 |
25 | describe "instance methods" do
26 | describe 'find' do
27 | it 'should objects set with "id"' do
28 | @base.find('id').objects.should == 'id'
29 | end
30 | end
31 |
32 | describe 'connection' do
33 | it 'should set connection_type to "type"' do
34 | @base.connection('type').connection_type.should == 'type'
35 | end
36 | end
37 |
38 | describe 'params=' do
39 | it 'should set params to {:fields => "fields"}' do
40 | @base.params = {:fields => "fields"}
41 | @base.params.should == {:fields => "fields"}
42 | end
43 | end
44 |
45 | describe 'params' do
46 | it 'should return params' do
47 | @base.params = {:fields => "fields"}
48 | @base.params.should == {:fields => "fields"}
49 | end
50 | end
51 |
52 | describe 'param' do
53 | it 'should merge the passed param' do
54 | @base.params = {:fields => "fields"}
55 | @base.param(:merged => true)
56 | @base.params.should == {:fields => "fields" , :merged => true}
57 | end
58 | end
59 |
60 | describe 'info!' do
61 | describe 'when object is an array' do
62 | it 'should request with the path "/?ids=1,2,3"' do
63 | uri = "?access_token=token&ids=1,2,3"
64 | @base.find([1,2,3])
65 | expect_consumer(uri)
66 | @base.info!(false)
67 | end
68 | end
69 |
70 | describe 'when object is a string' do
71 |
72 | it 'should request with the path "/123"' do
73 | uri = "123?access_token=token"
74 | @base.find('123')
75 | expect_consumer(uri)
76 | @base.info!(false)
77 | end
78 |
79 | it "should parse the result by default" do
80 | uri = "123?access_token=token"
81 | @base.find('123')
82 | expect_consumer(uri, '{"me": [1, 2]}')
83 | @base.info!.me.should == [1, 2]
84 | end
85 |
86 | describe 'when a connection is passed' do
87 | it 'should request with the path "/123/home"' do
88 | uri = "123/home?access_token=token"
89 | @base.find('123').connection('home')
90 | expect_consumer(uri)
91 | @base.info!(false)
92 | end
93 | end
94 |
95 | describe 'when params are passed' do
96 | it 'should request with the path "/123?fields=name,picture"' do
97 | uri = "123?fields=name,picture&access_token=token"
98 | @base.find('123')
99 | @base.params = {:fields => "name,picture"}
100 | expect_consumer(uri)
101 | @base.info!(false)
102 | end
103 | end
104 | end
105 | end
106 |
107 | describe 'publish!' do
108 | describe 'when is passed params before invocation' do
109 | it 'should request with the path "/123" and params {:extra => "extra" }' do
110 | uri = "123"
111 | @base.find('123')
112 | @base.params = {:extra => "extra" }
113 | #@client.consumer.stub!(:post).with(uri , @base.params).and_return('')
114 | expect_consumer_post(uri, {:extra => "extra", :access_token => 'token'})
115 | @base.publish!({}, false)
116 | end
117 | end
118 | describe 'when is passed params on invocation' do
119 | it 'should request with the path "/123" and params {:extra => "extra" }' do
120 | uri = "123"
121 | @base.find('123')
122 | ps = {:extra => "extra"}
123 | expect_consumer_post(uri, {:extra => "extra", :access_token => 'token'})
124 | @base.publish!(ps, false)
125 | end
126 | end
127 | end
128 |
129 | describe 'delete!' do
130 | it 'should request with the path "/123" and params {:extra => "extra" }' do
131 | uri = "123"
132 | @base.find('123')
133 | @base.params = {:extra => "extra" }
134 | expect_consumer_post(uri, {:method => :delete, :extra => "extra", :access_token => 'token'})
135 | @base.delete!(false)
136 | end
137 | end
138 |
139 | end
140 |
141 | end
142 | end
143 |
--------------------------------------------------------------------------------
/spec/lib/fbauth/canvas_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe FBGraph do
4 | describe FBGraph::Canvas do
5 | before :each do
6 | @payload = { 'algorithm' => 'HMAC-SHA256', 'foo' => 'bar' }
7 | @secret = 'thisisasecret'
8 |
9 | encoded_payload = Base64.encode64(@payload.to_json)
10 | hash = OpenSSL::HMAC.digest('sha256', @secret, encoded_payload)
11 | encoded_sig = Base64.encode64(hash)
12 |
13 | @valid_request = "#{encoded_sig}.#{encoded_payload}"
14 | end
15 |
16 | it "should decode a valid request" do
17 | result = FBGraph::Canvas.parse_signed_request(@secret, @valid_request)
18 | result.should == @payload
19 | end
20 |
21 | it "should raise on an invalid request" do
22 | bad_secret = "notagoodsecret"
23 |
24 | lambda {
25 | FBGraph::Canvas.parse_signed_request(bad_secret, @valid_request)
26 | }.should raise_error
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/lib/fbauth/client_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe FBGraph do
4 | describe FBGraph::Client do
5 | describe "initialization" do
6 | before :each do
7 | @client_id = 'client_id'
8 | @secret_id = 'secret_id'
9 | end
10 | describe 'default' do
11 |
12 | before :each do
13 | @client = FBGraph::Client.new(:client_id => @client_id,
14 | :secret_id => @secret_id)
15 | end
16 |
17 | it 'should set the client_id' do
18 | @client.client_id.should == @client_id
19 | end
20 | it 'should set the secret_id' do
21 | @client.secret_id.should == @secret_id
22 | end
23 | it 'should set the facebook_uri ' do
24 | @client.facebook_uri.should == "https://graph.facebook.com"
25 | end
26 | end
27 |
28 | describe 'when token is present' do
29 | before :each do
30 | @token = 'token'
31 | @client = FBGraph::Client.new(:client_id => @client_id,
32 | :secret_id => @secret_id,
33 | :token => @token)
34 | end
35 |
36 | it 'should set the access_token' do
37 | @client.access_token.should == @token
38 | end
39 | it 'should set the consumer client' do
40 | @client.consumer.class.should == RestClient::Resource
41 | end
42 | end
43 | end
44 |
45 |
46 | describe "instance methods" do
47 | before :each do
48 | @client_id = 'client_id'
49 | @secret_id = 'secret_id'
50 | @client = FBGraph::Client.new(:client_id => @client_id,
51 | :secret_id => @secret_id)
52 | end
53 | describe '.authorization' do
54 | it 'should return a FBGraph::Authorization object' do
55 | @client.authorization.class.should == FBGraph::Authorization
56 | end
57 | end
58 |
59 | describe '.selection' do
60 | it 'should return a FBGraph::Selection object' do
61 | @client.selection.class.should == FBGraph::Selection
62 | end
63 | end
64 |
65 | describe '.search' do
66 | it 'should return a FBGraph::Search object' do
67 | @client.search.class.should == FBGraph::Search
68 | end
69 | end
70 |
71 | describe '.realtime' do
72 | it 'should return a FBGraph::Search object' do
73 | @client.realtime.class.should == FBGraph::Realtime
74 | end
75 | end
76 |
77 | describe '.oauth_client' do
78 | it 'should return a OAuth2::Client object' do
79 | @client.oauth_client.class.should == OAuth2::Client
80 | end
81 | end
82 | end
83 | end
84 | end
85 |
--------------------------------------------------------------------------------
/spec/lib/fbauth/realtime_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe FBGraph do
4 | describe FBGraph::Realtime do
5 |
6 | before :each do
7 | @client_id = 'client_id'
8 | @secret_id = 'secret_id'
9 | @client = FBGraph::Client.new(:client_id => @client_id,
10 | :secret_id => @secret_id)
11 | @search = FBGraph::Search.new(@client)
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/spec/lib/fbauth/search_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe FBGraph do
4 | describe FBGraph::Search do
5 |
6 | before :each do
7 | @client_id = 'client_id'
8 | @secret_id = 'secret_id'
9 | @client = FBGraph::Client.new(:client_id => @client_id,
10 | :secret_id => @secret_id)
11 | @search = FBGraph::Search.new(@client)
12 | end
13 |
14 | describe "initialization" do
15 | it "should set @object with 'search'" do
16 | @search.objects.should == 'search'
17 | end
18 | end
19 |
20 |
21 | describe 'instance methods' do
22 |
23 | describe '.query' do
24 | before(:each) do
25 | @result = @search.query('query')
26 | end
27 | it 'should return self' do
28 | @result.should == @search
29 | end
30 | it "should assign in params[:q] 'query'" do
31 | @search.params[:q].should == 'query'
32 | end
33 | end
34 | describe '.on' do
35 | before(:each) do
36 | @result = @search.on('type')
37 | end
38 | it 'should return self' do
39 | @result.should == @search
40 | end
41 | it "should assign in params[:type] 'type'" do
42 | @search.params[:type].should == 'type'
43 | end
44 | end
45 | end
46 |
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/spec/lib/fbauth/selection_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe FBGraph do
4 | describe FBGraph::Selection do
5 |
6 | before :each do
7 | @client_id = 'client_id'
8 | @secret_id = 'secret_id'
9 | @token = 'token'
10 | @client = FBGraph::Client.new(:client_id => @client_id,
11 | :secret_id => @secret_id,
12 | :token => @token)
13 | @selection = FBGraph::Selection.new(@client)
14 | end
15 |
16 | describe "when asking for an object's picture" do
17 | it "should append the access token" do
18 | @selection.me.picture.should ==
19 | "https://graph.facebook.com/me/picture?type=square&access_token=#{@token}"
20 | end
21 |
22 | it "should not append an access token if none is available" do
23 | client = FBGraph::Client.new(:client_id => @client_id,
24 | :secret_id => @secret_id)
25 | selection = FBGraph::Selection.new(client)
26 |
27 | selection.me.picture.should ==
28 | "https://graph.facebook.com/me/picture?type=square"
29 | end
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # This file was generated by the `rspec --init` command. Conventionally, all
2 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3 | # Require this file using `require "spec_helper"` to ensure that it is only
4 | # loaded once.
5 | #
6 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7 |
8 | require 'fbgraph'
9 | require 'support/fbgraph_spec_helper'
10 | begin
11 | require 'redgreen'
12 | rescue LoadError
13 | # redgreen is for pretty spec result colors on Windows... no biggie.
14 | end
15 |
16 | RSpec.configure do |config|
17 | config.treat_symbols_as_metadata_keys_with_true_values = true
18 | config.run_all_when_everything_filtered = true
19 | config.filter_run :focus
20 |
21 | # Run specs in random order to surface order dependencies. If you find an
22 | # order dependency and want to debug it, you can fix the order by providing
23 | # the seed, which is printed after each run.
24 | # --seed 1234
25 | config.order = 'random'
26 |
27 | config.include FBGraphSpecHelper
28 | end
29 |
30 |
31 |
--------------------------------------------------------------------------------
/spec/support/fbgraph_spec_helper.rb:
--------------------------------------------------------------------------------
1 | module FBGraphSpecHelper
2 | def expect_consumer(uri, result = '')
3 | consumer = @client.consumer[uri]
4 | consumer.stub!(:get).and_return(Struct.new(:body).new(result))
5 | @client.consumer.stub!(:[]).with(uri).and_return(consumer)
6 | end
7 |
8 | def expect_consumer_post(uri, params = {}, result = '')
9 | rest_client = @client.consumer[uri]
10 | rest_client.stub!(:post).with(params).and_return(Struct.new(:body).new(result))
11 | @client.consumer.stub!(:[]).with(uri).and_return(rest_client)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------