simple_facebook_connect 0.0.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/.gitignore +1 -0
- data/MIT-LICENSE +20 -0
- data/README.md +115 -0
- data/Rakefile +27 -0
- data/VERSION +1 -0
- data/app/controllers/simple_facebook_connect/connect_controller.rb +59 -0
- data/app/views/shared/_facebook_connect_button.html.erb +15 -0
- data/config/simple_facebook_connect_routes.rb +4 -0
- data/generators/simple_facebook_connect_features/simple_facebook_connect_features_generator.rb +14 -0
- data/generators/simple_facebook_connect_features/templates/facebook_auth_getsession.xml +9 -0
- data/generators/simple_facebook_connect_features/templates/facebook_connect.feature +27 -0
- data/generators/simple_facebook_connect_features/templates/facebook_connect_steps.rb +19 -0
- data/generators/simple_facebook_connect_features/templates/facebook_connect_stubs.rb +43 -0
- data/generators/simple_facebook_connect_features/templates/facebook_users_getinfo.xml +119 -0
- data/generators/simple_facebook_connect_migration/simple_facebook_connect_migration_generator.rb +13 -0
- data/generators/simple_facebook_connect_migration/templates/migration.rb +17 -0
- data/init.rb +35 -0
- data/lib/simple_facebook_connect/controller_extension.rb +11 -0
- data/lib/simple_facebook_connect/extensions/routes.rb +13 -0
- data/lib/simple_facebook_connect/parser.rb +163 -0
- data/lib/simple_facebook_connect/service.rb +34 -0
- data/lib/simple_facebook_connect/session.rb +73 -0
- data/lib/simple_facebook_connect/user.rb +28 -0
- data/lib/simple_facebook_connect/user_extension.rb +21 -0
- data/lib/simple_facebook_connect.rb +14 -0
- data/rails/init.rb +1 -0
- data/simple_facebook_connect.gemspec +71 -0
- data/spec/fixtures/facebook.auth.getSession/default.xml +9 -0
- data/spec/fixtures/facebook.users.getInfo/default.xml +119 -0
- data/spec/lib/simple_facebook_connect/parser_spec.rb +12 -0
- data/spec/lib/simple_facebook_connect/user_extension_spec.rb +16 -0
- data/spec/lib/simple_facebook_connect/user_spec.rb +37 -0
- data/spec/spec_helper.rb +30 -0
- metadata +91 -0
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module SimpleFacebookConnect
|
4
|
+
|
5
|
+
class FacebookApiError < StandardError; end
|
6
|
+
|
7
|
+
class Parser
|
8
|
+
|
9
|
+
module REXMLElementExtensions
|
10
|
+
def text_value
|
11
|
+
self.children.first.to_s.strip
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
::REXML::Element.__send__(:include, REXMLElementExtensions)
|
16
|
+
|
17
|
+
def self.parse(method, data)
|
18
|
+
Errors.process(data)
|
19
|
+
parser = PARSERS[method]
|
20
|
+
parser.process(
|
21
|
+
data
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.array_of(response_element, element_name)
|
26
|
+
values_to_return = []
|
27
|
+
response_element.elements.each(element_name) do |element|
|
28
|
+
values_to_return << yield(element)
|
29
|
+
end
|
30
|
+
values_to_return
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.array_of_text_values(response_element, element_name)
|
34
|
+
array_of(response_element, element_name) do |element|
|
35
|
+
element.text_value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.array_of_hashes(response_element, element_name)
|
40
|
+
array_of(response_element, element_name) do |element|
|
41
|
+
hashinate(element)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.element(name, data)
|
46
|
+
data = data.body rescue data # either data or an HTTP response
|
47
|
+
doc = REXML::Document.new(data)
|
48
|
+
doc.elements.each(name) do |element|
|
49
|
+
return element
|
50
|
+
end
|
51
|
+
raise "Element #{name} not found in #{data}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.hash_or_value_for(element)
|
55
|
+
if element.children.size == 1 && element.children.first.kind_of?(REXML::Text)
|
56
|
+
element.text_value
|
57
|
+
else
|
58
|
+
hashinate(element)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.hashinate(response_element)
|
63
|
+
response_element.children.reject{|c| c.kind_of? REXML::Text}.inject({}) do |hash, child|
|
64
|
+
# If the node hasn't any child, and is not a list, we want empty strings, not empty hashes,
|
65
|
+
# except if attributes['nil'] == true
|
66
|
+
hash[child.name] =
|
67
|
+
if (child.attributes['nil'] == 'true')
|
68
|
+
nil
|
69
|
+
elsif (child.children.size == 1 && child.children.first.kind_of?(REXML::Text)) || (child.children.size == 0 && child.attributes['list'] != 'true')
|
70
|
+
anonymous_field_from(child, hash) || child.text_value
|
71
|
+
elsif child.attributes['list'] == 'true'
|
72
|
+
child.children.reject{|c| c.kind_of? REXML::Text}.map { |subchild| hash_or_value_for(subchild)}
|
73
|
+
else
|
74
|
+
child.children.reject{|c| c.kind_of? REXML::Text}.inject({}) do |subhash, subchild|
|
75
|
+
subhash[subchild.name] = hash_or_value_for(subchild)
|
76
|
+
subhash
|
77
|
+
end
|
78
|
+
end #if (child.attributes)
|
79
|
+
hash
|
80
|
+
end #do |hash, child|
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.booleanize(response)
|
84
|
+
response == "1" ? true : false
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.anonymous_field_from(child, hash)
|
88
|
+
if child.name == 'anon'
|
89
|
+
(hash[child.name] || []) << child.text_value
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class RevokeAuthorization < self
|
94
|
+
def self.process(data)
|
95
|
+
booleanize(data)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class CreateToken < self
|
100
|
+
def self.process(data)
|
101
|
+
element('auth_createToken_response', data).text_value
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class RegisterUsers < self
|
106
|
+
def self.process(data)
|
107
|
+
array_of_text_values(element("connect_registerUsers_response", data), "connect_registerUsers_response_elt")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class GetSession < self
|
112
|
+
def self.process(data)
|
113
|
+
hashinate(element('auth_getSession_response', data))
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class UserInfo < self
|
118
|
+
def self.process(data)
|
119
|
+
array_of_hashes(element('users_getInfo_response', data), 'user')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class UserStandardInfo < self
|
124
|
+
def self.process(data)
|
125
|
+
array_of_hashes(element('users_getStandardInfo_response', data), 'standard_user_info')
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class GetLoggedInUser < self
|
130
|
+
def self.process(data)
|
131
|
+
Integer(element('users_getLoggedInUser_response', data).text_value)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class ProfileInfo < self
|
136
|
+
def self.process(data)
|
137
|
+
hashinate(element('profile_getInfo_response info_fields', data))
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class Errors < self
|
142
|
+
def self.process(data)
|
143
|
+
response_element = element('error_response', data) rescue nil
|
144
|
+
if response_element
|
145
|
+
hash = hashinate(response_element)
|
146
|
+
raise FacebookApiError, hash['error_msg']
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
PARSERS = {
|
153
|
+
'facebook.auth.revokeAuthorization' => RevokeAuthorization,
|
154
|
+
'facebook.auth.createToken' => CreateToken,
|
155
|
+
'facebook.auth.getSession' => GetSession,
|
156
|
+
'facebook.connect.registerUsers' => RegisterUsers,
|
157
|
+
'facebook.users.getInfo' => UserInfo,
|
158
|
+
'facebook.users.getStandardInfo' => UserStandardInfo,
|
159
|
+
'facebook.profile.getInfo' => ProfileInfo
|
160
|
+
}
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module SimpleFacebookConnect
|
4
|
+
|
5
|
+
class Service
|
6
|
+
def initialize(api_base, api_path, api_key)
|
7
|
+
@api_base = api_base
|
8
|
+
@api_path = api_path
|
9
|
+
@api_key = api_key
|
10
|
+
end
|
11
|
+
|
12
|
+
def post(params)
|
13
|
+
attempt = 0
|
14
|
+
Parser.parse(params[:method], post_form(url,params) )
|
15
|
+
rescue Errno::ECONNRESET, EOFError
|
16
|
+
if attempt == 0
|
17
|
+
attempt += 1
|
18
|
+
retry
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def post_form(url,params)
|
23
|
+
Net::HTTP.post_form(url, params.stringify_keys)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def url(base = nil)
|
28
|
+
base ||= @api_base
|
29
|
+
URI.parse('http://'+ base + @api_path)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module SimpleFacebookConnect
|
2
|
+
|
3
|
+
class Session
|
4
|
+
API_SERVER_BASE_URL = "api.facebook.com"
|
5
|
+
API_PATH_REST = "/restserver.php"
|
6
|
+
WWW_SERVER_BASE_URL = "www.facebook.com"
|
7
|
+
WWW_PATH_LOGIN = "/login.php"
|
8
|
+
|
9
|
+
attr_accessor :auth_token
|
10
|
+
attr_reader :session_key
|
11
|
+
|
12
|
+
|
13
|
+
def initialize(api_key, secret_key)
|
14
|
+
@api_key = api_key
|
15
|
+
@secret_key = secret_key
|
16
|
+
@session_key = nil
|
17
|
+
@uid = nil
|
18
|
+
@auth_token = nil
|
19
|
+
@secret_from_session = nil
|
20
|
+
@expires = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def login_url(options={})
|
24
|
+
"http://#{WWW_SERVER_BASE_URL}#{WWW_PATH_LOGIN}?api_key=#{@api_key}&v=1.0"
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def secure!
|
29
|
+
response = post 'facebook.auth.getSession', :auth_token => auth_token
|
30
|
+
@session_key = response['session_key']
|
31
|
+
@uid = response['uid'].to_i
|
32
|
+
@expires = response['expires'].to_i
|
33
|
+
@secret_from_session = response['secret']
|
34
|
+
end
|
35
|
+
|
36
|
+
def user
|
37
|
+
@user ||= User.new(uid, self)
|
38
|
+
end
|
39
|
+
|
40
|
+
def post(method, params = {}, use_session_key = true, &proc)
|
41
|
+
add_facebook_params(params, method)
|
42
|
+
use_session_key && @session_key && params[:session_key] ||= @session_key
|
43
|
+
final_params = params.merge(:sig => signature_for(params))
|
44
|
+
result = service.post(final_params)
|
45
|
+
result = yield result if block_given?
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def add_facebook_params(hash, method)
|
51
|
+
hash[:method] = method
|
52
|
+
hash[:api_key] = @api_key
|
53
|
+
hash[:call_id] = Time.now.to_f.to_s unless method == 'facebook.auth.getSession'
|
54
|
+
hash[:v] = "1.0"
|
55
|
+
end
|
56
|
+
|
57
|
+
def service
|
58
|
+
@service ||= Service.new(API_SERVER_BASE_URL, API_PATH_REST, @api_key)
|
59
|
+
end
|
60
|
+
|
61
|
+
def uid
|
62
|
+
@uid || (secure!; @uid)
|
63
|
+
end
|
64
|
+
|
65
|
+
def signature_for(params)
|
66
|
+
raw_string = params.inject([]) do |collection, pair|
|
67
|
+
collection << pair.join("=")
|
68
|
+
collection
|
69
|
+
end.sort.join
|
70
|
+
Digest::MD5.hexdigest([raw_string, @secret_key].join)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module SimpleFacebookConnect
|
2
|
+
|
3
|
+
class User
|
4
|
+
|
5
|
+
FIELDS = [:uid, :hometown_location, :first_name, :last_name, :current_location, :pic, :locale, :email_hashes, :about_me, :interests]
|
6
|
+
attr_reader(*FIELDS)
|
7
|
+
attr_reader :session
|
8
|
+
|
9
|
+
def initialize(uid, session)
|
10
|
+
@uid = uid
|
11
|
+
@session = session
|
12
|
+
populate
|
13
|
+
end
|
14
|
+
|
15
|
+
def populate
|
16
|
+
@session.post('facebook.users.getInfo', :fields => coma_seperated_fields, :uids => uid) do |response|
|
17
|
+
FIELDS.each do |field|
|
18
|
+
instance_variable_set(:"@#{field}", response.first[field.to_s])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def coma_seperated_fields
|
24
|
+
FIELDS.join(',')
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'digest/md5'
|
3
|
+
|
4
|
+
module SimpleFacebookConnect
|
5
|
+
module UserExtension
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.class_eval do
|
9
|
+
before_save :build_email_hash, :if => :email_changed?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def build_email_hash
|
16
|
+
str = email.strip.downcase
|
17
|
+
self.email_hash = "#{Zlib.crc32(str)}_#{Digest::MD5.hexdigest(str)}"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
$LOAD_PATH << File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'simple_facebook_connect/parser'
|
4
|
+
require 'simple_facebook_connect/service'
|
5
|
+
require 'simple_facebook_connect/session'
|
6
|
+
require 'simple_facebook_connect/user'
|
7
|
+
require 'simple_facebook_connect/user_extension'
|
8
|
+
require 'simple_facebook_connect/controller_extension'
|
9
|
+
|
10
|
+
module SimpleFacebookConnect
|
11
|
+
class << self
|
12
|
+
attr_accessor :api_key, :secret_key
|
13
|
+
end
|
14
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../init'
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{simple_facebook_connect}
|
5
|
+
s.version = "0.0.5"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Alexander Lang", "Frank Pr\303\266\303\237dorf"]
|
9
|
+
s.date = %q{2009-07-22}
|
10
|
+
s.email = %q{alex@upstream-berlin.com}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"README.md"
|
13
|
+
]
|
14
|
+
s.files = [
|
15
|
+
".gitignore",
|
16
|
+
"MIT-LICENSE",
|
17
|
+
"README.md",
|
18
|
+
"Rakefile",
|
19
|
+
"VERSION",
|
20
|
+
"app/controllers/simple_facebook_connect/connect_controller.rb",
|
21
|
+
"app/views/shared/_facebook_connect_button.html.erb",
|
22
|
+
"config/simple_facebook_connect_routes.rb",
|
23
|
+
"generators/simple_facebook_connect_features/simple_facebook_connect_features_generator.rb",
|
24
|
+
"generators/simple_facebook_connect_features/templates/facebook_auth_getsession.xml",
|
25
|
+
"generators/simple_facebook_connect_features/templates/facebook_connect.feature",
|
26
|
+
"generators/simple_facebook_connect_features/templates/facebook_connect_steps.rb",
|
27
|
+
"generators/simple_facebook_connect_features/templates/facebook_connect_stubs.rb",
|
28
|
+
"generators/simple_facebook_connect_features/templates/facebook_users_getinfo.xml",
|
29
|
+
"generators/simple_facebook_connect_migration/simple_facebook_connect_migration_generator.rb",
|
30
|
+
"generators/simple_facebook_connect_migration/templates/migration.rb",
|
31
|
+
"init.rb",
|
32
|
+
"lib/simple_facebook_connect.rb",
|
33
|
+
"lib/simple_facebook_connect/controller_extension.rb",
|
34
|
+
"lib/simple_facebook_connect/extensions/routes.rb",
|
35
|
+
"lib/simple_facebook_connect/parser.rb",
|
36
|
+
"lib/simple_facebook_connect/service.rb",
|
37
|
+
"lib/simple_facebook_connect/session.rb",
|
38
|
+
"lib/simple_facebook_connect/user.rb",
|
39
|
+
"lib/simple_facebook_connect/user_extension.rb",
|
40
|
+
"rails/init.rb",
|
41
|
+
"simple_facebook_connect.gemspec",
|
42
|
+
"spec/fixtures/facebook.auth.getSession/default.xml",
|
43
|
+
"spec/fixtures/facebook.users.getInfo/default.xml",
|
44
|
+
"spec/lib/simple_facebook_connect/parser_spec.rb",
|
45
|
+
"spec/lib/simple_facebook_connect/user_extension_spec.rb",
|
46
|
+
"spec/lib/simple_facebook_connect/user_spec.rb",
|
47
|
+
"spec/spec_helper.rb"
|
48
|
+
]
|
49
|
+
s.has_rdoc = true
|
50
|
+
s.homepage = %q{http://github.com/upstream/simple_facebook_connect}
|
51
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
52
|
+
s.require_paths = ["lib"]
|
53
|
+
s.rubygems_version = %q{1.3.1}
|
54
|
+
s.summary = %q{This plugin adds the ability to sign in/sign up using facebook connect to your Rails application.}
|
55
|
+
s.test_files = [
|
56
|
+
"spec/lib/simple_facebook_connect/parser_spec.rb",
|
57
|
+
"spec/lib/simple_facebook_connect/user_extension_spec.rb",
|
58
|
+
"spec/lib/simple_facebook_connect/user_spec.rb",
|
59
|
+
"spec/spec_helper.rb"
|
60
|
+
]
|
61
|
+
|
62
|
+
if s.respond_to? :specification_version then
|
63
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
64
|
+
s.specification_version = 2
|
65
|
+
|
66
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
67
|
+
else
|
68
|
+
end
|
69
|
+
else
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<auth_getSession_response
|
3
|
+
xmlns="http://api.facebook.com/1.0/"
|
4
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
5
|
+
xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd">
|
6
|
+
<session_key>5f34e11bfb97c762e439e6a5-8055</session_key>
|
7
|
+
<uid>8055</uid>
|
8
|
+
<expires>1173309298</expires>
|
9
|
+
</auth_getSession_response>
|
@@ -0,0 +1,119 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<users_getInfo_response xmlns="http://api.facebook.com/1.0/"
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
4
|
+
xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
|
5
|
+
<user>
|
6
|
+
<uid>8055</uid>
|
7
|
+
<about_me>This field perpetuates the glorification of the ego. Also, it has a character limit.</about_me>
|
8
|
+
<activities>Here: facebook, etc. There: Glee Club, a capella, teaching.</activities>
|
9
|
+
<affiliations list="true">
|
10
|
+
<affiliation>
|
11
|
+
<nid>50453093</nid>
|
12
|
+
<name>Facebook Developers</name>
|
13
|
+
<type>work</type>
|
14
|
+
<status/>
|
15
|
+
<year/>
|
16
|
+
</affiliation>
|
17
|
+
</affiliations>
|
18
|
+
<birthday>November 3</birthday>
|
19
|
+
<books>The Brothers K, GEB, Ken Wilber, Zen and the Art, Fitzgerald, The Emporer's New Mind, The Wonderful Story of Henry Sugar</books>
|
20
|
+
<current_location>
|
21
|
+
<city>Palo Alto</city>
|
22
|
+
<state>California</state>
|
23
|
+
<country>United States</country>
|
24
|
+
<zip>94303</zip>
|
25
|
+
</current_location>
|
26
|
+
<education_history list="true">
|
27
|
+
<education_info>
|
28
|
+
<name>Harvard</name>
|
29
|
+
<year>2003</year>
|
30
|
+
<concentrations list="true">
|
31
|
+
<concentration>Applied Mathematics</concentration>
|
32
|
+
<concentration>Computer Science</concentration>
|
33
|
+
</concentrations>
|
34
|
+
</education_info>
|
35
|
+
</education_history>
|
36
|
+
<email_hashes list="true">
|
37
|
+
<email_hash_elt>2781152470_9f9c29692798573d8c76eaaf053a1911</email_hash_elt>
|
38
|
+
</email_hashes>
|
39
|
+
<family list="true">
|
40
|
+
<family_elt list="true">
|
41
|
+
<family_elt_elt>mother</family_elt_elt>
|
42
|
+
<family_elt_elt>1394244902</family_elt_elt>
|
43
|
+
</family_elt>
|
44
|
+
<family_elt list="true">
|
45
|
+
<family_elt_elt>sister</family_elt_elt>
|
46
|
+
<family_elt_elt>48703107</family_elt_elt>
|
47
|
+
</family_elt>
|
48
|
+
<family_elt list="true">
|
49
|
+
<family_elt_elt>brother</family_elt_elt>
|
50
|
+
<family_elt_elt>1078767258</family_elt_elt>
|
51
|
+
</family_elt>
|
52
|
+
<family_elt list="true">
|
53
|
+
<family_elt_elt>brother</family_elt_elt>
|
54
|
+
<family_elt_elt>John Doe</family_elt_elt>
|
55
|
+
<family_elt_elt/>
|
56
|
+
</family_elt>
|
57
|
+
</family>
|
58
|
+
<first_name>Dave</first_name>
|
59
|
+
<hometown_location>
|
60
|
+
<city>York</city>
|
61
|
+
<state>Pennsylvania</state>
|
62
|
+
<country>United States</country>
|
63
|
+
</hometown_location>
|
64
|
+
<hs_info>
|
65
|
+
<hs1_name>Central York High School</hs1_name>
|
66
|
+
<hs2_name/>
|
67
|
+
<grad_year>1999</grad_year>
|
68
|
+
<hs1_id>21846</hs1_id>
|
69
|
+
<hs2_id>0</hs2_id>
|
70
|
+
</hs_info>
|
71
|
+
<is_app_user>1</is_app_user>
|
72
|
+
<has_added_app>1</has_added_app>
|
73
|
+
<interests>coffee, computers, the funny, architecture, code breaking,snowboarding, philosophy, soccer, talking to strangers</interests>
|
74
|
+
<last_name>Fetterman</last_name>
|
75
|
+
<locale>en_US</locale>
|
76
|
+
<meeting_for list="true">
|
77
|
+
<seeking>Friendship</seeking>
|
78
|
+
</meeting_for>
|
79
|
+
<meeting_sex list="true">
|
80
|
+
<sex>female</sex>
|
81
|
+
</meeting_sex>
|
82
|
+
<movies>Tommy Boy, Billy Madison, Fight Club, Dirty Work, Meet the Parents, My Blue Heaven, Office Space </movies>
|
83
|
+
<music>New Found Glory, Daft Punk, Weezer, The Crystal Method, Rage, the KLF, Green Day, Live, Coldplay, Panic at the Disco, Family Force 5</music>
|
84
|
+
<name>Dave Fetterman</name>
|
85
|
+
<notes_count>0</notes_count>
|
86
|
+
<pic>http://photos-055.facebook.com/ip007/profile3/1271/65/s8055_39735.jpg</pic>
|
87
|
+
<pic_big>http://photos-055.facebook.com/ip007/profile3/1271/65/n8055_39735.jpg</pic_big>
|
88
|
+
<pic_small>http://photos-055.facebook.com/ip007/profile3/1271/65/t8055_39735.jpg</pic_small>
|
89
|
+
<pic_square>http://photos-055.facebook.com/ip007/profile3/1271/65/q8055_39735.jpg</pic_square>
|
90
|
+
<political>Moderate</political>
|
91
|
+
<profile_update_time>1170414620</profile_update_time>
|
92
|
+
<quotes/>
|
93
|
+
<relationship_status>In a Relationship</relationship_status>
|
94
|
+
<religion/>
|
95
|
+
<sex>male</sex>
|
96
|
+
<significant_other_id xsi:nil="true"/>
|
97
|
+
<status>
|
98
|
+
<message>Fast Company, November issue, page 84</message>
|
99
|
+
<time>1193075616</time>
|
100
|
+
</status>
|
101
|
+
<timezone>-8</timezone>
|
102
|
+
<tv>cf. Bob Trahan</tv>
|
103
|
+
<wall_count>121</wall_count>
|
104
|
+
<work_history list="true">
|
105
|
+
<work_info>
|
106
|
+
<location>
|
107
|
+
<city>Palo Alto</city>
|
108
|
+
<state>CA</state>
|
109
|
+
<country>United States</country>
|
110
|
+
</location>
|
111
|
+
<company_name>Facebook</company_name>
|
112
|
+
<position>Software Engineer</position>
|
113
|
+
<description>Tech Lead, Facebook Platform</description>
|
114
|
+
<start_date>2006-01</start_date>
|
115
|
+
<end_date/>
|
116
|
+
</work_info>
|
117
|
+
</work_history>
|
118
|
+
</user>
|
119
|
+
</users_getInfo_response>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe SimpleFacebookConnect::Parser, 'parse' do
|
4
|
+
it "should parse getInfo xml response" do
|
5
|
+
result = SimpleFacebookConnect::Parser.parse('facebook.users.getInfo', File.read(File.dirname(__FILE__) + '/../../fixtures/facebook.users.getInfo/default.xml'))
|
6
|
+
result.should == parsed_array
|
7
|
+
end
|
8
|
+
|
9
|
+
def parsed_array
|
10
|
+
[{"uid"=>"8055", "about_me"=>"This field perpetuates the glorification of the ego. Also, it has a character limit.", "activities"=>"Here: facebook, etc. There: Glee Club, a capella, teaching.", "affiliations"=>[{"nid"=>"50453093", "name"=>"Facebook Developers", "type"=>"work", "status"=>"", "year"=>""}], "birthday"=>"November 3", "books"=>"The Brothers K, GEB, Ken Wilber, Zen and the Art, Fitzgerald, The Emporer's New Mind, The Wonderful Story of Henry Sugar", "current_location"=>{"city"=>"Palo Alto", "state"=>"California", "country"=>"United States", "zip"=>"94303"}, "education_history"=>[{"name"=>"Harvard", "year"=>"2003", "concentrations"=>["Applied Mathematics", "Computer Science"]}], "email_hashes"=>["2781152470_9f9c29692798573d8c76eaaf053a1911"], "family"=>[{"family_elt_elt"=>"1394244902"}, {"family_elt_elt"=>"48703107"}, {"family_elt_elt"=>"1078767258"}, {"family_elt_elt"=>""}], "first_name"=>"Dave", "hometown_location"=>{"city"=>"York", "state"=>"Pennsylvania", "country"=>"United States"}, "hs_info"=>{"hs1_name"=>"Central York High School", "hs2_name"=>{}, "grad_year"=>"1999", "hs1_id"=>"21846", "hs2_id"=>"0"}, "is_app_user"=>"1", "has_added_app"=>"1", "interests"=>"coffee, computers, the funny, architecture, code breaking,snowboarding, philosophy, soccer, talking to strangers", "last_name"=>"Fetterman", "locale"=>"en_US", "meeting_for"=>["Friendship"], "meeting_sex"=>["female"], "movies"=>"Tommy Boy, Billy Madison, Fight Club, Dirty Work, Meet the Parents, My Blue Heaven, Office Space", "music"=>"New Found Glory, Daft Punk, Weezer, The Crystal Method, Rage, the KLF, Green Day, Live, Coldplay, Panic at the Disco, Family Force 5", "name"=>"Dave Fetterman", "notes_count"=>"0", "pic"=>"http://photos-055.facebook.com/ip007/profile3/1271/65/s8055_39735.jpg", "pic_big"=>"http://photos-055.facebook.com/ip007/profile3/1271/65/n8055_39735.jpg", "pic_small"=>"http://photos-055.facebook.com/ip007/profile3/1271/65/t8055_39735.jpg", "pic_square"=>"http://photos-055.facebook.com/ip007/profile3/1271/65/q8055_39735.jpg", "political"=>"Moderate", "profile_update_time"=>"1170414620", "quotes"=>"", "relationship_status"=>"In a Relationship", "religion"=>"", "sex"=>"male", "significant_other_id"=>nil, "status"=>{"message"=>"Fast Company, November issue, page 84", "time"=>"1193075616"}, "timezone"=>"-8", "tv"=>"cf. Bob Trahan", "wall_count"=>"121", "work_history"=>[{"location"=>{"city"=>"Palo Alto", "state"=>"CA", "country"=>"United States"}, "company_name"=>"Facebook", "position"=>"Software Engineer", "description"=>"Tech Lead, Facebook Platform", "start_date"=>"2006-01", "end_date"=>""}]}]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe SimpleFacebookConnect::UserExtension, 'email=' do
|
4
|
+
class User < ActiveRecord::Base
|
5
|
+
include SimpleFacebookConnect::UserExtension
|
6
|
+
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should set the email hash" do
|
10
|
+
user = User.new
|
11
|
+
user.email = 'joe@doe.com'
|
12
|
+
user.save!
|
13
|
+
user.email_hash.should == '3404385302_68ef883c573edb5d26365e8f20156eec'
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe SimpleFacebookConnect::User, 'initialize' do
|
4
|
+
before(:each) do
|
5
|
+
@session = stub 'session', :post => nil
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should send a remote call to facebook" do
|
9
|
+
@session.should_receive(:post).with('facebook.users.getInfo', :fields => 'uid,hometown_location,first_name,last_name,current_location,pic,locale,email_hashes,about_me,interests', :uids => 8055)
|
10
|
+
SimpleFacebookConnect::User.new(8055, @session)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should populate the user attributes" do
|
14
|
+
@session.stub!(:post).and_yield(user_info_response)
|
15
|
+
user = SimpleFacebookConnect::User.new(8055, @session)
|
16
|
+
user.email_hashes.should == ["2781152470_9f9c29692798573d8c76eaaf053a1911"]
|
17
|
+
user.uid.should == '8055'
|
18
|
+
user.hometown_location.should == {"city"=>"York", "state"=>"Pennsylvania", "country"=>"United States"}
|
19
|
+
user.first_name.should == 'Dave'
|
20
|
+
user.last_name.should == 'Fetterman'
|
21
|
+
user.current_location.should == {"city"=>"Palo Alto", "state"=>"California", "country"=>"United States", "zip"=>"94303"}
|
22
|
+
user.pic.should == 'http://photos-055.facebook.com/ip007/profile3/1271/65/s8055_39735.jpg'
|
23
|
+
user.locale.should == 'en_US'
|
24
|
+
user.about_me.should == 'This field perpetuates the glorification of the ego. Also, it has a character limit.'
|
25
|
+
user.interests.should == 'snowboarding, philosophy, soccer, talking to strangers'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should expose the session" do
|
29
|
+
user = SimpleFacebookConnect::User.new(8055, @session)
|
30
|
+
user.session.should == @session
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def user_info_response
|
35
|
+
[{"uid"=>"8055", "about_me"=>"This field perpetuates the glorification of the ego. Also, it has a character limit.", "activities"=>"Here: facebook, etc. There: Glee Club, a capella, teaching.", "affiliations"=>[{"nid"=>"50453093", "name"=>"Facebook Developers", "type"=>"work", "status"=>"", "year"=>""}], "birthday"=>"November 3", "books"=>"The Brothers K, GEB, Ken Wilber, Zen and the Art, Fitzgerald, The Emporer's New Mind, The Wonderful Story of Henry Sugar", "current_location"=>{"city"=>"Palo Alto", "state"=>"California", "country"=>"United States", "zip"=>"94303"}, "education_history"=>[{"name"=>"Harvard", "year"=>"2003", "concentrations"=>["Applied Mathematics", "Computer Science"]}], "email_hashes"=>["2781152470_9f9c29692798573d8c76eaaf053a1911"], "family"=>[{"family_elt_elt"=>"1394244902"}, {"family_elt_elt"=>"48703107"}, {"family_elt_elt"=>"1078767258"}, {"family_elt_elt"=>""}], "first_name"=>"Dave", "hometown_location"=>{"city"=>"York", "state"=>"Pennsylvania", "country"=>"United States"}, "hs_info"=>{"hs1_name"=>"Central York High School", "hs2_name"=>{}, "grad_year"=>"1999", "hs1_id"=>"21846", "hs2_id"=>"0"}, "is_app_user"=>"1", "has_added_app"=>"1", "interests"=>"snowboarding, philosophy, soccer, talking to strangers", "last_name"=>"Fetterman", "locale"=>"en_US", "meeting_for"=>["Friendship"], "meeting_sex"=>["female"], "movies"=>"Tommy Boy, Billy Madison, Fight Club, Dirty Work, Meet the Parents, My Blue Heaven, Office Space", "music"=>"New Found Glory, Daft Punk, Weezer, The Crystal Method, Rage, the KLF, Green Day, Live, Coldplay, Panic at the Disco, Family Force 5", "name"=>"Dave Fetterman", "notes_count"=>"0", "pic"=>"http://photos-055.facebook.com/ip007/profile3/1271/65/s8055_39735.jpg", "pic_big"=>"http://photos-055.facebook.com/ip007/profile3/1271/65/n8055_39735.jpg", "pic_small"=>"http://photos-055.facebook.com/ip007/profile3/1271/65/t8055_39735.jpg", "pic_square"=>"http://photos-055.facebook.com/ip007/profile3/1271/65/q8055_39735.jpg", "political"=>"Moderate", "profile_update_time"=>"1170414620", "quotes"=>"", "relationship_status"=>"In a Relationship", "religion"=>"", "sex"=>"male", "significant_other_id"=>nil, "status"=>{"message"=>"Fast Company, November issue, page 84", "time"=>"1193075616"}, "timezone"=>"-8", "tv"=>"cf. Bob Trahan", "wall_count"=>"121", "work_history"=>[{"location"=>{"city"=>"Palo Alto", "state"=>"CA", "country"=>"United States"}, "company_name"=>"Facebook", "position"=>"Software Engineer", "description"=>"Tech Lead, Facebook Platform", "start_date"=>"2006-01", "end_date"=>""}]}]
|
36
|
+
end
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
__DIR__ = File.dirname __FILE__
|
2
|
+
$LOAD_PATH.unshift __DIR__ + '/../lib'
|
3
|
+
|
4
|
+
require 'simple_facebook_connect'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'rubygems'
|
7
|
+
Gem::RubyGemsVersion.inspect # without this the activerecord gem doesn't load on ruby 1.9 #WTF
|
8
|
+
require 'sqlite3'
|
9
|
+
gem 'activerecord'
|
10
|
+
require 'activerecord'
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
FileUtils.rm_rf __DIR__ + '/../test.sqlite3'
|
15
|
+
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => File.join(__DIR__, '..', 'test.sqlite3')
|
16
|
+
|
17
|
+
# migrate
|
18
|
+
|
19
|
+
class CreateUsers < ActiveRecord::Migration
|
20
|
+
def self.up
|
21
|
+
create_table :users do |t|
|
22
|
+
t.string :email
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require __DIR__ + '/../generators/simple_facebook_connect_migration/templates/migration'
|
28
|
+
|
29
|
+
CreateUsers.up
|
30
|
+
AddFacebookConnect.up
|