mmangino-facebooker 1.0.37 → 1.0.38

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -56,6 +56,12 @@ Your application users will need to have added the application in facebook to ac
56
56
 
57
57
  to your application controller.
58
58
 
59
+ To prevent a violation of Facebook Terms of Service while reducing log bloat, you should also add
60
+
61
+ filter_parameter_logging :fb_sig_friends
62
+
63
+ to your application controller.
64
+
59
65
  == using MemCache session
60
66
 
61
67
  Facebook uses some non alphanum characters in the session identifier which interfere with memcache stored sessions. If you want to use MemCache for storing sessions, you can override the valid session id method on memcache by placing the following code in an initializer:
data/facebooker.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{facebooker}
5
- s.version = "1.0.37"
5
+ s.version = "1.0.38"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Chad Fowler", "Patrick Ewing", "Mike Mangino", "Shane Vitarana", "Corey Innis"]
9
- s.date = %q{2009-06-04}
9
+ s.date = %q{2009-06-23}
10
10
  s.description = %q{Facebooker is a Ruby wrapper over the Facebook[http://facebook.com] {REST API}[http://wiki.developers.facebook.com/index.php/API]. Its goals are: * Idiomatic Ruby * No dependencies outside of the Ruby standard library (This is true with Rails 2.1. Previous Rails versions require the JSON gem) * Concrete classes and methods modeling the Facebook data, so it's easy for a Rubyist to understand what's available * Well tested}
11
11
  s.email = %q{mmangino@elevatedrails.com}
12
12
  s.extra_rdoc_files = ["Manifest.txt", "CHANGELOG.rdoc", "COPYING.rdoc", "README.rdoc", "TODO.rdoc"]
@@ -46,6 +46,7 @@ function encodeURIComponent(str) {
46
46
  }
47
47
  };
48
48
 
49
+ var Form = {};
49
50
  Form.serialize = function(form_element) {
50
51
  return $(form_element).serialize();
51
52
  };
@@ -68,6 +69,15 @@ Ajax.Updater = function (container,url,options) {
68
69
  this.ajax.onerror = options["onFailure"];
69
70
  }
70
71
 
72
+ if (!options['parameters']) {
73
+ options['parameters'] = {}
74
+ }
75
+
76
+ // simulate other verbs over post
77
+ if (options['method']) {
78
+ options['parameters']['_method'] = options['method'];
79
+ }
80
+
71
81
  this.ajax.post(url,options['parameters']);
72
82
  if (options["onLoading"]) {
73
83
  options["onLoading"].call()
data/init.rb CHANGED
@@ -21,5 +21,6 @@ if defined? Rails
21
21
  require 'facebooker/rails/facebook_url_helper'
22
22
  require 'facebooker/rails/extensions/rack_setup' if Rails.version > '2.3'
23
23
  require 'facebooker/rails/extensions/action_controller'
24
+ #require 'facebooker/rails/extensions/action_view'
24
25
  require 'facebooker/rails/extensions/routing'
25
26
  end
@@ -131,6 +131,19 @@ module Facebooker
131
131
  :action_links => options[:action_links]
132
132
  )
133
133
  end
134
+
135
+
136
+ ###
137
+ # Publish a comment on a post
138
+ #
139
+ # See: http://wiki.developers.facebook.com/index.php/Stream.addComment
140
+ #
141
+ # +post_id+ the post_id for the post that is being commented on
142
+ # +comment+ the text of the comment
143
+ def comment_on(post_id, comment)
144
+ @session.post('facebook.stream.addComment', {:post_id=>post_id, :comment=>comment})
145
+ end
146
+
134
147
 
135
148
  def friend_lists
136
149
  @friend_lists ||= @session.post('facebook.friends.getLists').map do |hash|
@@ -351,6 +364,12 @@ module Facebooker
351
364
  session.post('facebook.users.hasAppPermission',:ext_perm=>ext_perm) == "1"
352
365
  end
353
366
 
367
+ ##
368
+ # Convenience method to check multiple permissions at once
369
+ def has_permissions?(ext_perms)
370
+ ext_perms.all?{|p| has_permission?(p)}
371
+ end
372
+
354
373
  ##
355
374
  # Convenience method to send email to the current user
356
375
  def send_email(subject, text=nil, fbml=nil)
@@ -58,8 +58,13 @@ module Facebooker
58
58
  def self.element(name, data)
59
59
  data = data.body rescue data # either data or an HTTP response
60
60
  begin
61
- node = Nokogiri::XML(data.strip).at(name)
62
- return node if node
61
+ xml = Nokogiri::XML(data.strip).at(name)
62
+ if node = xml.at(name)
63
+ return node
64
+ end
65
+ if xml.root.name == name
66
+ return xml.root
67
+ end
63
68
  rescue # Can't parse with Nokogiri
64
69
  doc = REXML::Document.new(data)
65
70
  doc.elements.each(name) do |element|
@@ -205,6 +210,12 @@ module Facebooker
205
210
  element('stream_publish_response', data).content.strip
206
211
  end
207
212
  end
213
+
214
+ class StreamAddComment < Parser#:nodoc:
215
+ def self.process(data)
216
+ element('stream_addComment_response', data).content.strip
217
+ end
218
+ end
208
219
 
209
220
  class RegisterTemplateBundle < Parser#:nodoc:
210
221
  def self.process(data)
@@ -399,6 +410,25 @@ module Facebooker
399
410
  end
400
411
  end
401
412
 
413
+ class FqlMultiquery < Parser#nodoc
414
+ def self.process(data)
415
+ root = element('fql_multiquery_response', data)
416
+ root.elements.collect do |elm|
417
+ [
418
+ elm.elements[1].text,
419
+ if elm.elements[2].elements[1].nil?
420
+ []
421
+ else
422
+ [
423
+ elm.elements[2].elements[1].name,
424
+ array_of_hashes(elm.elements[2], elm.elements[2].elements[1].name)
425
+ ]
426
+ end
427
+ ]
428
+ end
429
+ end
430
+ end
431
+
402
432
  class SetRefHandle < Parser#:nodoc:
403
433
  def self.process(data)
404
434
  element('fbml_setRefHandle_response', data).content.strip
@@ -620,6 +650,7 @@ module Facebooker
620
650
  'facebook.admin.getAllocation' => GetAllocation,
621
651
  'facebook.batch.run' => BatchRun,
622
652
  'facebook.fql.query' => FqlQuery,
653
+ 'facebook.fql.multiquery' => FqlMultiquery,
623
654
  'facebook.photos.get' => GetPhotos,
624
655
  'facebook.photos.getAlbums' => GetAlbums,
625
656
  'facebook.photos.createAlbum' => CreateAlbum,
@@ -627,6 +658,7 @@ module Facebooker
627
658
  'facebook.photos.addTag' => AddTags,
628
659
  'facebook.photos.upload' => UploadPhoto,
629
660
  'facebook.stream.publish' => StreamPublish,
661
+ 'facebook.stream.addComment' => StreamAddComment,
630
662
  'facebook.events.get' => EventsGet,
631
663
  'facebook.groups.get' => GroupsGet,
632
664
  'facebook.events.getMembers' => EventMembersGet,
@@ -163,11 +163,15 @@ module Facebooker
163
163
  def after_facebook_login_url
164
164
  nil
165
165
  end
166
+
167
+ def default_after_facebook_login_url
168
+ url_for(:only_path => false, :overwrite_params => {})
169
+ end
166
170
 
167
171
  def create_new_facebook_session_and_redirect!
168
172
  session[:facebook_session] = new_facebook_session
169
- url_params = after_facebook_login_url.nil? ? {} : {:next=>after_facebook_login_url}
170
- top_redirect_to session[:facebook_session].login_url(url_params) unless @installation_required
173
+ next_url = after_facebook_login_url || default_after_facebook_login_url
174
+ top_redirect_to session[:facebook_session].login_url({:next => next_url}) unless @installation_required
171
175
  false
172
176
  end
173
177
 
@@ -298,8 +302,8 @@ module Facebooker
298
302
  end
299
303
 
300
304
  def application_is_not_installed_by_facebook_user
301
- url_params = after_facebook_login_url.nil? ? {} : { :next => after_facebook_login_url }
302
- top_redirect_to session[:facebook_session].install_url(url_params)
305
+ next_url = after_facebook_login_url || default_after_facebook_login_url
306
+ top_redirect_to session[:facebook_session].install_url({:next => next_url})
303
307
  end
304
308
 
305
309
  def set_facebook_request_format
@@ -2,5 +2,5 @@
2
2
  require 'rack/facebook'
3
3
  ActionController::Dispatcher.middleware.insert_before(
4
4
  ActionController::ParamsParser,
5
- Rack::Facebook,
6
- Facebooker.secret_key )
5
+ Rack::Facebook
6
+ )
@@ -22,9 +22,7 @@ module ::ActionController
22
22
  end
