Class: RestGraph

Inherits:
RestGraphStruct show all
Extended by:
DefaultAttributes
Defined in:
lib/rest-graph/rails_util.rb,
lib/rest-graph/core.rb,
lib/rest-graph/rails_util.rb

Overview

this cannot be put here because of load order, so put in the bottom of this file to load up for rails2. if Rails::VERSION::MAJOR == 2

::RestGraph::RailsUtil.init(Rails)

end

Defined Under Namespace

Modules: ConfigUtil, DefaultAttributes, FacebookUtil, Gsub, Json, RailsCache, RailsUtil, TestUtil, YajlRuby Classes: Error, Event, EventStruct, Railtie

Constant Summary collapse

Attributes =
RestGraphStruct.members.map(&:to_sym)

Instance Attribute Summary

Attributes inherited from RestGraphStruct

#accept, #app_id, #auto_decode, #cache, #data, #error_handler, #expires_in, #graph_server, #lang, #log_handler, #log_method, #old_server, #secret, #timeout

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DefaultAttributes

default_accept, default_access_token, default_app_id, default_auto_authorize, default_auto_authorize_options, default_auto_authorize_scope, default_auto_decode, default_cache, default_canvas, default_check_handler, default_data, default_ensure_authorized, default_error_handler, default_expires_in, default_graph_server, default_iframe, default_lang, default_log_handler, default_log_method, default_old_server, default_secret, default_strict, default_timeout, default_write_cookies, default_write_handler, default_write_session

Constructor Details

#initialize(o = {}) ⇒ RestGraph

common methods



198
199
200
# File 'lib/rest-graph/core.rb', line 198

def initialize o={}
  o.each{ |key, value| send("#{key}=", value) if respond_to?("#{key}=") }
end

Class Method Details

.hmac_sha256(key, data) ⇒ Object

Fallback to ruby-hmac gem in case system openssl lib doesn't support SHA256 (OSX 10.5)



120
121
122
123
124
125
# File 'lib/rest-graph/core.rb', line 120

def self.hmac_sha256 key, data
  OpenSSL::HMAC.digest('sha256', key, data)
rescue RuntimeError
  require 'hmac-sha2'
  HMAC::SHA256.digest(key, data)
end

.select_json!(picked = false) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/rest-graph/core.rb', line 170

def self.select_json! picked=false
  if    defined?(::Yajl)
    extend YajlRuby
  elsif defined?(::JSON)
    extend Json
  elsif picked
    extend Gsub
  else
    # pick a json gem if available
    %w[yajl json].each{ |json|
      begin
        require json
        break
      rescue LoadError
      end
    }
    select_json!(true)
  end
end

Instance Method Details

#access_tokenObject



202
203
204
# File 'lib/rest-graph/core.rb', line 202

def access_token
  data['access_token'] || data['oauth_token']
end

#access_token=(token) ⇒ Object



206
207
208
# File 'lib/rest-graph/core.rb', line 206

def access_token= token
  data['access_token'] = token
end

#adelete(path, query = {}, opts = {}, &cb) ⇒ Object



286
287
288
# File 'lib/rest-graph/core.rb', line 286

def adelete path, query={}, opts={}, &cb
  delete(path, query, {:async => true}.merge(opts), &cb)
end

#aget(path, query = {}, opts = {}, &cb) ⇒ Object

request by eventmachine (em-http)



282
283
284
# File 'lib/rest-graph/core.rb', line 282

def aget    path, query={}, opts={}, &cb
  get(path, query, {:async => true}.merge(opts), &cb)
end

#apost(path, payload = {}, query = {}, opts = {}, &cb) ⇒ Object



290
291
292
# File 'lib/rest-graph/core.rb', line 290

def apost   path, payload={}, query={}, opts={}, &cb
  post(path, payload, query, {:async => true}.merge(opts), &cb)
end

#aput(path, payload = {}, query = {}, opts = {}, &cb) ⇒ Object



294
295
296
# File 'lib/rest-graph/core.rb', line 294

def aput    path, payload={}, query={}, opts={}, &cb
  put(path, payload, query, {:async => true}.merge(opts), &cb)
end

#attributesObject



234
235
236
# File 'lib/rest-graph/core.rb', line 234

def attributes
  Hash[each_pair.map{ |k, v| [k, send(k)] }]
end

#authorize!(opts = {}) ⇒ Object



410
411
412
413
414
415
# File 'lib/rest-graph/core.rb', line 410

def authorize! opts={}
  payload = {:client_id => app_id, :client_secret => secret}.merge(opts)
  self.data = Rack::Utils.parse_query(
                request({:auto_decode => false}.merge(opts),
                        [:post, url('oauth/access_token'), payload]))
end

#authorize_url(opts = {}) ⇒ Object

oauth related



405
406
407
408
# File 'lib/rest-graph/core.rb', line 405

def authorize_url opts={}
  query = {:client_id => app_id, :access_token => nil}.merge(opts)
  "#{graph_server}oauth/authorize#{build_query_string(query)}"
end

#authorized?Boolean

