facebooker 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.txt +0 -0
- data/COPYING +19 -0
- data/History.txt +3 -0
- data/Manifest.txt +60 -0
- data/README +44 -0
- data/README.txt +79 -0
- data/Rakefile +38 -0
- data/TODO.txt +10 -0
- data/facebooker.yml.tpl +36 -0
- data/init.rb +52 -0
- data/install.rb +5 -0
- data/lib/facebooker.rb +63 -0
- data/lib/facebooker/affiliation.rb +10 -0
- data/lib/facebooker/album.rb +11 -0
- data/lib/facebooker/cookie.rb +10 -0
- data/lib/facebooker/data.rb +38 -0
- data/lib/facebooker/education_info.rb +11 -0
- data/lib/facebooker/event.rb +26 -0
- data/lib/facebooker/feed.rb +65 -0
- data/lib/facebooker/group.rb +35 -0
- data/lib/facebooker/location.rb +8 -0
- data/lib/facebooker/model.rb +118 -0
- data/lib/facebooker/notifications.rb +17 -0
- data/lib/facebooker/parser.rb +386 -0
- data/lib/facebooker/photo.rb +9 -0
- data/lib/facebooker/rails/controller.rb +174 -0
- data/lib/facebooker/rails/facebook_asset_path.rb +18 -0
- data/lib/facebooker/rails/facebook_form_builder.rb +112 -0
- data/lib/facebooker/rails/facebook_request_fix.rb +14 -0
- data/lib/facebooker/rails/facebook_session_handling.rb +58 -0
- data/lib/facebooker/rails/facebook_url_rewriting.rb +31 -0
- data/lib/facebooker/rails/helpers.rb +535 -0
- data/lib/facebooker/rails/routing.rb +49 -0
- data/lib/facebooker/rails/test_helpers.rb +11 -0
- data/lib/facebooker/rails/utilities.rb +22 -0
- data/lib/facebooker/server_cache.rb +24 -0
- data/lib/facebooker/service.rb +25 -0
- data/lib/facebooker/session.rb +385 -0
- data/lib/facebooker/tag.rb +12 -0
- data/lib/facebooker/user.rb +200 -0
- data/lib/facebooker/version.rb +9 -0
- data/lib/facebooker/work_info.rb +9 -0
- data/lib/net/http_multipart_post.rb +123 -0
- data/lib/tasks/facebooker.rake +16 -0
- data/lib/tasks/tunnel.rake +39 -0
- data/setup.rb +1585 -0
- data/test/event_test.rb +15 -0
- data/test/facebook_cache_test.rb +43 -0
- data/test/facebook_data_test.rb +50 -0
- data/test/facebooker_test.rb +766 -0
- data/test/fixtures/multipart_post_body_with_only_parameters.txt +33 -0
- data/test/fixtures/multipart_post_body_with_single_file.txt +38 -0
- data/test/fixtures/multipart_post_body_with_single_file_that_has_nil_key.txt +38 -0
- data/test/http_multipart_post_test.rb +54 -0
- data/test/model_test.rb +79 -0
- data/test/rails_integration_test.rb +732 -0
- data/test/session_test.rb +396 -0
- data/test/test_helper.rb +54 -0
- data/test/user_test.rb +101 -0
- metadata +130 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'facebooker'
|
2
|
+
module Facebooker
|
3
|
+
module Rails
|
4
|
+
module Controller
|
5
|
+
def self.included(controller)
|
6
|
+
controller.extend(ClassMethods)
|
7
|
+
controller.before_filter :set_fbml_format
|
8
|
+
controller.helper_attr :facebook_session_parameters
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def facebook_session
|
13
|
+
@facebook_session
|
14
|
+
end
|
15
|
+
|
16
|
+
def facebook_session_parameters
|
17
|
+
{:fb_sig_session_key=>params[:fb_sig_session_key]}
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def set_facebook_session
|
22
|
+
|
23
|
+
returning session_set = session_already_secured? || secure_with_token! || secure_with_facebook_params! do
|
24
|
+
if session_set
|
25
|
+
capture_facebook_friends_if_available!
|
26
|
+
Session.current = facebook_session
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def facebook_params
|
32
|
+
@facebook_params ||= verified_facebook_params
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def session_already_secured?
|
38
|
+
(@facebook_session = session[:facebook_session]) && session[:facebook_session].secured?
|
39
|
+
end
|
40
|
+
|
41
|
+
def secure_with_token!
|
42
|
+
if params['auth_token']
|
43
|
+
@facebook_session = new_facebook_session
|
44
|
+
@facebook_session.auth_token = params['auth_token']
|
45
|
+
@facebook_session.secure!
|
46
|
+
session[:facebook_session] = @facebook_session
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def secure_with_facebook_params!
|
51
|
+
return unless request_is_for_a_facebook_canvas?
|
52
|
+
|
53
|
+
if ['user', 'session_key'].all? {|element| facebook_params[element]}
|
54
|
+
@facebook_session = new_facebook_session
|
55
|
+
@facebook_session.secure_with!(facebook_params['session_key'], facebook_params['user'], facebook_params['expires'])
|
56
|
+
session[:facebook_session] = @facebook_session
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def create_new_facebook_session_and_redirect!
|
61
|
+
session[:facebook_session] = new_facebook_session
|
62
|
+
redirect_to session[:facebook_session].login_url unless @installation_required
|
63
|
+
false
|
64
|
+
end
|
65
|
+
|
66
|
+
def new_facebook_session
|
67
|
+
Facebooker::Session.create(Facebooker::Session.api_key, Facebooker::Session.secret_key)
|
68
|
+
end
|
69
|
+
|
70
|
+
def capture_facebook_friends_if_available!
|
71
|
+
return unless request_is_for_a_facebook_canvas?
|
72
|
+
if friends = facebook_params['friends']
|
73
|
+
facebook_session.user.friends = friends.map do |friend_uid|
|
74
|
+
User.new(friend_uid, facebook_session)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def blank?(value)
|
80
|
+
(value == '0' || value.nil? || value == '')
|
81
|
+
end
|
82
|
+
|
83
|
+
def verified_facebook_params
|
84
|
+
facebook_sig_params = params.inject({}) do |collection, pair|
|
85
|
+
collection[pair.first.sub(/^fb_sig_/, '')] = pair.last if pair.first[0,7] == 'fb_sig_'
|
86
|
+
collection
|
87
|
+
end
|
88
|
+
verify_signature(facebook_sig_params,params['fb_sig'])
|
89
|
+
|
90
|
+
facebook_sig_params.inject(HashWithIndifferentAccess.new) do |collection, pair|
|
91
|
+
collection[pair.first] = facebook_parameter_conversions[pair.first].call(pair.last)
|
92
|
+
collection
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def earliest_valid_session
|
97
|
+
48.hours.ago
|
98
|
+
end
|
99
|
+
|
100
|
+
def verify_signature(facebook_sig_params,expected_signature)
|
101
|
+
raw_string = facebook_sig_params.map{ |*args| args.join('=') }.sort.join
|
102
|
+
actual_sig = Digest::MD5.hexdigest([raw_string, Facebooker::Session.secret_key].join)
|
103
|
+
raise Facebooker::Session::IncorrectSignature if actual_sig != expected_signature
|
104
|
+
raise Facebooker::Session::SignatureTooOld if Time.at(facebook_sig_params['time'].to_f) < earliest_valid_session
|
105
|
+
true
|
106
|
+
end
|
107
|
+
|
108
|
+
def facebook_parameter_conversions
|
109
|
+
@facebook_parameter_conversions ||= Hash.new do |hash, key|
|
110
|
+
lambda{|value| value}
|
111
|
+
end.merge(
|
112
|
+
'time' => lambda{|value| Time.at(value.to_f)},
|
113
|
+
'in_canvas' => lambda{|value| !blank?(value)},
|
114
|
+
'added' => lambda{|value| !blank?(value)},
|
115
|
+
'expires' => lambda{|value| blank?(value) ? nil : Time.at(value.to_f)},
|
116
|
+
'friends' => lambda{|value| value.split(/,/)}
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
def redirect_to(*args)
|
121
|
+
if request_is_for_a_facebook_canvas?
|
122
|
+
render :text => fbml_redirect_tag(*args)
|
123
|
+
else
|
124
|
+
super
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def fbml_redirect_tag(url)
|
129
|
+
"<fb:redirect url=\"#{url_for(url)}\" />"
|
130
|
+
end
|
131
|
+
|
132
|
+
def request_is_for_a_facebook_canvas?
|
133
|
+
!params['fb_sig_in_canvas'].blank?
|
134
|
+
end
|
135
|
+
|
136
|
+
def application_is_installed?
|
137
|
+
facebook_params['added']
|
138
|
+
end
|
139
|
+
|
140
|
+
def ensure_authenticated_to_facebook
|
141
|
+
set_facebook_session || create_new_facebook_session_and_redirect!
|
142
|
+
end
|
143
|
+
|
144
|
+
def ensure_application_is_installed_by_facebook_user
|
145
|
+
@installation_required = true
|
146
|
+
returning ensure_authenticated_to_facebook && application_is_installed? do |authenticated_and_installed|
|
147
|
+
application_is_not_installed_by_facebook_user unless authenticated_and_installed
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def application_is_not_installed_by_facebook_user
|
152
|
+
redirect_to session[:facebook_session].install_url
|
153
|
+
end
|
154
|
+
|
155
|
+
def set_fbml_format
|
156
|
+
params[:format]="fbml" if request_is_for_a_facebook_canvas?
|
157
|
+
end
|
158
|
+
|
159
|
+
module ClassMethods
|
160
|
+
#
|
161
|
+
# Creates a filter which reqires a user to have already authenticated to
|
162
|
+
# Facebook before executing actions. Accepts the same optional options hash which
|
163
|
+
# before_filter and after_filter accept.
|
164
|
+
def ensure_authenticated_to_facebook(options = {})
|
165
|
+
before_filter :ensure_authenticated_to_facebook, options
|
166
|
+
end
|
167
|
+
|
168
|
+
def ensure_application_is_installed_by_facebook_user(options = {})
|
169
|
+
before_filter :ensure_application_is_installed_by_facebook_user, options
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# module ActionView
|
2
|
+
# module Helpers
|
3
|
+
# module AssetTagHelper
|
4
|
+
# def compute_public_path_with_facebooker(*args)
|
5
|
+
# public_path=compute_public_path_without_facebooker(*args)
|
6
|
+
# if public_path.starts_with?(ActionController::Base.asset_host)
|
7
|
+
# str=ActionController::Base.asset_host
|
8
|
+
# str += "/" unless str.ends_with?("/")
|
9
|
+
# public_path.gsub(/#{Regexp.escape(ActionController::Base.asset_host)}#{@controller.request.relative_url_root}\//,str)
|
10
|
+
# else
|
11
|
+
# public_path
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# alias_method_chain :compute_public_path, :facebooker
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
# end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Facebooker
|
2
|
+
module Rails
|
3
|
+
class FacebookFormBuilder < ActionView::Helpers::FormBuilder
|
4
|
+
|
5
|
+
|
6
|
+
second_param = %w(password_field file_field check_box date_select datetime_select time_select)
|
7
|
+
third_param = %w(radio_button country_select select time_zone_select)
|
8
|
+
fifth_param = %w(collection_select)
|
9
|
+
|
10
|
+
def self.create_with_offset(name,offset)
|
11
|
+
define_method name do |field,*args|
|
12
|
+
options = args[offset] || {}
|
13
|
+
build_shell(field,options) do
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
second_param.each do |name|
|
20
|
+
create_with_offset(name,0)
|
21
|
+
end
|
22
|
+
third_param.each do |name|
|
23
|
+
create_with_offset(name,1)
|
24
|
+
end
|
25
|
+
fifth_param.each do |name|
|
26
|
+
create_with_offset(name,3)
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_shell(field,options)
|
30
|
+
@template.content_tag "fb:editor-custom", :label=>label_for(field,options) do
|
31
|
+
yield
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def label_for(field,options)
|
36
|
+
options[:label] || field.to_s.humanize
|
37
|
+
end
|
38
|
+
|
39
|
+
def text(string,options={})
|
40
|
+
@template.content_tag "fb:editor-custom",string, :label=>label_for("",options)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def text_field(method, options = {})
|
45
|
+
options[:label] ||= label_for(method,options)
|
46
|
+
add_default_name_and_id(options,method)
|
47
|
+
options["value"] ||= value_before_type_cast(object,method)
|
48
|
+
@template.content_tag("fb:editor-text","",options)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def text_area(method, options = {})
|
53
|
+
options[:label] ||= label_for(method,options)
|
54
|
+
add_default_name_and_id(options,method)
|
55
|
+
@template.content_tag("fb:editor-textarea",value_before_type_cast(object,method),options)
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Build a text input area that uses typeahed
|
60
|
+
# options are like collection_select
|
61
|
+
def collection_typeahead(method,collection,value_method,text_method,options={})
|
62
|
+
build_shell(method,options) do
|
63
|
+
collection_typeahead_internal(method,collection,value_method,text_method,options)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def collection_typeahead_internal(method,collection,value_method,text_method,options={})
|
68
|
+
option_values = collection.map do |item|
|
69
|
+
value=item.send(value_method)
|
70
|
+
text=item.send(text_method)
|
71
|
+
@template.content_tag "fb:typeahead-option",text,:value=>value
|
72
|
+
end.join
|
73
|
+
add_default_name_and_id(options,method)
|
74
|
+
options["value"] ||= value_before_type_cast(object,method)
|
75
|
+
@template.content_tag("fb:typeahead-input",option_values,options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def value_before_type_cast(object,method)
|
79
|
+
unless object.nil?
|
80
|
+
method_name = method.to_s
|
81
|
+
object.respond_to?(method_name + "_before_type_cast") ?
|
82
|
+
object.send(method_name + "_before_type_cast") :
|
83
|
+
object.send(method_name)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def multi_friend_input(options={})
|
88
|
+
build_shell(:friends,options) do
|
89
|
+
@template.content_tag("fb:multi-friend-input","",options)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def buttons(*names)
|
94
|
+
buttons=names.map do |name|
|
95
|
+
create_button(name)
|
96
|
+
end.join
|
97
|
+
|
98
|
+
@template.content_tag "fb:editor-buttonset",buttons
|
99
|
+
end
|
100
|
+
|
101
|
+
def create_button(name)
|
102
|
+
@template.content_tag("fb:editor-button","",:value=>name)
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_default_name_and_id(options,method)
|
106
|
+
options[:name] = "#{object.class.name.downcase}[#{method}]"
|
107
|
+
options[:id] ||= "#{object.class.name.downcase}_#{method}"
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ::ActionController
|
2
|
+
class AbstractRequest
|
3
|
+
def request_method_with_facebooker
|
4
|
+
if parameters[:fb_sig_request_method]=="GET" and parameters[:_method].blank?
|
5
|
+
parameters[:_method]="GET"
|
6
|
+
end
|
7
|
+
request_method_without_facebooker
|
8
|
+
end
|
9
|
+
|
10
|
+
if new.methods.include?("request_method")
|
11
|
+
alias_method_chain :request_method, :facebooker
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module ActionController
|
2
|
+
class CgiRequest
|
3
|
+
alias :initialize_aliased_by_facebooker :initialize
|
4
|
+
|
5
|
+
def initialize(cgi, session_options = {})
|
6
|
+
initialize_aliased_by_facebooker(cgi, session_options)
|
7
|
+
@cgi.instance_variable_set("@request_params", request_parameters.merge(query_parameters))
|
8
|
+
end
|
9
|
+
|
10
|
+
DEFAULT_SESSION_OPTIONS[:cookie_only] = false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class CGI
|
15
|
+
class Session
|
16
|
+
private
|
17
|
+
alias :initialize_aliased_by_facebooker :initialize
|
18
|
+
attr_reader :request, :initialization_options
|
19
|
+
|
20
|
+
def initialize(request, option={})
|
21
|
+
@request = request
|
22
|
+
@initialization_options = option
|
23
|
+
option['session_id'] = set_session_id
|
24
|
+
initialize_aliased_by_facebooker(request, option)
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_session_id
|
28
|
+
if session_key_should_be_set_with_facebook_session_key?
|
29
|
+
request_parameters[facebook_session_key]
|
30
|
+
else
|
31
|
+
request_parameters[session_key]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def request_parameters
|
36
|
+
request.instance_variable_get("@request_params")
|
37
|
+
end
|
38
|
+
|
39
|
+
def session_key_should_be_set_with_facebook_session_key?
|
40
|
+
request_parameters[session_key].blank? && !request_parameters[facebook_session_key].blank?
|
41
|
+
end
|
42
|
+
|
43
|
+
def session_key
|
44
|
+
initialization_options['session_key'] || '_session_id'
|
45
|
+
end
|
46
|
+
|
47
|
+
def facebook_session_key
|
48
|
+
'fb_sig_session_key'
|
49
|
+
end
|
50
|
+
|
51
|
+
alias :create_new_id_aliased_by_facebooker :create_new_id
|
52
|
+
|
53
|
+
def create_new_id
|
54
|
+
@new_session = true
|
55
|
+
@session_id || create_new_id_aliased_by_facebooker
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ::ActionController
|
2
|
+
class AbstractRequest
|
3
|
+
def relative_url_root
|
4
|
+
Facebooker.path_prefix
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class UrlRewriter
|
9
|
+
RESERVED_OPTIONS << :canvas
|
10
|
+
|
11
|
+
def link_to_canvas?(params, options)
|
12
|
+
option_override = options[:canvas]
|
13
|
+
return false if option_override == false # important to check for false. nil should use default behavior
|
14
|
+
option_override || @request.parameters["fb_sig_in_canvas"] == "1" || @request.parameters[:fb_sig_in_canvas] == "1"
|
15
|
+
end
|
16
|
+
|
17
|
+
def rewrite_url_with_facebooker(*args)
|
18
|
+
options = args.first.is_a?(Hash) ? args.first : args.last
|
19
|
+
is_link_to_canvas = link_to_canvas?(@request.request_parameters, options)
|
20
|
+
if is_link_to_canvas && !options.has_key?(:host)
|
21
|
+
options[:host] = "apps.facebook.com"
|
22
|
+
end
|
23
|
+
options.delete(:canvas)
|
24
|
+
Facebooker.request_for_canvas(is_link_to_canvas) do
|
25
|
+
rewrite_url_without_facebooker(*args)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
alias_method_chain :rewrite_url, :facebooker
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,535 @@
|
|
1
|
+
module Facebooker
|
2
|
+
module Rails
|
3
|
+
|
4
|
+
# Facebook specific helpers for creating FBML
|
5
|
+
#
|
6
|
+
# All helpers that take a user as a parameter will get the Facebook UID from the facebook_id attribute if it exists.
|
7
|
+
# It will use to_s if the facebook_id attribute is not present.
|
8
|
+
#
|
9
|
+
module Helpers
|
10
|
+
|
11
|
+
# Create an fb:request-form without a selector
|
12
|
+
#
|
13
|
+
# The block passed to this tag is used as the content of the form
|
14
|
+
#
|
15
|
+
# The message param is the name sent to content_for that specifies the body of the message
|
16
|
+
#
|
17
|
+
# For example,
|
18
|
+
#
|
19
|
+
# <% content_for("invite_message") do %>
|
20
|
+
# This gets sent in the invite. <%= fb_req_choice("with a button!",new_poke_path) %>
|
21
|
+
# <% end %>
|
22
|
+
# <% fb_request_form("Poke","invite_message",create_poke_path) do %>
|
23
|
+
# Send a poke to: <%= fb_friend_selector %> <br />
|
24
|
+
# <%= fb_request_form_submit %>
|
25
|
+
# <% end %>
|
26
|
+
def fb_request_form(type,message_param,url,&block)
|
27
|
+
content = capture(&block)
|
28
|
+
message = @template.instance_variable_get("@content_for_#{message_param}")
|
29
|
+
concat(content_tag("fb:request-form", content,
|
30
|
+
{:action=>url,:method=>"post",:invite=>true,:type=>type,:content=>message}),
|
31
|
+
block.binding)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create a submit button for an <fb:request-form>
|
35
|
+
# If the request is for an individual user you can optionally
|
36
|
+
# Provide the user and a label for the request button.
|
37
|
+
# For example
|
38
|
+
# <% content_for("invite_user") do %>
|
39
|
+
# This gets sent in the invite. <%= fb_req_choice("Come join us!",new_invite_path) %>
|
40
|
+
# <% end %>
|
41
|
+
# <% fb_request_form("Invite","invite_user",create_invite_path) do %>
|
42
|
+
# Invite <%= fb_name(@facebook_user.friends.first.id)%> to the party <br />
|
43
|
+
# <%= fb_request_form_submit(@facebook_user.friends.first.id,"Invite %n") %>
|
44
|
+
# <% end %>
|
45
|
+
# <em>See:</em> http://wiki.developers.facebook.com/index.php/Fb:request-form-submit for options
|
46
|
+
def fb_request_form_submit(options={})
|
47
|
+
tag("fb:request-form-submit",options)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# Create an fb:request-form with an fb_multi_friend_selector inside
|
52
|
+
#
|
53
|
+
# The content of the block are used as the message on the form,
|
54
|
+
#
|
55
|
+
# For example:
|
56
|
+
# <% fb_multi_friend_request("Poke","Choose some friends to Poke",create_poke_path) do %>
|
57
|
+
# If you select some friends, they will see this message.
|
58
|
+
# <%= fb_req_choice("They will get this button, too",new_poke_path) %>
|
59
|
+
# <% end %>
|
60
|
+
def fb_multi_friend_request(type,friend_selector_message,url,&block)
|
61
|
+
content = capture(&block)
|
62
|
+
concat(content_tag("fb:request-form",
|
63
|
+
fb_multi_friend_selector(friend_selector_message),
|
64
|
+
{:action=>url,:method=>"post",:invite=>true,:type=>type,:content=>content}
|
65
|
+
),
|
66
|
+
block.binding)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Render an <fb:friend-selector> element
|
70
|
+
# <em>See:</em> http://wiki.developers.facebook.com/index.php/Fb:friend-selector for options
|
71
|
+
#
|
72
|
+
def fb_friend_selector(options={})
|
73
|
+
tag("fb:friend-selector",options)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Render an <fb:multi-friend-input> element
|
77
|
+
# <em> See: </em> http://wiki.developers.facebook.com/index.php/Fb:multi-friend-input for options
|
78
|
+
def fb_multi_friend_input(options={})
|
79
|
+
tag "fb:multi-friend-input",options
|
80
|
+
end
|
81
|
+
|
82
|
+
# Render an <fb:multi-friend-selector> with the passed in welcome message
|
83
|
+
# Full version shows all profile pics for friends.
|
84
|
+
# <em> See: </em> http://wiki.developers.facebook.com/index.php/Fb:multi-friend-selector for options
|
85
|
+
# <em> Note: </em> I don't think the block is used here.
|
86
|
+
def fb_multi_friend_selector(message,options={},&block)
|
87
|
+
tag("fb:multi-friend-selector",options.merge(:showborder=>false,:actiontext=>message,:max=>20))
|
88
|
+
end
|
89
|
+
|
90
|
+
# Render a condensed <fb:multi-friend-selector> with the passed in welcome message
|
91
|
+
# Condensed version show checkboxes for each friend.
|
92
|
+
# <em> See: </em> http://wiki.developers.facebook.com/index.php/Fb:multi-friend-selector_%28condensed%29 for options
|
93
|
+
# <em> Note: </em> I don't think the block is used here.
|
94
|
+
def fb_multi_friend_selector_condensed(options={},&block)
|
95
|
+
tag("fb:multi-friend-selector",options.merge(:condensed=>true))
|
96
|
+
end
|
97
|
+
|
98
|
+
# Render a button in a request using the <fb:req-choice> tag
|
99
|
+
# url must be an absolute url
|
100
|
+
# This should be used inside the block of an fb_multi_friend_request
|
101
|
+
def fb_req_choice(label,url)
|
102
|
+
tag "fb:req-choice",:label=>label,:url=>url
|
103
|
+
end
|
104
|
+
|
105
|
+
# Create a facebook form using <fb:editor>
|
106
|
+
#
|
107
|
+
# It yields a form builder that will convert the standard rails form helpers
|
108
|
+
# into the facebook specific version.
|
109
|
+
#
|
110
|
+
# Example:
|
111
|
+
# <% facebook_form_for(:poke,@poke,:url => create_poke_path) do |f| %>
|
112
|
+
# <%= f.text_field :message, :label=>"message" %>
|
113
|
+
# <%= f.buttons "Save Poke" %>
|
114
|
+
# <% end %>
|
115
|
+
#
|
116
|
+
# will generate
|
117
|
+
#
|
118
|
+
# <fb:editor action="/pokes/create">
|
119
|
+
# <fb:editor-text name="poke[message]" id="poke_message" value="" label="message" />
|
120
|
+
# <fb:editor-buttonset>
|
121
|
+
# <fb:editor-button label="Save Poke"
|
122
|
+
# </fb:editor-buttonset>
|
123
|
+
# </fb:editor>
|
124
|
+
def facebook_form_for( record_or_name_or_array,*args, &proc)
|
125
|
+
|
126
|
+
raise ArgumentError, "Missing block" unless block_given?
|
127
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
128
|
+
|
129
|
+
case record_or_name_or_array
|
130
|
+
when String, Symbol
|
131
|
+
object_name = record_or_name_or_array
|
132
|
+
when Array
|
133
|
+
object = record_or_name_or_array.last
|
134
|
+
object_name = ActionController::RecordIdentifier.singular_class_name(object)
|
135
|
+
apply_form_for_options!(record_or_name_or_array, options)
|
136
|
+
args.unshift object
|
137
|
+
else
|
138
|
+
object = record_or_name_or_array
|
139
|
+
object_name = ActionController::RecordIdentifier.singular_class_name(object)
|
140
|
+
apply_form_for_options!([object], options)
|
141
|
+
args.unshift object
|
142
|
+
end
|
143
|
+
method = (options[:html]||{})[:method]
|
144
|
+
options[:builder] ||= Facebooker::Rails::FacebookFormBuilder
|
145
|
+
editor_options={}
|
146
|
+
|
147
|
+
action=options.delete(:url)
|
148
|
+
editor_options[:action]= action unless action.blank?
|
149
|
+
width=options.delete(:width)
|
150
|
+
editor_options[:width]=width unless width.blank?
|
151
|
+
width=options.delete(:labelwidth)
|
152
|
+
editor_options[:labelwidth]=width unless width.blank?
|
153
|
+
|
154
|
+
concat(tag("fb:editor",editor_options,true) , proc.binding)
|
155
|
+
concat(tag(:input,{:type=>"hidden",:name=>:_method, :value=>method},false), proc.binding) unless method.blank?
|
156
|
+
fields_for( object_name,*(args << options), &proc)
|
157
|
+
concat("</fb:editor>",proc.binding)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Render an fb:name tag for the given user
|
161
|
+
# This renders the name of the user specified. You can use this tag as both subject and object of
|
162
|
+
# a sentence. <em> See </em> http://wiki.developers.facebook.com/index.php/Fb:name for full description.
|
163
|
+
# Use this tag on FBML pages instead of retrieving the user's info and rendering the name explicitly.
|
164
|
+
#
|
165
|
+
def fb_name(user, options={})
|
166
|
+
options.transform_keys!(FB_NAME_OPTION_KEYS_TO_TRANSFORM)
|
167
|
+
options.assert_valid_keys(FB_NAME_VALID_OPTION_KEYS)
|
168
|
+
options.merge!(:uid => cast_to_facebook_id(user))
|
169
|
+
tag("fb:name", options)
|
170
|
+
end
|
171
|
+
|
172
|
+
FB_NAME_OPTION_KEYS_TO_TRANSFORM = {:first_name_only => :firstnameonly,
|
173
|
+
:last_name_only => :lastnameonly,
|
174
|
+
:show_network => :shownetwork,
|
175
|
+
:use_you => :useyou,
|
176
|
+
:if_cant_see => :ifcantsee,
|
177
|
+
:subject_id => :subjectid}
|
178
|
+
FB_NAME_VALID_OPTION_KEYS = [:firstnameonly, :linked, :lastnameonly, :possessive, :reflexive,
|
179
|
+
:shownetwork, :useyou, :ifcantsee, :capitalize, :subjectid]
|
180
|
+
|
181
|
+
# Render an <fb:pronoun> tag for the specified user
|
182
|
+
# Options give flexibility for placing in any part of a sentence.
|
183
|
+
# <em> See </em> http://wiki.developers.facebook.com/index.php/Fb:pronoun for complete list of options.
|
184
|
+
#
|
185
|
+
def fb_pronoun(user, options={})
|
186
|
+
options.transform_keys!(FB_PRONOUN_OPTION_KEYS_TO_TRANSFORM)
|
187
|
+
options.assert_valid_keys(FB_PRONOUN_VALID_OPTION_KEYS)
|
188
|
+
options.merge!(:uid => cast_to_facebook_id(user))
|
189
|
+
tag("fb:pronoun", options)
|
190
|
+
end
|
191
|
+
|
192
|
+
FB_PRONOUN_OPTION_KEYS_TO_TRANSFORM = {:use_you => :useyou, :use_they => :usethey}
|
193
|
+
FB_PRONOUN_VALID_OPTION_KEYS = [:useyou, :possessive, :reflexive, :objective,
|
194
|
+
:usethey, :capitalize]
|
195
|
+
|
196
|
+
# Render an fb:ref tag.
|
197
|
+
# Options must contain either url or handle.
|
198
|
+
# * <em> url </em> The URL from which to fetch the FBML. You may need to call fbml.refreshRefUrl to refresh cache
|
199
|
+
# * <em> handle </em> The string previously set by fbml.setRefHandle that identifies the FBML
|
200
|
+
# <em> See </em> http://wiki.developers.facebook.com/index.php/Fb:ref for complete description
|
201
|
+
def fb_ref(options)
|
202
|
+
options.assert_valid_keys(FB_REF_VALID_OPTION_KEYS)
|
203
|
+
validate_fb_ref_has_either_url_or_handle(options)
|
204
|
+
validate_fb_ref_does_not_have_both_url_and_handle(options)
|
205
|
+
tag("fb:ref", options)
|
206
|
+
end
|
207
|
+
|
208
|
+
def validate_fb_ref_has_either_url_or_handle(options)
|
209
|
+
unless options.has_key?(:url) || options.has_key?(:handle)
|
210
|
+
raise ArgumentError, "fb_ref requires :url or :handle"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def validate_fb_ref_does_not_have_both_url_and_handle(options)
|
215
|
+
if options.has_key?(:url) && options.has_key?(:handle)
|
216
|
+
raise ArgumentError, "fb_ref may not have both :url and :handle"
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
FB_REF_VALID_OPTION_KEYS = [:url, :handle]
|
221
|
+
|
222
|
+
# Render an <fb:profile-pic> for the specified user.
|
223
|
+
#
|
224
|
+
# You can optionally specify the size using the :size=> option.
|
225
|
+
#
|
226
|
+
# Valid sizes are :thumb, :small, :normal and :square
|
227
|
+
def fb_profile_pic(user, options={})
|
228
|
+
validate_fb_profile_pic_size(options)
|
229
|
+
options.merge!(:uid => cast_to_facebook_id(user))
|
230
|
+
tag("fb:profile-pic", options)
|
231
|
+
end
|
232
|
+
|
233
|
+
# Render an fb:photo tag.
|
234
|
+
# photo is either a Facebooker::Photo or an id of a Facebook photo or an object that responds to photo_id.
|
235
|
+
# <em> See: </em> http://wiki.developers.facebook.com/index.php/Fb:photo for complete list of options.
|
236
|
+
def fb_photo(photo, options={})
|
237
|
+
options.assert_valid_keys(FB_PHOTO_VALID_OPTION_KEYS)
|
238
|
+
options.merge!(:pid => cast_to_photo_id(photo))
|
239
|
+
validate_fb_photo_size(options)
|
240
|
+
validate_fb_photo_align_value(options)
|
241
|
+
tag("fb:photo", options)
|
242
|
+
end
|
243
|
+
|
244
|
+
FB_PHOTO_VALID_OPTION_KEYS = [:uid, :size, :align]
|
245
|
+
|
246
|
+
def cast_to_photo_id(object)
|
247
|
+
object.respond_to?(:photo_id) ? object.photo_id : object
|
248
|
+
end
|
249
|
+
|
250
|
+
VALID_FB_SHARED_PHOTO_SIZES = [:thumb, :small, :normal, :square]
|
251
|
+
VALID_FB_PHOTO_SIZES = VALID_FB_SHARED_PHOTO_SIZES
|
252
|
+
VALID_FB_PROFILE_PIC_SIZES = VALID_FB_SHARED_PHOTO_SIZES
|
253
|
+
|
254
|
+
# Deprecated
|
255
|
+
#
|
256
|
+
# set ActionController::Base.asset_host and use the regular image_tag method.
|
257
|
+
def facebook_image_tag(name,options={})
|
258
|
+
tag "img",:src=>"http://#{ENV['FACEBOOKER_STATIC_HOST']}#{image_path(name)}"
|
259
|
+
end
|
260
|
+
|
261
|
+
# Render an fb:tabs tag containing some number of fb:tab_item tags.
|
262
|
+
# Example:
|
263
|
+
# <% fb_tabs do %>
|
264
|
+
# <%= fb_tab_item("Home", "home") %>
|
265
|
+
# <%= fb_tab_item("Office", "office") %>
|
266
|
+
# <% end %>
|
267
|
+
def fb_tabs(&block)
|
268
|
+
content = capture(&block)
|
269
|
+
concat(content_tag("fb:tabs", content), block.binding)
|
270
|
+
end
|
271
|
+
|
272
|
+
# Render an fb:tab_item tag.
|
273
|
+
# Use this in conjunction with fb_tabs
|
274
|
+
# Options can contains :selected => true to indicate that a tab is the current tab.
|
275
|
+
# <em> See: </em> http://wiki.developers.facebook.com/index.php/Fb:tab-item for complete list of options
|
276
|
+
def fb_tab_item(title, url, options={})
|
277
|
+
options.assert_valid_keys(FB_TAB_ITEM_VALID_OPTION_KEYS)
|
278
|
+
options.merge!(:title => title, :href => url)
|
279
|
+
validate_fb_tab_item_align_value(options)
|
280
|
+
tag("fb:tab-item", options)
|
281
|
+
end
|
282
|
+
|
283
|
+
FB_TAB_ITEM_VALID_OPTION_KEYS = [:align, :selected]
|
284
|
+
|
285
|
+
def validate_fb_tab_item_align_value(options)
|
286
|
+
if options.has_key?(:align) && !VALID_FB_TAB_ITEM_ALIGN_VALUES.include?(options[:align].to_sym)
|
287
|
+
raise(ArgumentError, "Unkown value for align: #{options[:align]}")
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def validate_fb_photo_align_value(options)
|
292
|
+
if options.has_key?(:align) && !VALID_FB_PHOTO_ALIGN_VALUES.include?(options[:align].to_sym)
|
293
|
+
raise(ArgumentError, "Unkown value for align: #{options[:align]}")
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
VALID_FB_SHARED_ALIGN_VALUES = [:left, :right]
|
298
|
+
VALID_FB_PHOTO_ALIGN_VALUES = VALID_FB_SHARED_ALIGN_VALUES
|
299
|
+
VALID_FB_TAB_ITEM_ALIGN_VALUES = VALID_FB_SHARED_ALIGN_VALUES
|
300
|
+
|
301
|
+
|
302
|
+
# Create a Facebook wall. It can contain fb_wall_posts
|
303
|
+
#
|
304
|
+
# For Example:
|
305
|
+
# <% fb_wall do %>
|
306
|
+
# <%= fb_wall_post(@user,"This is my message") %>
|
307
|
+
# <%= fb_wall_post(@otheruser,"This is another message") %>
|
308
|
+
# <% end %>
|
309
|
+
def fb_wall(&proc)
|
310
|
+
content = capture(&proc)
|
311
|
+
concat(content_tag("fb:wall",content,{}),proc.binding)
|
312
|
+
end
|
313
|
+
|
314
|
+
# Render an <fb:wallpost> tag
|
315
|
+
# TODO: Optionally takes a time parameter t = int The current time, which is displayed in epoch seconds.
|
316
|
+
def fb_wallpost(user,message)
|
317
|
+
content_tag("fb:wallpost",message,:uid=>cast_to_facebook_id(user))
|
318
|
+
end
|
319
|
+
alias_method :fb_wall_post, :fb_wallpost
|
320
|
+
|
321
|
+
# Render an <fb:error> tag
|
322
|
+
# If message and text are present then this will render fb:error and fb:message tag
|
323
|
+
# TODO: Optionally takes a decoration tag with value of 'no_padding' or 'shorten'
|
324
|
+
def fb_error(message, text=nil)
|
325
|
+
fb_status_msg("error", message, text)
|
326
|
+
end
|
327
|
+
|
328
|
+
# Render an <fb:explanation> tag
|
329
|
+
# If message and text are present then this will render fb:error and fb:message tag
|
330
|
+
# TODO: Optionally takes a decoration tag with value of 'no_padding' or 'shorten'
|
331
|
+
def fb_explanation(message, text=nil)
|
332
|
+
fb_status_msg("explanation", message, text)
|
333
|
+
end
|
334
|
+
|
335
|
+
# Render an <fb:success> tag
|
336
|
+
# If message and text are present then this will render fb:error and fb:message tag
|
337
|
+
# TODO: Optionally takes a decoration tag with value of 'no_padding' or 'shorten'
|
338
|
+
def fb_success(message, text=nil)
|
339
|
+
fb_status_msg("success", message, text)
|
340
|
+
end
|
341
|
+
|
342
|
+
# Render flash values as <fb:message> and <fb:error> tags
|
343
|
+
#
|
344
|
+
# values in flash[:notice] will be rendered as an <fb:message>
|
345
|
+
#
|
346
|
+
# values in flash[:error] will be rendered as an <fb:error>
|
347
|
+
# TODO: Allow flash[:info] to render fb_explanation
|
348
|
+
def facebook_messages
|
349
|
+
message=""
|
350
|
+
unless flash[:notice].blank?
|
351
|
+
message += fb_success(flash[:notice])
|
352
|
+
end
|
353
|
+
unless flash[:error].blank?
|
354
|
+
message += fb_error(flash[:error])
|
355
|
+
end
|
356
|
+
message
|
357
|
+
end
|
358
|
+
|
359
|
+
# Create a dashboard. It can contain fb_action, fb_help, and fb_create_button
|
360
|
+
#
|
361
|
+
# For Example:
|
362
|
+
# <% fb_dashboard do %>
|
363
|
+
# <%= APP_NAME %>
|
364
|
+
# <%= fb_action 'My Matches', search_path %>
|
365
|
+
# <%= fb_help 'Feedback', "http://www.facebook.com/apps/application.php?id=6236036681" %>
|
366
|
+
# <%= fb_create_button 'Invite Friends', main_path %>
|
367
|
+
# <% end %>
|
368
|
+
def fb_dashboard(&proc)
|
369
|
+
if block_given?
|
370
|
+
content = capture(&proc)
|
371
|
+
concat(content_tag("fb:dashboard",content,{}),proc.binding)
|
372
|
+
else
|
373
|
+
content_tag("fb:dashboard",content,{})
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
# Content for the wide profile box goes in this tag
|
378
|
+
def fb_wide(&proc)
|
379
|
+
content = capture(&proc)
|
380
|
+
concat(content_tag("fb:wide", content, {}), proc.binding)
|
381
|
+
end
|
382
|
+
|
383
|
+
# Content for the narrow profile box goes in this tag
|
384
|
+
def fb_narrow(&proc)
|
385
|
+
content = capture(&proc)
|
386
|
+
concat(content_tag("fb:narrow", content, {}), proc.binding)
|
387
|
+
end
|
388
|
+
|
389
|
+
# Renders an action using the <fb:action> tag
|
390
|
+
def fb_action(name, url)
|
391
|
+
"<fb:action href=\"#{url_for(url)}\">#{name}</fb:action>"
|
392
|
+
end
|
393
|
+
|
394
|
+
# Render a <fb:help> tag
|
395
|
+
# For use inside <fb:dashboard>
|
396
|
+
def fb_help(name, url)
|
397
|
+
"<fb:help href=\"#{url_for(url)}\">#{name}</fb:help>"
|
398
|
+
end
|
399
|
+
|
400
|
+
# Render a <fb:create-button> tag
|
401
|
+
# For use inside <fb:dashboard>
|
402
|
+
def fb_create_button(name, url)
|
403
|
+
"<fb:create-button href=\"#{url_for(url)}\">#{name}</fb:create-button>"
|
404
|
+
end
|
405
|
+
|
406
|
+
# Create a comment area
|
407
|
+
# All the data for this content area is stored on the facebook servers.
|
408
|
+
# <em>See:</em> http://wiki.developers.facebook.com/index.php/Fb:comments for full details
|
409
|
+
# TODO: Comments can optionally take an fb:title tag.
|
410
|
+
def fb_comments(xid,canpost=true,candelete=false,numposts=5,options={})
|
411
|
+
tag "fb:comments",options.merge(:xid=>xid,:canpost=>canpost.to_s,:candelete=>candelete.to_s,:numposts=>numposts)
|
412
|
+
end
|
413
|
+
|
414
|
+
# Adds a title to the title bar
|
415
|
+
#
|
416
|
+
# Facebook | App Name | This is the canvas page window title
|
417
|
+
#
|
418
|
+
# +title+: This is the canvas page window
|
419
|
+
def fb_title(title)
|
420
|
+
"<fb:title>#{title}</fb:title>"
|
421
|
+
end
|
422
|
+
|
423
|
+
# Create a Google Analytics tag
|
424
|
+
#
|
425
|
+
# +uacct+: Your Urchin/Google Analytics account ID.
|
426
|
+
def fb_google_analytics(uacct, options={})
|
427
|
+
tag "fb:google-analytics", options.merge(:uacct => uacct)
|
428
|
+
end
|
429
|
+
|
430
|
+
# Render if-is-app-user tag
|
431
|
+
# This tag renders the enclosing content only if the user specified has accepted the terms of service for the application.
|
432
|
+
# Use fb_if_user_has_added_app to determine wether the user has added the app.
|
433
|
+
# Example:
|
434
|
+
# <% fb_if_is_app_user(@facebook_user) do %>
|
435
|
+
# Thanks for accepting our terms of service!
|
436
|
+
# <% fb_else do %>
|
437
|
+
# Hey you haven't agreed to our terms. <%= link_to("Please accept our terms of service.", :action => "terms_of_service") %>
|
438
|
+
# <% end %>
|
439
|
+
#<% end %>
|
440
|
+
def fb_if_is_app_user(user,options={},&proc)
|
441
|
+
content = capture(&proc)
|
442
|
+
concat(content_tag("fb:if-is-app-user",content,options.merge(:uid=>cast_to_facebook_id(user))),proc.binding)
|
443
|
+
end
|
444
|
+
|
445
|
+
# Render if-user-has-added-app tag
|
446
|
+
# This tag renders the enclosing content only if the user specified has installed the application
|
447
|
+
#
|
448
|
+
# Example:
|
449
|
+
# <% fb_if_user_has_added_app(@facebook_user) do %>
|
450
|
+
# Hey you are an app user!
|
451
|
+
# <% fb_else do %>
|
452
|
+
# Hey you aren't an app user. <%= link_to("Add App and see the other side.", :action => "added_app") %>
|
453
|
+
# <% end %>
|
454
|
+
#<% end %>
|
455
|
+
def fb_if_user_has_added_app(user,options={},&proc)
|
456
|
+
content = capture(&proc)
|
457
|
+
concat(content_tag("fb:if-user-has-added-app",content,options.merge(:uid=>cast_to_facebook_id(user))),proc.binding)
|
458
|
+
end
|
459
|
+
|
460
|
+
# Render fb:if-is-user tag
|
461
|
+
# This tag only renders enclosing content if the user is one of those specified
|
462
|
+
# user can be a single user or an Array of users
|
463
|
+
# Example:
|
464
|
+
# <% fb_if_is_user(@check_user) do %>
|
465
|
+
# <%= fb_name(@facebook_user) %> are one of the users. <%= link_to("Check the other side", :action => "friend") %>
|
466
|
+
# <% fb_else do %>
|
467
|
+
# <%= fb_name(@facebook_user) %> are not one of the users <%= fb_name(@check_user) %>
|
468
|
+
# <%= link_to("Check the other side", :action => "you") %>
|
469
|
+
# <% end %>
|
470
|
+
# <% end %>
|
471
|
+
def fb_if_is_user(user,&proc)
|
472
|
+
content = capture(&proc)
|
473
|
+
user = [user] unless user.is_a? Array
|
474
|
+
user_list=user.map{|u| cast_to_facebook_id(u)}.join(",")
|
475
|
+
concat(content_tag("fb:if-is-user",content,{:uid=>user_list}),proc.binding)
|
476
|
+
end
|
477
|
+
|
478
|
+
# Render fb:else tag
|
479
|
+
# Must be used within if block such as fb_if_is_user or fb_if_is_app_user . See example in fb_if_is_app_user
|
480
|
+
def fb_else
|
481
|
+
content = capture(&proc)
|
482
|
+
concat(content_tag("fb:else",content),proc.binding)
|
483
|
+
end
|
484
|
+
|
485
|
+
def fb_about_url
|
486
|
+
"http://www.facebook.com/apps/application.php?api_key=#{ENV["FACEBOOK_API_KEY"]}"
|
487
|
+
end
|
488
|
+
|
489
|
+
|
490
|
+
protected
|
491
|
+
|
492
|
+
def cast_to_facebook_id(object)
|
493
|
+
Facebooker::User.cast_to_facebook_id(object)
|
494
|
+
end
|
495
|
+
|
496
|
+
def validate_fb_profile_pic_size(options)
|
497
|
+
if options.has_key?(:size) && !VALID_FB_PROFILE_PIC_SIZES.include?(options[:size].to_sym)
|
498
|
+
raise(ArgumentError, "Unkown value for size: #{options[:size]}")
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
def validate_fb_photo_size(options)
|
503
|
+
if options.has_key?(:size) && !VALID_FB_PHOTO_SIZES.include?(options[:size].to_sym)
|
504
|
+
raise(ArgumentError, "Unkown value for size: #{options[:size]}")
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
private
|
509
|
+
|
510
|
+
def fb_status_msg(type, message, text)
|
511
|
+
if text.blank?
|
512
|
+
tag("fb:#{type}", :message => message)
|
513
|
+
else
|
514
|
+
content_tag("fb:#{type}", content_tag("fb:message", message) + text)
|
515
|
+
end
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
class Hash
|
522
|
+
def transform_keys!(transformation_hash)
|
523
|
+
transformation_hash.each_pair{|key, value| transform_key!(key, value)}
|
524
|
+
end
|
525
|
+
|
526
|
+
def transform_key!(old_key, new_key)
|
527
|
+
swapkey!(new_key, old_key)
|
528
|
+
end
|
529
|
+
|
530
|
+
### This method is lifted from Ruby Facets core
|
531
|
+
def swapkey!( newkey, oldkey )
|
532
|
+
self[newkey] = self.delete(oldkey) if self.has_key?(oldkey)
|
533
|
+
self
|
534
|
+
end
|
535
|
+
end
|