23
23
  alias_method_chain :xml_http_request?, :facebooker
24
24
  # we have to re-alias xhr? since it was pointing to the old method
25
- unless defined? :xhr?
26
- alias xhr? :xml_http_request?
27
- end
25
+ alias :xhr? :xml_http_request?
28
26
 
29
27
  end
30
28
  end
@@ -25,7 +25,7 @@ module ::ActionController
25
25
  alias_method_chain :xml_http_request?, :facebooker
26
26
 
27
27
  # we have to re-alias xhr? since it was pointing to the old method
28
- alias xhr? :xml_http_request?
28
+ alias :xhr? :xml_http_request?
29
29
 
30
30
  end
31
31
  end
@@ -24,6 +24,14 @@ module Facebooker
24
24
  end
25
25
  end
26
26
 
27
+ def fb_iframe(src, options = {})
28
+ content_tag "fb:iframe", '', options.merge({ :src => src })
29
+ end
30
+
31
+ def fb_swf(src, options = {})
32
+ tag "fb:swf", options.merge(:swfsrc => src)
33
+ end
34
+
27
35
  def fb_dialog_title( title )
28
36
  content_tag "fb:dialog-title", title
29
37
  end
@@ -331,7 +339,8 @@ module Facebooker
331
339
  VALID_FB_SHARED_PHOTO_SIZES = [:thumb, :small, :normal, :square]