Returns:

  • (Boolean)


210
211
212
# File 'lib/rest-graph/core.rb', line 210

def authorized?
  !!access_token
end

#delete(path, query = {}, opts = {}, &cb) ⇒ Object



266
267
268
# File 'lib/rest-graph/core.rb', line 266

def delete path, query={}, opts={}, &cb
  request(opts, [:delete, url(path, query, graph_server, opts)], &cb)
end

#exchange_sessions(query = {}, opts = {}, &cb) ⇒ Object



451
452
453
454
455
# File 'lib/rest-graph/core.rb', line 451

def exchange_sessions query={}, opts={}, &cb
  q = {:client_id => app_id, :client_secret => secret,
       :type => 'client_cred'}.merge(query)
  request(opts, [:post, url('oauth/exchange_sessions', q)], &cb)
end

#fbsObject



379
380
381
# File 'lib/rest-graph/core.rb', line 379

def fbs
  "#{fbs_without_sig(data).join('&')}&sig=#{calculate_sig(data)}"
end

#for_pages(hash, pages = 1, opts = {}, kind = :next_page, &cb) ⇒ Object



326
327
328
329
330
331
332
333
334
335
336
# File 'lib/rest-graph/core.rb', line 326

def for_pages hash, pages=1, opts={}, kind=:next_page, &cb
  if pages > 1
    merge_data(send(kind, hash, opts){ |result|
      yield(result.freeze) if block_given?
      for_pages(result, pages - 1, opts, kind, &cb) if result
    }, hash)
  else
    yield(nil) if block_given?
    hash
  end
end

#fql(code, query = {}, opts = {}, &cb) ⇒ Object



442
443
444
# File 'lib/rest-graph/core.rb', line 442

def fql code, query={}, opts={}, &cb
  old_rest('fql.query', {:query => code}.merge(query), opts, &cb)
end

#fql_multi(codes, query = {}, opts = {}, &cb) ⇒ Object



446
447
448
449
# File 'lib/rest-graph/core.rb', line 446

def fql_multi codes, query={}, opts={}, &cb
  old_rest('fql.multiquery',
    {:queries => self.class.json_encode(codes)}.merge(query), opts, &cb)
end

#get(path, query = {}, opts = {}, &cb) ⇒ Object

extra options:

auto_decode: Bool # decode with json or not in this API request
                  # default: auto_decode in rest-graph instance
    timeout: Int  # the timeout for this API request
                  # default: timeout in rest-graph instance
     secret: Bool # use secret_acccess_token or not
                  # default: false
      cache: Bool # use cache or not; if it's false, update cache, too
                  # default: true
 expires_in: Int  # control when would the cache be expired
                  # default: nil
      async: Bool # use eventmachine for http client or not
                  # default: false, but true in aget family
    headers: Hash # additional hash you want to pass
                  # default: {}


262
263
264
# File 'lib/rest-graph/core.rb', line 262

def get    path, query={}, opts={}, &cb
  request(opts, [:get   , url(path, query, graph_server, opts)], &cb)
end

#inspectObject



229
230
231
232
# File 'lib/rest-graph/core.rb', line 229

def inspect
  "#<struct RestGraph #{attributes.map{ |k, v|
    "#{k}=#{v.inspect}" }.join(', ')}>"
end

#lighten(o = {}) ⇒ Object



225
226
227
# File 'lib/rest-graph/core.rb', line 225

def lighten o={}
  dup.lighten!(o)
end

#lighten!(o = {}) ⇒ Object



218
219
220
221
222
223
# File 'lib/rest-graph/core.rb', line 218

def lighten! o={}
  [:cache, :log_method, :log_handler, :error_handler].each{ |obj|
    send("#{obj}=", false) }
  send(:initialize, o)
  self
end

#multi(reqs, opts = {}, &cb) ⇒ Object



298
299
300
301
302
303
# File 'lib/rest-graph/core.rb', line 298

def multi reqs, opts={}, &cb
  request({:async => true}.merge(opts),
    *reqs.map{ |(meth, path, query, payload)|
      [meth, url(path, query || {}, graph_server, opts), payload]
    }, &cb)
end

#next_page(hash, opts = {}, &cb) ⇒ Object



309
310
311
312
313
314
315
# File 'lib/rest-graph/core.rb', line 309

def next_page hash, opts={}, &cb
  if hash['paging'].kind_of?(Hash) && hash['paging']['next']
    request(opts, [:get, URI.encode(hash['paging']['next'])], &cb)
  else
    yield(nil) if block_given?
  end
end

#old_rest(path, query = {}, opts = {}, &cb) ⇒ Object

old rest facebook api, i will definitely love to remove them someday



423
424
425
426
427
428
429
430
431
432
433
434
435
436
# File 'lib/rest-graph/core.rb', line 423

def old_rest path, query={}, opts={}, &cb
  uri = url("method/#{path}", {:format => 'json'}.merge(query),
            old_server, opts)
  if opts[:post]
    request(
      opts.merge(:uri => uri),
      [:post,
       url("method/#{path}", {:format => 'json'}, old_server, opts),
       query],
      &cb)
  else
    request(opts, [:get, uri], &cb)
  end
