koala 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -0
- data/Manifest +0 -14
- data/Rakefile +2 -1
- data/koala.gemspec +6 -3
- data/spec/facebook_data.yml +5 -5
- data/spec/koala/api_base_tests.rb +1 -0
- data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +1 -1
- data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +1 -1
- data/spec/koala/graph_api/graph_collection_tests.rb +2 -2
- data/spec/koala/live_testing_data_helper.rb +20 -12
- data/spec/koala/net_http_service_tests.rb +164 -159
- data/spec/koala/oauth/oauth_tests.rb +4 -11
- data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +5 -5
- data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +1 -1
- data/spec/koala_spec_helper.rb +18 -4
- metadata +16 -19
- data/examples/oauth_playground/Capfile +0 -2
- data/examples/oauth_playground/LICENSE +0 -22
- data/examples/oauth_playground/Rakefile +0 -4
- data/examples/oauth_playground/config.ru +0 -27
- data/examples/oauth_playground/config/deploy.rb +0 -39
- data/examples/oauth_playground/config/facebook.yml +0 -13
- data/examples/oauth_playground/lib/load_facebook.rb +0 -3
- data/examples/oauth_playground/lib/oauth_playground.rb +0 -187
- data/examples/oauth_playground/readme.md +0 -8
- data/examples/oauth_playground/spec/oauth_playground_spec.rb +0 -35
- data/examples/oauth_playground/spec/spec_helper.rb +0 -36
- data/examples/oauth_playground/tmp/restart.txt +0 -0
- data/examples/oauth_playground/views/index.erb +0 -206
- data/examples/oauth_playground/views/layout.erb +0 -39
@@ -1,14 +1,3 @@
|
|
1
|
-
# stub the Time class to always return a time for which the valid cookie is still valid
|
2
|
-
class Time
|
3
|
-
def self.now
|
4
|
-
self
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.to_i
|
8
|
-
1273363199
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
1
|
class FacebookOAuthTests < Test::Unit::TestCase
|
13
2
|
describe "Koala OAuth tests" do
|
14
3
|
before :each do
|
@@ -34,6 +23,10 @@ class FacebookOAuthTests < Test::Unit::TestCase
|
|
34
23
|
@raw_offline_access_token_string
|
35
24
|
|
36
25
|
@oauth = Koala::Facebook::OAuth.new(@app_id, @secret, @callback_url)
|
26
|
+
|
27
|
+
time = Time.now
|
28
|
+
Time.stub!(:now).and_return(time)
|
29
|
+
time.stub!(:to_i).and_return(1273363199)
|
37
30
|
end
|
38
31
|
|
39
32
|
# initialization
|
@@ -83,12 +83,12 @@ shared_examples_for "Koala RestAPI without an access token" do
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
class FacebookRestAPINoAccessTokenTest < Test::Unit::TestCase
|
87
|
-
before :each do
|
88
|
-
@api = Koala::Facebook::RestAPI.new
|
89
|
-
end
|
90
|
-
|
86
|
+
class FacebookRestAPINoAccessTokenTest < Test::Unit::TestCase
|
91
87
|
describe "Koala RestAPI without an access token" do
|
88
|
+
before :each do
|
89
|
+
@api = Koala::Facebook::RestAPI.new
|
90
|
+
end
|
91
|
+
|
92
92
|
it_should_behave_like "Koala RestAPI without an access token"
|
93
93
|
end
|
94
94
|
end
|
@@ -26,7 +26,7 @@ end
|
|
26
26
|
|
27
27
|
class FacebookRestAPIWithAccessTokenTests < Test::Unit::TestCase
|
28
28
|
describe "Koala RestAPI with an access token" do
|
29
|
-
|
29
|
+
include LiveTestingDataHelper
|
30
30
|
it_should_behave_like "Koala RestAPI with an access token"
|
31
31
|
|
32
32
|
before :each do
|
data/spec/koala_spec_helper.rb
CHANGED
@@ -1,6 +1,18 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
require '
|
1
|
+
if defined?(RUBY_VERSION) && RUBY_VERSION =~ /1\.9/
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rspec'
|
4
|
+
|
5
|
+
Rspec.configure do |c|
|
6
|
+
c.mock_with :rspec
|
7
|
+
end
|
8
|
+
|
9
|
+
else
|
10
|
+
# Ruby 1.8.x
|
11
|
+
require 'test/unit'
|
12
|
+
require 'rubygems'
|
13
|
+
|
14
|
+
require 'spec/test/unit'
|
15
|
+
end
|
4
16
|
|
5
17
|
# load the libraries
|
6
18
|
require 'koala'
|
@@ -28,4 +40,6 @@ require 'koala/oauth/oauth_tests'
|
|
28
40
|
require 'koala/realtime_updates/realtime_updates_tests'
|
29
41
|
|
30
42
|
# Services tests
|
31
|
-
require 'koala/net_http_service_tests'
|
43
|
+
require 'koala/net_http_service_tests'
|
44
|
+
|
45
|
+
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 9
|
8
|
-
-
|
9
|
-
version: 0.9.
|
8
|
+
- 1
|
9
|
+
version: 0.9.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional
|
@@ -14,10 +14,21 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-10-13 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: json
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
21
32
|
description: Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph API and the older REST API, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services.
|
22
33
|
email: alex@alexkoppel.com
|
23
34
|
executables: []
|
@@ -37,20 +48,6 @@ files:
|
|
37
48
|
- LICENSE
|
38
49
|
- Manifest
|
39
50
|
- Rakefile
|
40
|
-
- examples/oauth_playground/Capfile
|
41
|
-
- examples/oauth_playground/LICENSE
|
42
|
-
- examples/oauth_playground/Rakefile
|
43
|
-
- examples/oauth_playground/config.ru
|
44
|
-
- examples/oauth_playground/config/deploy.rb
|
45
|
-
- examples/oauth_playground/config/facebook.yml
|
46
|
-
- examples/oauth_playground/lib/load_facebook.rb
|
47
|
-
- examples/oauth_playground/lib/oauth_playground.rb
|
48
|
-
- examples/oauth_playground/readme.md
|
49
|
-
- examples/oauth_playground/spec/oauth_playground_spec.rb
|
50
|
-
- examples/oauth_playground/spec/spec_helper.rb
|
51
|
-
- examples/oauth_playground/tmp/restart.txt
|
52
|
-
- examples/oauth_playground/views/index.erb
|
53
|
-
- examples/oauth_playground/views/layout.erb
|
54
51
|
- init.rb
|
55
52
|
- koala.gemspec
|
56
53
|
- lib/koala.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2010 Alex Koppel
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person
|
4
|
-
obtaining a copy of this software and associated documentation
|
5
|
-
files (the "Software"), to deal in the Software without
|
6
|
-
restriction, including without limitation the rights to use,
|
7
|
-
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
-
copies of the Software, and to permit persons to whom the
|
9
|
-
Software is furnished to do so, subject to the following
|
10
|
-
conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be
|
13
|
-
included in all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
-
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
-
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
-
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# gems
|
2
|
-
require 'sinatra'
|
3
|
-
require 'logger'
|
4
|
-
require 'yaml'
|
5
|
-
|
6
|
-
# app files
|
7
|
-
require 'koala'
|
8
|
-
require File.join(File.dirname(__FILE__), 'lib', 'load_facebook.rb')
|
9
|
-
require File.join(File.dirname(__FILE__), 'lib', 'oauth_playground.rb')
|
10
|
-
|
11
|
-
# LOGGING
|
12
|
-
# set up the logfile
|
13
|
-
Dir.mkdir('log') unless File.exists?('log')
|
14
|
-
log_filename = File.join(File.dirname(__FILE__), "log", "sinatra.log")
|
15
|
-
log = File.new(log_filename, "a+")
|
16
|
-
|
17
|
-
# log requests
|
18
|
-
use Rack::CommonLogger, log
|
19
|
-
# log application-generated code
|
20
|
-
LOGGER = Logger.new(log_filename)
|
21
|
-
# log output to stdout and stderr as well
|
22
|
-
$stdout.reopen(log)
|
23
|
-
$stderr.reopen(log)
|
24
|
-
|
25
|
-
# activate the app
|
26
|
-
disable :run
|
27
|
-
run OAuthPlayground
|
@@ -1,39 +0,0 @@
|
|
1
|
-
set :application, "oauth_playground"
|
2
|
-
set :repository, "git://github.com/arsduo/oauth_playground.git"
|
3
|
-
set :domain, "oauth.twoalex.com"
|
4
|
-
set :deploy_to, "$HOME/rails_apps/#{application}/"
|
5
|
-
|
6
|
-
# authentication
|
7
|
-
set :scm, "git"
|
8
|
-
set :user, "alexkm"
|
9
|
-
set :use_sudo, false
|
10
|
-
ssh_options[:forward_agent] = true
|
11
|
-
|
12
|
-
# web server
|
13
|
-
role :web, "oauth.twoalex.com" # Your HTTP server, Apache/etc
|
14
|
-
role :app, "oauth.twoalex.com" # This may be the same as your `Web` server
|
15
|
-
role :db, "oauth.twoalex.com", :primary => true # This is where Rails migrations will run
|
16
|
-
|
17
|
-
|
18
|
-
# other git-related commands
|
19
|
-
set :branch, "master"
|
20
|
-
default_run_options[:pty] = true
|
21
|
-
# cache the repository locally to speed updates
|
22
|
-
set :repository_cache, "git_cache"
|
23
|
-
set :deploy_via, :remote_cache
|
24
|
-
|
25
|
-
|
26
|
-
# passenger-specific deploy tasks
|
27
|
-
namespace :deploy do
|
28
|
-
task :start do
|
29
|
-
run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
|
30
|
-
end
|
31
|
-
|
32
|
-
task :stop do
|
33
|
-
# nothing
|
34
|
-
end
|
35
|
-
|
36
|
-
task :restart, :roles => :app, :except => { :no_release => true } do
|
37
|
-
run "touch #{File.join(current_path,'tmp','restart.txt')}"
|
38
|
-
end
|
39
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
development:
|
2
|
-
api_key: 171e3563d4fee42e0ba27450838bba32
|
3
|
-
secret_key: c81302ccef57cbdd2e68b2229e54cd2f
|
4
|
-
app_id: 119347844754245
|
5
|
-
|
6
|
-
test:
|
7
|
-
api_key:
|
8
|
-
secret_key:
|
9
|
-
|
10
|
-
production:
|
11
|
-
api_key: 25e1cec0df2b3bfa781da3ed78da3a1e
|
12
|
-
secret_key: e45e55a333eec232d4206d2703de1307
|
13
|
-
app_id: 119908831367602
|
@@ -1,187 +0,0 @@
|
|
1
|
-
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'sinatra'
|
5
|
-
require 'erb'
|
6
|
-
|
7
|
-
class OAuthPlayground < Sinatra::Application
|
8
|
-
|
9
|
-
set :root, APP_ROOT
|
10
|
-
|
11
|
-
include Koala
|
12
|
-
|
13
|
-
layout :layout
|
14
|
-
|
15
|
-
get "/" do
|
16
|
-
@app_data = FACEBOOK_INFO.merge("callback_url" => "#{request.scheme}://#{request.host}/")
|
17
|
-
@oauth = Facebook::OAuth.new(@app_data["app_id"], @app_data["secret_key"], @app_data["callback_url"])
|
18
|
-
|
19
|
-
# get authentication info
|
20
|
-
set_facebook_cookies
|
21
|
-
set_oauth_data
|
22
|
-
set_access_token
|
23
|
-
|
24
|
-
unless (@permissions = params[:permissions]) && @permissions.length > 0
|
25
|
-
@active_permissions = (get_active_permissions || {}).inject([]) do |active, perm|
|
26
|
-
# collect our active permissions
|
27
|
-
active << perm[0].to_sym if perm[1] == 1
|
28
|
-
active
|
29
|
-
end
|
30
|
-
@fetched_permissions = true
|
31
|
-
else
|
32
|
-
@active_permissions = @permissions.collect {|p| p.to_sym}
|
33
|
-
end
|
34
|
-
|
35
|
-
@available_permissions = [
|
36
|
-
{:name => "User Activity", :perms => ACTIVITY_PERMISSIONS},
|
37
|
-
{:name => "User Info", :perms => USER_PERMISSIONS},
|
38
|
-
{:name => "Friend Info", :perms => FRIEND_PERMISSIONS}
|
39
|
-
]
|
40
|
-
|
41
|
-
erb :index
|
42
|
-
end
|
43
|
-
|
44
|
-
get "/subscriptions" do
|
45
|
-
# validate that this is a valid response
|
46
|
-
# it will automatically render the result of the verification
|
47
|
-
# e.g. either the challenge phrase or false
|
48
|
-
subscription = Facebook::RealtimeUpdates.meet_challenge(params) do |verification_token|
|
49
|
-
token_parts = verification_token.split("|")
|
50
|
-
expected = Digest::MD5.hexdigest("#{token_parts.first}~koala")
|
51
|
-
logger.info "expected: #{expected}"
|
52
|
-
logger.info "got: #{token_parts.last}"
|
53
|
-
# determine if this is a valid token -- that is, if the send part is a properly encoding of the first
|
54
|
-
expected == token_parts.last
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
helpers do
|
59
|
-
def logger
|
60
|
-
LOGGER
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# helpers
|
65
|
-
|
66
|
-
# set up our understanding of the user's session
|
67
|
-
|
68
|
-
def set_access_token
|
69
|
-
# get the access token from wherever we can
|
70
|
-
@access_token ||= (set_oauth_data && @oauth_access_token) || (set_facebook_cookies && @cookie_access_token)
|
71
|
-
end
|
72
|
-
|
73
|
-
def set_oauth_data
|
74
|
-
unless @oauth_access_token
|
75
|
-
if (@code = params[:code]) && @raw_access_response = @oauth.send(:fetch_token_string, {:code => @code, :redirect_uri => @app_data["callback_url"]})
|
76
|
-
parsed = @oauth.send(:parse_access_token, @raw_access_response)
|
77
|
-
@oauth_access_token = parsed["access_token"]
|
78
|
-
@expiration = parsed["expires"] || "Does not expire (offline)"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
@oauth_access_token
|
83
|
-
end
|
84
|
-
|
85
|
-
def set_facebook_cookies
|
86
|
-
unless @facebook_cookies
|
87
|
-
if @facebook_cookies = @oauth.get_user_from_cookie(request.cookies)
|
88
|
-
@cookie_access_token = @facebook_cookies["access_token"]
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
@facebook_cookies
|
93
|
-
end
|
94
|
-
|
95
|
-
def set_uid
|
96
|
-
# get the OAuth data, including fetching the access token, if available and necessary
|
97
|
-
# e.g. if we have an OAuth token and no cookie data
|
98
|
-
unless @uid
|
99
|
-
if @facebook_cookies
|
100
|
-
@uid = @facebook_cookies["uid"]
|
101
|
-
elsif token = set_access_token
|
102
|
-
# we have to fetch the info
|
103
|
-
@graph = Facebook::GraphAPI.new(token)
|
104
|
-
result = @graph.get_object("me")
|
105
|
-
@uid = result["id"]
|
106
|
-
end
|
107
|
-
end
|
108
|
-
@uid
|
109
|
-
end
|
110
|
-
|
111
|
-
# fetch the active permissions about the user
|
112
|
-
def get_active_permissions
|
113
|
-
set_access_token
|
114
|
-
if @access_token && !@permissions && set_uid
|
115
|
-
# if we don't have permissions set but have an access token
|
116
|
-
# grab the user's info
|
117
|
-
@rest = Facebook::RestAPI.new(@access_token)
|
118
|
-
result = @rest.fql_query("select #{all_permissions.join(",")} from permissions where uid = #{@uid.to_s}")
|
119
|
-
result.first
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# list of permissions
|
124
|
-
|
125
|
-
def all_permissions
|
126
|
-
ACTIVITY_PERMISSIONS + USER_PERMISSIONS + FRIEND_PERMISSIONS
|
127
|
-
end
|
128
|
-
|
129
|
-
ACTIVITY_PERMISSIONS = [
|
130
|
-
:publish_stream, # Enables your application to post content, comments, and likes to a user's stream and to the streams of the user's friends, without prompting the user each time.
|
131
|
-
:create_event, # Enables your application to create and modify events on the user's behalf
|
132
|
-
:rsvp_event, # Enables your application to RSVP to events on the user's behalf
|
133
|
-
:sms, # Enables your application to send messages to the user and respond to messages from the user via text message
|
134
|
-
:offline_access # Enables your application to perform authorized requests on behalf of the user at any time. By default, most access tokens expire after a short time period to ensure applications only make requests on behalf of the user when the are actively using the application. This permission makes the access token returned by our OAuth endpoint long-lived.
|
135
|
-
]
|
136
|
-
|
137
|
-
USER_PERMISSIONS = [
|
138
|
-
:email, # Provides access to the user's primary email address in the email property. Do not spam users. Your use of email must comply both with Facebook policies and with the CAN-SPAM Act.
|
139
|
-
:read_insights, # Provides read access to the Insights data for pages, applications, and domains the user owns.
|
140
|
-
:read_stream, # Provides access to all the posts in the user's News Feed and enables your application to perform searches against the user's News Feed
|
141
|
-
:user_about_me, # Provides access to the "About Me" section of the profile in the about property
|
142
|
-
:user_activities, # Provides access to the user's list of activities as the activities connection
|
143
|
-
:user_birthday, # Provides access to the full birthday with year as the birthday_date property
|
144
|
-
:user_education_history, # Provides access to education history as the education property
|
145
|
-
:user_events, # Provides access to the list of events the user is attending as the events connection
|
146
|
-
:user_groups, # Provides access to the list of groups the user is a member of as the groups connection
|
147
|
-
:user_hometown, # Provides access to the user's hometown in the hometown property
|
148
|
-
:user_interests, # Provides access to the user's list of interests as the interests connection
|
149
|
-
:user_likes, # Provides access to the list of all of the pages the user has liked as the likes connection
|
150
|
-
:user_location, # Provides access to the user's current location as the current_location property
|
151
|
-
:user_notes, # Provides access to the user's notes as the notes connection
|
152
|
-
:user_online_presence, # Provides access to the user's online/offline presence
|
153
|
-
:user_photo_video_tags, # Provides access to the photos the user has been tagged in as the photos connection
|
154
|
-
:user_photos, # Provides access to the photos the user has uploaded
|
155
|
-
:user_relationships, # Provides access to the user's family and personal relationships and relationship status
|
156
|
-
:user_religion_politics, # Provides access to the user's religious and political affiliations
|
157
|
-
:user_status, # Provides access to the user's most recent status message
|
158
|
-
:user_videos, # Provides access to the videos the user has uploaded
|
159
|
-
:user_website, # Provides access to the user's web site URL
|
160
|
-
:user_work_history # Provides access to work history as the work property
|
161
|
-
]
|
162
|
-
|
163
|
-
FRIEND_PERMISSIONS = [
|
164
|
-
:read_friendlists, # Provides read access to the user's friend lists
|
165
|
-
:read_requests, # Provides read access to the user's friend requests
|
166
|
-
:friends_about_me, # Provides access to the "About Me" section of the profile in the about property
|
167
|
-
:friends_activities, # Provides access to the user's list of activities as the activities connection
|
168
|
-
:friends_birthday, # Provides access to the full birthday with year as the birthday_date property
|
169
|
-
:friends_education_history, # Provides access to education history as the education property
|
170
|
-
:friends_events, # Provides access to the list of events the user is attending as the events connection
|
171
|
-
:friends_groups, # Provides access to the list of groups the user is a member of as the groups connection
|
172
|
-
:friends_hometown, # Provides access to the user's hometown in the hometown property
|
173
|
-
:friends_interests, # Provides access to the user's list of interests as the interests connection
|
174
|
-
:friends_likes, # Provides access to the list of all of the pages the user has liked as the likes connection
|
175
|
-
:friends_location, # Provides access to the user's current location as the current_location property
|
176
|
-
:friends_notes, # Provides access to the user's notes as the notes connection
|
177
|
-
:friends_online_presence, # Provides access to the user's online/offline presence
|
178
|
-
:friends_photo_video_tags, # Provides access to the photos the user has been tagged in as the photos connection
|
179
|
-
:friends_photos, # Provides access to the photos the user has uploaded
|
180
|
-
:friends_relationships, # Provides access to the user's family and personal relationships and relationship status
|
181
|
-
:friends_religion_politics, # Provides access to the user's religious and political affiliations
|
182
|
-
:friends_status, # Provides access to the user's most recent status message
|
183
|
-
:friends_videos, # Provides access to the videos the user has uploaded
|
184
|
-
:friends_website, # Provides access to the user's web site URL
|
185
|
-
:friends_work_history # Provides access to work history as the work property
|
186
|
-
]
|
187
|
-
end
|