332
340
  VALID_FB_PHOTO_SIZES = VALID_FB_SHARED_PHOTO_SIZES
333
341
  VALID_FB_PROFILE_PIC_SIZES = VALID_FB_SHARED_PHOTO_SIZES
334
- VALID_PERMISSIONS=[:email, :offline_access, :status_update, :photo_upload, :create_listing, :create_event, :rsvp_event, :sms, :video_upload]
342
+ VALID_PERMISSIONS=[:email, :offline_access, :status_update, :photo_upload, :create_listing, :create_event, :rsvp_event, :sms, :video_upload,
343
+ :publish_stream, :read_stream]
335
344
 
336
345
  # Render an fb:tabs tag containing some number of fb:tab_item tags.
337
346
  # Example:
@@ -639,20 +648,22 @@ module Facebooker
639
648
  #
640
649
  # You can prompt a user with the following permissions:
641
650
  # * email
651
+ # * read_stream
652
+ # * publish_stream
642
653
  # * offline_access
643
654
  # * status_update
644
655
  # * photo_upload
645
- # * video_upload
646
- # * create_listing
647
656
  # * create_event
648
657
  # * rsvp_event
649
658
  # * sms
650
- #
659
+ # * video_upload
660
+ # * create_note
661
+ # * share_item
651
662
  # Example:
652
663
  # <%= fb_prompt_permission('email', "Would you like to receive email from our application?" ) %>
653
664
  #
654
665
  # See http://wiki.developers.facebook.com/index.php/Fb:prompt-permission for
655
- # more details
666
+ # more details. Correct as of 7th June 2009.
656
667
  #
657
668
  def fb_prompt_permission(permission,message,callback=nil)
658
669
  raise(ArgumentError, "Unknown value for permission: #{permission}") unless VALID_PERMISSIONS.include?(permission.to_sym)
@@ -661,6 +672,19 @@ module Facebooker
661
672
  content_tag("fb:prompt-permission",message,args)
662
673
  end
663
674
 
675
+ # Renders a link to prompt for multiple permissions at once.
676
+ #
677
+ # Example:
678
+ # <%= fb_prompt_permissions(['email','offline_access','status_update'], 'Would you like to grant some permissions?')
679
+ def fb_prompt_permissions(permissions,message,callback=nil)
680
+ permissions.each do |p|
681
+ raise(ArgumentError, "Unknown value for permission: #{p}") unless VALID_PERMISSIONS.include?(p.to_sym)
682
+ end
683
+ args={:perms=>permissions*','}
684
+ args[:next_fbjs]=callback unless callback.nil?
685
+ content_tag("fb:prompt-permission",message,args)
686
+ end
687
+
664
688
  # Renders an <fb:eventlink /> tag that displays the event name and links to the event's page.
665
689
  def fb_eventlink(eid)
666
690
  content_tag "fb:eventlink",nil,:eid=>eid
@@ -98,7 +98,11 @@ module Facebooker
98
98
  @from = nil
99
99
  @full_story_template = nil
100
100
  @recipients = nil
101
- @controller = PublisherController.new
101
+ @controller = PublisherController.new(self)
102
+ end
103
+
104
+ def default_url_options
105
+ {:host => Facebooker.canvas_server_base + Facebooker.facebook_path_prefix}
102
106
  end
103
107
 
104
108
  # use facebook options everywhere
@@ -122,6 +126,8 @@ module Facebooker
122
126
  end
123
127
  end
124
128
 
129
+
130
+
125
131
  class << self
126
132
 
127
133
  def register(klass,method)
@@ -490,11 +496,7 @@ module Facebooker
490
496
 
491
497
  should_send ? publisher.send_message(method) : publisher._body
492
498
  end
493
-
494
- def default_url_options
495
- {:host => Facebooker.canvas_server_base + Facebooker.facebook_path_prefix}
496
- end
497
-
499
+
498
500
  def controller_path
499
501
  self.to_s.underscore
500
502
  end
@@ -528,11 +530,16 @@ module Facebooker
528
530
  class PublisherController
529
531
  include Facebooker::Rails::Publisher.master_helper_module
530
532
  include ActionController::UrlWriter