end

#parse_cookies!(cookies) ⇒ Object



349
350
351
352
353
354
355
# File 'lib/rest-graph/core.rb', line 349

def parse_cookies! cookies
  self.data = if   fbsr = cookies["fbsr_#{app_id}"]
                parse_fbsr!(fbsr)
              else fbs  = cookies["fbs_#{app_id}"]
                parse_fbs!(fbs)
              end
end

#parse_fbs!(fbs) ⇒ Object



357
358
359
360
361
# File 'lib/rest-graph/core.rb', line 357

def parse_fbs! fbs
  self.data = check_sig_and_return_data(
    # take out facebook sometimes there but sometimes not quotes in cookies
    Rack::Utils.parse_query(fbs.to_s.sub(/^"/, '').sub(/"$/, '')))
end

#parse_fbsr!(fbsr) ⇒ Object



363
364
365
366
367
368
369
370
# File 'lib/rest-graph/core.rb', line 363

def parse_fbsr! fbsr
  old_data = parse_signed_request!(fbsr)
  # beware! maybe facebook would take out the code someday
  return self.data = old_data unless old_data && old_data['code']
  # passing empty redirect_uri is needed!
  authorize!(:code => old_data['code'], :redirect_uri => '')
  self.data = old_data.merge(data)
end

#parse_json!(json) ⇒ Object



372
373
374
375
376
377
# File 'lib/rest-graph/core.rb', line 372

def parse_json! json
  self.data = json &&
    check_sig_and_return_data(self.class.json_decode(json))
rescue ParseError
  self.data = nil
end

#parse_rack_env!(env) ⇒ Object

cookies, app_id, secrect related below



344
345
346
347
# File 'lib/rest-graph/core.rb', line 344

def parse_rack_env! env
  env['HTTP_COOKIE'].to_s =~ /fbs_#{app_id}=([^\;]+)/
  self.data = parse_fbs!($1)
end

#parse_signed_request!(request) ⇒ Object

facebook's new signed_request…



385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'lib/rest-graph/core.rb', line 385

def parse_signed_request! request
  sig_encoded, json_encoded = request.split('.')
  return self.data = nil unless sig_encoded && json_encoded
  sig,  json = [sig_encoded, json_encoded].map{ |str|
    "#{str.tr('-_', '+/')}==".unpack('m').first
  }
  self.data = check_sig_and_return_data(
                self.class.json_decode(json).merge('sig' => sig)){
                  self.class.hmac_sha256(secret, json_encoded)
                }
rescue ParseError
  self.data = nil
end

#post(path, payload = {}, query = {}, opts = {}, &cb) ⇒ Object



270
271
272
273
# File 'lib/rest-graph/core.rb', line 270

def post   path, payload={}, query={}, opts={}, &cb
  request(opts, [:post  , url(path, query, graph_server, opts), payload],
          &cb)
end

#prev_page(hash, opts = {}, &cb) ⇒ Object Also known as: previous_page



317
318
319
320
321
322
323
# File 'lib/rest-graph/core.rb', line 317

def prev_page hash, opts={}, &cb
  if hash['paging'].kind_of?(Hash) && hash['paging']['previous']
    request(opts, [:get, URI.encode(hash['paging']['previous'])], &cb)
  else
    yield(nil) if block_given?
  end
end

#put(path, payload = {}, query = {}, opts = {}, &cb) ⇒ Object



275
276
277
278
# File 'lib/rest-graph/core.rb', line 275

def put    path, payload={}, query={}, opts={}, &cb
  request(opts, [:put   , url(path, query, graph_server, opts), payload],
          &cb)
end

#request(opts, *reqs, &cb) ⇒ Object



461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'lib/rest-graph/core.rb', line 461

def request opts, *reqs, &cb
  Timeout.timeout(opts[:timeout] || timeout){
    reqs.each{ |(meth, uri, payload)|
      next if meth != :get     # only get result would get cached
      cache_assign(opts, uri, nil)
    } if opts[:cache] == false # remove cache if we don't want it

    if opts[:async]
      request_em(opts, reqs, &cb)
    else
      request_rc(opts, *reqs.first, &cb)
    end
  }
end

#secret_access_tokenObject



214
215
216
# File 'lib/rest-graph/core.rb', line 214

def secret_access_token
  "#{app_id}|#{secret}"
end

#secret_old_rest(path, query = {}, opts = {}, &cb) ⇒ Object



438
439
440
# File 'lib/rest-graph/core.rb', line 438

def secret_old_rest path, query={}, opts={}, &cb
  old_rest(path, query, {:secret => true}.merge(opts), &cb)
end

#url(path, query = {}, server = graph_server, opts = {}) ⇒ Object

graph api related methods



243
244
245
# File 'lib/rest-graph/core.rb', line 243

def url path, query={}, server=graph_server, opts={}
  "#{server}#{path}#{build_query_string(query, opts)}"
end