533
+
534
+ def initialize(source)
535
+ self.class.url_option_source = source
536
+ end
531
537
 
532
538
  class << self
539
+ attr_accessor :url_option_source
533
540
  alias :old_default_url_options :default_url_options
534
541
  def default_url_options(*args)
535
- Facebooker::Rails::Publisher.default_url_options(*args)
542
+ url_option_source.default_url_options(*args)
536
543
  end
537
544
  end
538
545
 
@@ -193,30 +193,55 @@ module Facebooker
193
193
  @secret_from_session = secret_from_session
194
194
  end
195
195
 
196
+ def fql_build_object(type, hash)
197
+ case type
198
+ when 'user'
199
+ user = User.new
200
+ user.session = self
201
+ user.populate_from_hash!(hash)
202
+ user
203
+ when 'photo'
204
+ Photo.from_hash(hash)
205
+ when 'page'
206
+ Page.from_hash(hash)
207
+ when 'page_admin'
208
+ Page.from_hash(hash)
209
+ when 'group'
210
+ Group.from_hash(hash)
211
+ when 'event_member'
212
+ Event::Attendance.from_hash(hash)
213
+ else
214
+ hash
215
+ end
216
+ end
217
+
196
218
  def fql_query(query, format = 'XML')
197
219
  post('facebook.fql.query', :query => query, :format => format) do |response|
198
220
  type = response.shift
199
221
  return [] if type.nil?
200
222
  response.shift.map do |hash|
201
- case type
202
- when 'user'
203
- user = User.new
204
- user.session = self
205
- user.populate_from_hash!(hash)
206
- user
207
- when 'photo'
208
- Photo.from_hash(hash)
209
- when 'page'
210
- Page.from_hash(hash)
211
- when 'page_admin'
212
- Page.from_hash(hash)
213
- when 'event_member'
214
- Event::Attendance.from_hash(hash)
215
- else
216
- hash
223
+ fql_build_object(type, hash)
224
+ end
225
+ end
226
+ end
227
+
228
+ def fql_multiquery(queries, format = 'XML')
229
+ results = {}
230
+ post('facebook.fql.multiquery', :queries => queries.to_json, :format => format) do |responses|
231
+ responses.each do |response|
232
+ name = response.shift
233
+ response = response.shift
234
+ type = response.shift
235
+ value = []
236
+ unless type.nil?
237
+ value = response.shift.map do |hash|
238
+ fql_build_object(type, hash)
239
+ end
217
240
  end
241
+ results[name] = value
218
242
  end
219
243
  end
244
+ results
220
245
  end
221
246
 
222
247
  def user
@@ -2,7 +2,7 @@ module Facebooker #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
4
  MINOR = 0
5
- TINY = 37
5
+ TINY = 38
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/facebooker.rb CHANGED
@@ -27,6 +27,7 @@ require 'digest/md5'
27
27
  module Facebooker
28
28
 
29
29
  @facebooker_configuration = {}
30
+ @raw_facebooker_configuration = {}
30
31
  @current_adapter = nil
31
32
  @set_asset_host_to_callback_url = true
32
33
  @path_prefix = nil
@@ -37,11 +38,12 @@ module Facebooker
37
38
  def load_configuration(facebooker_yaml_file)
38
39
  if File.exist?(facebooker_yaml_file)
39
40
  if defined? RAILS_ENV
40
- config = YAML.load_file(facebooker_yaml_file)[RAILS_ENV]
41
+ @raw_facebooker_configuration = YAML.load_file(facebooker_yaml_file)[RAILS_ENV]
41
42
  else
42
- config = YAML.load_file(facebooker_yaml_file)
43
+ @raw_facebooker_configuration = YAML.load_file(facebooker_yaml_file)
43
44
  end
44
- apply_configuration(config)
45
+ Thread.current[:fb_api_config] = @raw_facebooker_configuration unless Thread.current[:fb_api_config]
46
+ apply_configuration(@raw_facebooker_configuration)
45
47
  end
46
48
  end
47
49
 
@@ -67,6 +69,41 @@ module Facebooker
67
69
  @facebooker_configuration
68
70
  end
69
71
 
72
+ def with_application(api_key, &block)
73
+ config = fetch_config_for( api_key )
74
+
75
+ unless config
76
+ self.logger.info "Can't find facebooker config: '#{api_key}'" if self.logger
77
+ yield if block_given?
78
+ return
79
+ end
80
+
81
+ # Save the old config to handle nested activation
82
+ old = Thread.current[:fb_api_config].dup rescue false
83
+
84
+ if block_given?
85
+ begin
86
+ self.logger.info "Swapping facebooker config: '#{api_key}'" if self.logger
87
+ Thread.current[:fb_api_config] = apply_configuration(config)
88
+ yield
89
+ ensure
90
+ Thread.current[:fb_api_config] = old if old
91
+ apply_configuration(Thread.current[:fb_api_config])
92
+ end
93
+ end
94
+ end
95
+
96
+ def fetch_config_for(api_key)
97
+ if @raw_facebooker_configuration['api_key'] == api_key
98
+ return @raw_facebooker_configuration
99
+ elsif @raw_facebooker_configuration['alternative_keys'] and
100
+ @raw_facebooker_configuration['alternative_keys'].keys.include?(api_key)
101
+ return @raw_facebooker_configuration['alternative_keys'][api_key].merge(
102
+ 'api_key' => api_key )
103
+ end
104
+ return false
105
+ end
106
+
70
107
  # TODO: This should be converted to attr_accessor, but we need to
71
108
  # get all the require statements at the top of the file to work.
72
109
 
data/lib/rack/facebook.rb CHANGED
@@ -24,9 +24,8 @@ module Rack
24
24
  # end
25
25
  #
26
26
  class Facebook
27
- def initialize(app, secret_key, &condition)
27
+ def initialize(app, &condition)
28
28
  @app = app
29
- @secret_key = secret_key
30
29
  @condition = condition
31
30
  end
32
31
 
@@ -35,14 +34,20 @@ module Rack
35
34
  request = Rack::Request.new(env)
36
35
  fb_params = extract_fb_sig_params(request.POST)
37
36
  unless fb_params.empty?
38
- unless signature_is_valid?(fb_params, request.POST['fb_sig'])
39
- return Rack::Response.new(["Invalid Facebook signature"], 400).finish
37
+ Facebooker.with_application(fb_params['api_key']) do
38
+ unless signature_is_valid?(fb_params, request.POST['fb_sig'])
39
+ return Rack::Response.new(["Invalid Facebook signature"], 400).finish
40
+ end
41
+ env['REQUEST_METHOD'] = fb_params["request_method"] if fb_params["request_method"]
42
+ convert_parameters!(request.POST)
43
+ @app.call(env)
40
44
  end
41
- env['REQUEST_METHOD'] = fb_params["request_method"] if fb_params["request_method"]
42
- convert_parameters!(request.POST)
45
+ else
46
+ @app.call(env)
43
47
  end
48
+ else
49
+ @app.call(env)
44
50
  end
45
- @app.call(env)
46
51
  end
47
52
 
48
53
  private
@@ -56,7 +61,7 @@ module Rack
56
61
 
57
62
  def signature_is_valid?(fb_params, actual_sig)
58
63
  raw_string = fb_params.map{ |*args| args.join('=') }.sort.join
59
- expected_signature = Digest::MD5.hexdigest([raw_string, @secret_key].join)
64
+ expected_signature = Digest::MD5.hexdigest([raw_string, Facebooker.secret_key].join)
60
65
  actual_sig == expected_signature
61
66
  end
62
67
 
@@ -74,4 +79,4 @@ module Rack
74
79
  end
75
80
  end
76
81
  end
77
- end
82
+ end
@@ -93,4 +93,82 @@ class Facebooker::AdaptersTest < Test::Unit::TestCase
93
93
  def test_bebo_process_data
94
94
 
95
95
  end
96
+
97
+ def test_fetch_config_for_can_find_top_level_api_key
98
+ old = Facebooker.instance_variable_get('@raw_facebooker_configuration')
99
+ # Now that we've backed up the old value...
100
+ raw_fb_config = { 'api_key' => 'a key' }
101
+ Facebooker.instance_variable_set('@raw_facebooker_configuration', raw_fb_config)
102
+ assert_equal Facebooker.fetch_config_for( 'a key' ), raw_fb_config
103
+ ensure
104
+ # Put the old value back
105
+ Facebooker.instance_variable_set('@raw_facebooker_configuration', old)
106
+ end
107
+
108
+ def test_fetch_config_for_can_find_deep_api_key
109
+ old = Facebooker.instance_variable_get('@raw_facebooker_configuration')
110
+ # Now that we've backed up the old value...
111
+ raw_fb_config = { 'api_key' => 'a key',
112
+ 'alternative_keys' => {
113
+ 'another key' => { 'secret_key' => 'sdfsd' },
114
+ 'yet another key' => { 'secret_key' => '9ho2h' } } }
115
+ Facebooker.instance_variable_set('@raw_facebooker_configuration', raw_fb_config)
116
+ assert_equal raw_fb_config['alternative_keys']['another key'].merge( 'api_key' => 'another key' ),
117
+ Facebooker.fetch_config_for( 'another key' )
118
+ ensure
119
+ # Put the old value back
120
+ Facebooker.instance_variable_set('@raw_facebooker_configuration', old)
121
+ end
122
+
123
+ def test_fetch_config_for_returns_false_if_no_apikey_found
124
+ old = Facebooker.instance_variable_get('@raw_facebooker_configuration')
125
+ # Now that we've backed up the old value...
126
+ raw_fb_config = { 'api_key' => 'a key' }
127
+ Facebooker.instance_variable_set('@raw_facebooker_configuration', raw_fb_config)
128
+ assert ! Facebooker.fetch_config_for( 'another key' )
129
+ ensure
130
+ # Put the old value back
131
+ Facebooker.instance_variable_set('@raw_facebooker_configuration', old)
132
+ end
133
+
134
+ def test_with_application_yields_if_no_config_is_found
135
+ flexmock( Facebooker ).
136
+ should_receive( :fetch_config_for ).
137
+ and_return( false )
138
+ # Is there a better way to assert the block is yielded?
139
+ @changes_to_true = false
140
+ Facebooker.with_application('somekey not found') do
141
+ @changes_to_true = true
142
+ end
143
+ assert @changes_to_true
144
+ end
145
+
146
+ def test_with_application_changes_config_inside_block
147
+ flexmock( Facebooker ).
148
+ should_receive( :fetch_config_for ).
149
+ and_return({ 'api_key' => 'a key',
150
+ 'secret_key' => 'my secret key' })
151
+ Facebooker.with_application('a key') do
152
+ @secret_in_block = Facebooker.secret_key
153
+ end
154
+ # Check outside the block, assures the assertion gets run
155
+ assert_equal 'my secret key', @secret_in_block
156
+ end
157
+
158
+ def test_with_application_restores_last_config_outside_block
159
+ flexmock( Facebooker ).
160
+ should_receive( :fetch_config_for ).
161
+ and_return( { 'api_key' => 'a key',
162
+ 'secret_key' => 'my secret key' },
163
+ { 'api_key' => 'another key',
164
+ 'secret_key' => 'my other secret key' } )
165
+ Facebooker.with_application('a key') do
166
+ Facebooker.with_application('another key') do
167
+ end
168
+ @secret_in_outer_block = Facebooker.secret_key
169
+ end
170
+ # Check outside the block, assures the assertion gets run
171
+ assert_equal 'my secret key', @secret_in_outer_block
172
+ end
173
+
96
174
  end
@@ -16,9 +16,14 @@ class Facebooker::UserTest < Test::Unit::TestCase
16
16
 
17
17
  def test_has_permission
18
18
  expect_http_posts_with_responses(has_app_permission_response_xml)
19
- assert @user.has_permission?("status_update")
19
+ assert @user.has_permission?("status_update")
20
20
  end
21
21
 
22
+ def test_has_permissions
23
+ expect_http_posts_with_responses(has_app_permission_response_xml, has_app_permission_response_xml)
24
+ assert @user.has_permissions?(["status_update", "read_stream"])
25
+ end
26
+
22
27
  def test_can_ask_user_if_he_or_she_is_friends_with_another_user
23
28
  assert(@user.friends_with?(@other_user))
24
29
  end
@@ -131,6 +136,12 @@ class Facebooker::UserTest < Test::Unit::TestCase
131
136
  @user.publish_to(@other_user, :message => 'i love you man')
132
137
  end
133
138
 
139
+ def test_comment_on
140
+ @user = Facebooker::User.new(548871286, @session)
141
+ expect_http_posts_with_responses(example_comment_on_response)
142
+ assert_equal('703826862_78463536863', @user.comment_on('703826862_78463536862', :message => 'that was hilarious!'))
143
+ end
144
+
134
145
  def test_can_send_email
135
146
  @user.expects(:send_email).with("subject", "body text")
136
147
  @user.send_email("subject", "body text")
@@ -340,4 +351,11 @@ class Facebooker::UserTest < Test::Unit::TestCase
340
351
  <stream_publish_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd">703826862_78463536862</stream_publish_response>
341
352
  eoxml
342
353
  end
354
+
355
+ def example_comment_on_response
356
+ <<-eoxml
357
+ <?xml version="1.0" encoding="UTF-8"?>
358
+ <stream_addComment_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd">703826862_78463536863</stream_addComment_response>
359
+ eoxml
360
+ end
343
361
  end
@@ -1,12 +1,13 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../../rails_test_helper')
2
-
2
+ require 'facebooker/rails/facebook_request_fix_2-3' if Rails.version >= '2.3'
3
3
  class Facebooker::Rails::FacebookRequestFix23Test < Test::Unit::TestCase
4
4
 
5
5
  def setup
6
6
  ENV['FACEBOOK_API_KEY'] = '1234567'
7
7
  ENV['FACEBOOK_SECRET_KEY'] = '7654321'
8
- if Rails.version < '2.3'
8
+ if Rails.version < '2.3'
9
9
  @request = ActionController::TestRequest.new({"fb_sig_is_ajax"=>"1"}, {}, nil)
10
+
10
11
  else
11
12
  @request = ActionController::TestRequest.new
12
13
  @request.query_parameters[:fb_sig_is_ajax] = "1"
@@ -441,7 +441,7 @@ class Facebooker::Rails::Publisher::PublisherTest < Test::Unit::TestCase
441
441
 
442
442
  def test_default_url_options
443
443
  Facebooker.expects(:facebook_path_prefix).returns("/mike")
444
- assert_equal({:host=>"apps.facebook.com/mike"},TestPublisher.default_url_options)
444
+ assert_equal({:host=>"apps.facebook.com/mike"},TestPublisher.new.default_url_options)
445
445
  end
446
446
 
447
447
  def test_recipients
@@ -259,13 +259,13 @@ class RailsIntegrationTestForApplicationInstallation < Test::Unit::TestCase
259
259
  def test_if_controller_requires_application_installation_unauthenticated_requests_will_redirect_to_install_page
260
260
  get :index
261
261
  assert_response :redirect
262
- assert_equal("http://www.facebook.com/install.php?api_key=1234567&v=1.0", @response.headers['Location'])
262
+ assert_equal("http://www.facebook.com/install.php?api_key=1234567&v=1.0&next=http%3A%2F%2Ftest.host%2Frequire_install", @response.headers['Location'])
263
263
  end
264
264
 
265
265
  def test_if_controller_requires_application_installation_authenticated_requests_without_installation_will_redirect_to_install_page
266
266
  get :index, facebook_params(:fb_sig_added => nil)
267
267
  assert_response :success
268
- assert_equal("<fb:redirect url=\"http://www.facebook.com/install.php?api_key=1234567&v=1.0\" />", @response.body)
268
+ assert(@response.body =~ /fb:redirect/)
269
269
  end
270
270
 
271
271
  def test_if_controller_requires_application_installation_authenticated_requests_with_installation_will_render
@@ -297,7 +297,7 @@ class RailsIntegrationTest < Test::Unit::TestCase
297
297
  def test_if_controller_requires_facebook_authentication_unauthenticated_requests_will_redirect
298
298
  get :index
299
299
  assert_response :redirect
300
- assert_equal("http://www.facebook.com/login.php?api_key=1234567&v=1.0", @response.headers['Location'])
300
+ assert_equal("http://www.facebook.com/login.php?api_key=1234567&v=1.0&next=http%3A%2F%2Ftest.host%2Frequire_auth", @response.headers['Location'])
301
301
  end
302
302
 
303
303
  def test_facebook_params_are_parsed_into_a_separate_hash
@@ -425,7 +425,7 @@ class RailsIntegrationTest < Test::Unit::TestCase
425
425
  def test_redirect_to_renders_fbml_redirect_tag_if_request_is_for_a_facebook_canvas
426
426
  get :index, facebook_params(:fb_sig_user => nil)
427
427
  assert_response :success
428
- assert_equal("<fb:redirect url=\"http://www.facebook.com/login.php?api_key=1234567&v=1.0\" />", @response.body)
428
+ assert @response.body =~ /fb:redirect/
429
429
  end
430
430
 
431
431
  def test_redirect_to_renders_javascript_redirect_if_request_is_for_a_facebook_iframe
@@ -433,7 +433,6 @@ class RailsIntegrationTest < Test::Unit::TestCase
433
433
  assert_response :success
434
434
  assert_match "javascript", @response.body
435
435
  assert_match "http-equiv", @response.body
436
- assert_match "http://www.facebook.com/login.php?api_key=1234567&v=1.0".to_json, @response.body
437
436
  assert_match "http://www.facebook.com/login.php?api_key=1234567&amp;v=1.0", @response.body
438
437
  end
439
438
 
@@ -643,6 +642,22 @@ class RailsHelperTest < Test::Unit::TestCase
643
642
 
644
643
  end
645
644
 
645
+ def test_fb_prompt_permissions_valid_no_callback
646
+ assert_equal "<fb:prompt-permission perms=\"publish_stream,read_stream\">Can I read and write your streams?</fb:prompt-permission>",
647
+ @h.fb_prompt_permissions(['publish_stream', 'read_stream'],"Can I read and write your streams?")
648
+ end
649
+
650
+ def test_fb_prompt_permissions_valid_with_callback
651
+ assert_equal "<fb:prompt-permission next_fbjs=\"do_stuff()\" perms=\"publish_stream,read_stream\">Can I read and write your streams?</fb:prompt-permission>",
652
+ @h.fb_prompt_permissions(['publish_stream', 'read_stream'],"Can I read and write your streams?", "do_stuff()")
653
+ end
654
+
655
+ def test_fb_prompt_permissions_invalid_option
656
+ assert_raises(ArgumentError) {@h.fb_prompt_permissions(["invliad", "read_stream"], "a message")}
657
+
658
+ end
659
+
660
+
646
661
  def test_fb_add_profile_section
647
662
  assert_equal "<fb:add-section-button section=\"profile\" />",@h.fb_add_profile_section
648
663
  end
@@ -29,12 +29,14 @@ class Facebooker::SessionTest < Test::Unit::TestCase
29
29
 
30
30
  def test_if_keys_are_not_available_via_environment_then_they_are_gotten_from_a_file
31
31
  ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'] = nil
32
+ Facebooker.instance_variable_set('@facebooker_configuration', nil)
32
33
  flexmock(File).should_receive(:read).with(File.expand_path("~/.facebookerrc")).once.and_return('{:api => "foo"}')
33
34
  assert_equal('foo', Facebooker::Session.api_key)
34
35
  end
35
36
 
36
37
  def test_if_environment_and_file_fail_to_match_then_an_exception_is_raised
37
38
  ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'] = nil
39
+ Facebooker.instance_variable_set('@facebooker_configuration', nil)
38
40
  flexmock(File).should_receive(:read).with(File.expand_path("~/.facebookerrc")).once.and_return {raise Errno::ENOENT, "No such file"}
39
41
  assert_raises(Facebooker::Session::ConfigurationMissing) {
40
42
  Facebooker::Session.api_key
@@ -160,6 +162,15 @@ class Facebooker::SessionTest < Test::Unit::TestCase
160
162
  assert_equal "Ari Steinberg", response.first.name
161
163
  end
162
164
 
165
+ def test_can_fql_multiquery_for_users_and_pictures
166
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
167
+ mock_http = establish_session
168
+ mock_http.should_receive(:post_form).and_return(example_fql_multiquery_xml).once.ordered(:posts)
169
+ response = @session.fql_multiquery({:query => 'SELECT name, pic FROM user WHERE uid=211031 OR uid=4801660'})
170
+ assert_kind_of Array, response["query1"]
171
+ assert_kind_of Facebooker::User, response["query1"].first
172
+ assert_equal "Ari Steinberg", response["query1"].first.name
173
+ end
163
174
 
164
175
  def test_can_send_notification_with_object
165
176
  @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
@@ -282,6 +293,33 @@ class Facebooker::SessionTest < Test::Unit::TestCase
282
293
 
283
294
  private
284
295
 
296
+ def example_fql_multiquery_xml
297
+ <<-XML
298
+ <?xml version="1.0" encoding="UTF-8"?>
299
+ <fql_multiquery_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
300
+ <fql_result>
301
+ <name>query1</name>
302
+ <results list="true">
303
+ <user>
304
+ <name>Ari Steinberg</name>
305
+ <uid>46903192</uid>
306
+ <rsvp_status xsi:nil="true"/>
307
+ </user>
308
+ </results>
309
+ </fql_result>
310
+ <fql_result>
311
+ <name>query2</name>
312
+ <results list="true">
313
+ <user>
314
+ <name>Lisa Petrovskaia</name>
315
+ <pic xsi:nil="true"/>
316
+ </user>
317
+ </results>
318
+ </fql_result>
319
+ </fql_multiquery_response>
320
+ XML
321
+ end
322
+
285
323
  def example_groups_get_xml
286
324
  <<-XML
287
325
  <?xml version="1.0" encoding="UTF-8"?>
@@ -6,12 +6,12 @@ require 'rack/mock'
6
6
  class Rack::FacebookTest < Test::Unit::TestCase
7
7
 
8
8
  def setup
9
- @secret_key = 'secret'
9
+ flexmock(Facebooker).should_receive(:secret_key).and_return('secret')
10
10
  @app = lambda do |env|
11
11
  @env = env
12
12
  Rack::Response.new().to_a
13
13
  end
14
- @facebook = Rack::Facebook.new(@app, @secret_key)
14
+ @facebook = Rack::Facebook.new(@app)
15
15
  end
16
16
 
17
17
  def params(p)
@@ -47,13 +47,13 @@ class Rack::FacebookTest < Test::Unit::TestCase
47
47
  end
48
48
 
49
49
  def test_skips_with_false_condition
50
- @facebook = Rack::Facebook.new(@app, @secret_key) { false }
50
+ @facebook = Rack::Facebook.new(@app) { false }
51
51
  response = app.post("/", :input => params(:fb_sig_user => 'ignored'))
52
52
  assert_equal 200, response.status
53
53
  end
54
54
 
55
55
  def test_verifies_with_true_condition
56
- @facebook = Rack::Facebook.new(@app, @secret_key) { true }
56
+ @facebook = Rack::Facebook.new(@app) { true }
57
57
  response = app.post("/", :input => params(:fb_sig_user => 'ignored'))
58
58
  assert_equal 400, response.status
59
59
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mmangino-facebooker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.37
4
+ version: 1.0.38
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chad Fowler
@@ -13,7 +13,7 @@ autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
15
 
16
- date: 2009-06-04 00:00:00 -07:00
16
+ date: 2009-06-23 00:00:00 -07:00
17
17
  default_executable:
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency