Статьи

Ruby Social Gems: LinkedIn

Введение в серию Ruby Social Gems

В этой серии мы расскажем о драгоценных камнях, основанных на социальных сетях и социальных сетях, таких как LinkedIn , Twitter , Facebook , Youtube и любые другие предлагаемые драгоценные камни.

LinkedIn Gem

Первая жемчужина в серии — это жемчужина LinkedIn и API-интерфейсы LinkedIn. Мы увидим, насколько простым и понятным является API LinkedIn, и как гем делает его более доступным.

Прежде чем мы начнем, я должен отметить еще одну важную жемчужину: omniauth и omniauth-linkedin. Эти драгоценные камни позволяют пользователю входить в систему с помощью своей учетной записи LinkedIn, Facebook, Twitter и т. Д. Мы посвятим учебник Omniauth позже, но в этой статье мы будем использовать Devise для создания простых учетных записей пользователей.

Демо-приложение

Приложение, которое мы собираемся создать с помощью самоцвета LinkeIn, довольно простое. Мы получим все пользовательские данные из LinkedIn в наших моделях приложений rails, чтобы мы могли отображать их в любом формате, который нам нужен.

Начиная с приложения:

Вы можете скачать полный исходный код формы github здесь

Создайте новое приложение rails:
rails new rsg_linkedin_gem

Добавьте Gem, devise, bootstrap gems в path/to/project/Gemfile

gem ‘devise’
gem ‘linkedin’
gem ‘twitter-bootstrap-rails’

view raw
gemfile.rb
hosted with ❤ by GitHub

А потом беги
bundle install

Мы собираемся использовать начальную загрузку для компонента пользовательского интерфейса.

Инициализация

Прежде чем начать, нам нужно выполнить несколько команд для инициализации проекта.

Создание пользовательской модели и стиля Bootstrap

Следующие команды находятся на странице github проекта devise и проекта начальной загрузки Twitter.

Чтобы установить устройство
rails generate devise:install

Создать пользовательскую модель
rails generate devise user

Чтобы настроить представления
rails generate devise:views

Чтобы установить загрузчик
rails g bootstrap:install

Чтобы установить макет начальной загрузки
rails g bootstrap:layout application fixed

Удалить индексный файл из
path/to/project/public/index.html

Структура приложения

Контроллеры

Нам потребуется только создать один контроллер, который будет обрабатывать соединение с LinkedIn. Контроллер будет извлекать данные из API и передавать их нашим моделям.

rails g controller linkedin

Добавьте следующую строку в начале контроллера linkedin

before_filter :authenticate_user!

Мы добавим несколько вспомогательных методов для обработки запросов аутентификации и API.

Во-первых, и прежде чем углубляться в какие-либо методы, мы должны определить хэш конфигурации. Хеш содержит всю информацию для согласования соединения с API-интерфейсами LinkedIn. Элемент request_token_path предоставляет разрешения для доступа к различным частям API, таким как r_fullprofile для полного профиля или r_network для соединений.

Вы можете добавить больше токенов к элементу request_token_path , связав их знаком + , например:
/uas/oauth/requestToken?scope=r_basicprofile+r_fullprofile+r_emailaddress+r_network

Полный объект, который мы добавим вверху контроллера LinkedIn, находится ниже:

@@config = {
:site => ‘https://api.linkedin.com’,
:authorize_path => ‘/uas/oauth/authenticate’,
:request_token_path => ‘/uas/oauth/requestToken?scope=r_basicprofile+r_fullprofile’,
:access_token_path => ‘/uas/oauth/accessToken’
}

Объект LinkedinOauthSetting используется для хранения токена доступа и доступа к секрету.

Цель метода generate_linkedin_oauth_url состоит в том, чтобы сгенерировать URI аутентификации linkedin, который запрашивает у пользователя разрешения. Метод сначала проверяет, существует ли объект для текущего пользователя. Если нет, то он создаст клиентский объект linkedin и создаст объект request_token с помощью oauth_callback . Этот обратный вызов является методом, который будет вызван после того, как пользователь предоставит доступ. Теперь сохраните request_token.token и request_token.secret в сеансе, поскольку они будут использоваться для создания постоянных токенов доступа. Наконец, перенаправьте пользователя на authorize_url . Если пользователь уже был здесь, он перенаправит его непосредственно в действие /oauth_account .

generate_linkedin_oauth_url

def generate_linkedin_oauth_url
if LinkedinOauthSetting.find_by_user_id(current_user.id).nil?
client = LinkedIn::Client.new(‘your-api-key’, ‘your-secret-key’, @@config)
request_token = client.request_token(:oauth_callback => «http://#{request.host}:#{request.port}/oauth_account»)
session[:rtoken] = request_token.token
session[:rsecret] = request_token.secret
redirect_to request_token.authorize_url
else
redirect_to «/oauth_account»
end
end

Метод аутентификации, который устанавливается в качестве обратного вызова в объекте request_token , аутентифицирует пользователя в первый раз. Если пользователь уже аутентифицирован, он будет перенаправлять пользователя домой без каких-либо действий.

oauth_account

def oauth_account
client = LinkedIn::Client.new(‘your-api-key’, ‘your-secret-key’, @@config)
pin = params[:oauth_verifier]
if pin
atoken, asecret = client.authorize_from_request(session[:rtoken], session[:rsecret], pin)
LinkedinOauthSetting.create!(:asecret => asecret, :atoken => atoken, :user_id => current_user.id)
end
redirect_to «/»
end

Во-первых, мы создаем клиентский объект linkedin с нашими ключами (‘your-api-key’, ‘your-secret-key’), которые вы получаете после регистрации приложения в подключенном api . Если существуют параметры oauth_verifier , которые передаются LinkedIn, пользователь предоставил доступ к приложению, поэтому мы авторизуем клиента. Когда мы авторизируемся в первый раз, нам нужно сохранить и получить токен доступа и секрет, чтобы получить их позже.

get_client просто возвращает авторизованный клиентский объект linkedin. Здесь объект linkedin_oauth_setting извлекается из базы данных и авторизует клиентский объект.

get_client

def get_client
linkedin_oauth_setting = LinkedinOauthSetting.find_by_user_id(current_user.id)
client = LinkedIn::Client.new(‘iv6uehul4g5m’, ‘wtMfG2MbFerSULTC’, @@config)
client.authorize_from_access(linkedin_oauth_setting.atoken, linkedin_oauth_setting.asecret)
client
end

view raw
get_client.rb
hosted with ❤ by GitHub

Вот корневое действие. Он проверяет, есть ли у этого пользователя настройка «oauth». Если это так, он перенаправит их на действие linkedin_profile.
index

def index
unless LinkedinOauthSetting.find_by_user_id(current_user.id).nil?
redirect_to «/linkedin_profile»
end
end

view raw
index.rb
hosted with ❤ by GitHub

Здесь мы показываем простую HTML-страницу данных, извлеченных из API-интерфейсов linkedin.
linkedin_profile

def linkedin_profile
basic_profile = get_basic_profile
full_profile = get_full_profile
positions = get_positions
educations = get_educations
end

Маршруты

Добавьте следующее в path/to/project/config/routes

resources :linkedin
match ‘/linkedin_profile’
match ‘/oauth_account’ => «linkedin#oauth_account»
match ‘/linkedin_oauth_url’ => ‘linkedin#generate_linkedin_oauth_url’
root :to => ‘linkedin#index’

view raw
routes.rb
hosted with ❤ by GitHub

Взгляды

Мы должны сделать несколько изменений перед запуском сервера.

Измените path/to/project/app/views/layouts/application.html.erb представления макета path/to/project/app/views/layouts/application.html.erb
удалив следующий блок 65-75 , а затем заменив следующие строки 50-52 на

<li><%= link_to current_user.email, «/users/edit» %></li>
<li><%= link_to «Sign out», «/users/sign_out», :method => «DELETE» %></li>

Измените представление индекса [путь / к / проекту / приложению / views / linkedin / index.html.erb]:

<h1>Linkedin Application</h1>
<a href/linkedin_oauth_url» classbtn btn-primary btn-larg«>Connect to LinkedIn</a>

view raw
index.html.erb
hosted with ❤ by GitHub

модели

Мы должны остановиться здесь, чтобы взглянуть на API-интерфейсы LinkedIn и на то, что мы рассмотрим здесь. Мы также изучим спецификацию моделей, которые нам нужно создать в нашем приложении.

Сайт разработчиков LinkedIn — это лучшее место, это краткое руководство является исчерпывающим. В руководстве показано, как создать приложение на LinkedIn, а также как получить ключ API и секретный ключ (которым вы никогда не должны делиться ни с кем).

Вы увидите демонстрацию того, как соединиться со скриптом ruby ​​без каких-либо драгоценных камней, что занимает гораздо больше времени, чем драгоценный камень.

В таблице на странице Аутентификация перечислены разрешения, которые мы увидим, как их использовать позже.

Вот несколько из них:

разрешение Сфера
Ваш профиль Обзор r_basicprofile
Ваш полный профиль r_fullprofile
Ваша электронная почта r_emailaddress
Ваши связи r_network

Мы сфокусируемся на части API полей профиля , потому что не можем охватить весь API. Я думаю, вы получите хорошее представление о том, как работает самоцвет, написав это демо-приложение.

Давайте сначала сосредоточимся на полях базового профиля . Это будет первая часть API, которая будет привязана к нашему приложению rails.

LinkedinOauthSetting

Это важная модель, в которой для каждого пользователя хранятся два важных значения, которые разрешают доступ к его учетной записи без запроса разрешения каждый раз.

Выполните следующие команды для генерации вышеуказанной модели:

rails g model linkedin_oauth_setting atoken:string asecret:string user_id:integer
rake db:migrate

Не забывайте всегда проверять эту строку над каждой таблицей «Для этих полей требуется разрешение члена r_basicprofile », чтобы использовать эти параметры разрешения позже.

Добавьте ассоциацию к модели linkedin_oauth_setting:
path/to/project/app/models/linkedin_oauth_setting.rb

belongs_to :user

BasicProfile

Выберите несколько атрибутов для добавления в модель, и вот их список:

поле Описание
Имя имя участника
фамилия фамилия участника
девичья фамилия девичья фамилия участника
отформатирован имя имя участника отформатировано на основе языка
Заголовок заголовок участника (часто «Должность в компании»)
название местоположения) Общее название местоположения члена LinkedIn (например: «Область залива Сан-Франциско»)
промышленность отрасль, в которой участник LinkedIn указал свой профиль (отраслевые коды)
резюме Длинная текстовая область, где участник описывает свой профессиональный профиль
специальности Краткая текстовая область, где участник перечисляет свои специальности
фото гиперссылка URL-адрес изображения профиля, если участник связал его со своим профилем, и он виден запрашивающей стороне
общественные профильный URL URL-адрес общедоступного профиля участника, если он включен

Теперь выполните следующую команду, чтобы создать таблицу basic_profiles :

rails g model basic_profile first_name:string last_name:string maiden_name:string formatted_name:string headline:string location:string industry:string summary:string specialties:string picture_url:string public_profile_url:string user_id:integer

rake db:migrate

Добавьте ассоциацию к модели basic_profile:
path/to/project/app/models/basic_profile.rb

belongs_to :user

FullProfile

Выбрав несколько атрибутов для добавления в модель, вы заметите, что таблица full_profile содержит много других сложных объектов, таких как ( publications , patents , languages , skills и т. Д.). Мы собираемся создать отдельные модели для нескольких из них. Вот их список:

поле Описание
ассоциации Краткая текстовая область, перечисляющая Ассоциации, которые имеет член
почести Краткая текстовая область с описанием почестей, которые может иметь участник
интересы Краткая текстовая область с описанием интересов участника

Теперь выполните следующую команду, чтобы создать таблицу full_profiles :

rails g model full_profile associations:string honors:string interests:string user_id:integer

rake db:migrate

Добавьте ассоциацию к модели full_profile:
path/to/project/app/models/full_profile.rb

belongs_to :user
has_many :educations
has_many :positions

Позиция

Давайте добавим несколько атрибутов в модель:

поле Описание
заглавие должность, занимаемая на должности, указанной участником
резюме краткое изложение позиции члена
Дата начала структурированный объект с полями месяца и года, указывающими, когда началась позиция
Дата окончания структурированный объект с полями месяца и года, указывающими, когда позиция закончилась
это тока значение «истина» или «ложь», в зависимости от того, отмечено ли оно текущим
Компания компания, в которой работает участник

Теперь выполните следующую команду, чтобы создать таблицу positions :

rails g model position title:string summary:string start_date:date end_date:date is_current:boolean company:string full_profile_id:integer

rake db:migrate

Добавьте ассоциацию к модели позиции:
path/to/project/app/models/position.rb

belongs_to :full_profile

view raw
position.rb
hosted with ❤ by GitHub

образование

Для модели образования у нас есть:

поле Описание
название школы название школы, указанное участником
область изучения область обучения в школе, как указано участником
Дата начала структурированный объект поле года, указывающее, когда началось образование
Дата окончания структурированный объект с полем года, указывающим, когда закончилось образование
степень строка, описывающая степень, если таковая имеется, полученную в этом учреждении
виды деятельности строка, описывающая действия, в которых участник принимал участие, будучи студентом в этом учреждении
Примечания строка, описывающая другие детали исследований участника

Теперь выполните следующую команду для создания таблицы educations :

rails g model education school_name:string field_of_study:string start_date:date end_date:date degree:string activities:string notes:string full_profile_id:integer

rake db:migrate

Добавьте ассоциацию к модели:
path/to/project/app/models/education.rb

belongs_to :full_profile

view raw
education.rb
hosted with ❤ by GitHub

пользователь

Добавьте ассоциацию к модели:
path/to/project/app/models/user.rb

has_one :basic_profile
has_one :full_profile
has_one :linkedin_oauth_setting

view raw
user.rb
hosted with ❤ by GitHub

Запросы API-интерфейсов LinkedIn

Теперь в контроллере linkedin есть необходимые вспомогательные методы для аутентификации. Мы сохранили необходимые токены для последующего доступа, поэтому пришло время написать несколько вспомогательных методов для запроса API. Мы будем использовать модельные объекты для этой части.

Запросить API-интерфейсы очень просто. После авторизации объекта client вы вызываете метод profile для объекта и передаете все поля, которые хотите получить, например:
client.profile(:fields => [:first_name, :last_name, :maiden_name , :formatted_name ,:headline])

Следующие методы используются для извлечения данных из API и передачи их в модели рельсов. Как видите, мы создаем объект с помощью извлеченного объекта json из API с несколькими настройками.

get_basic_profile

def get_basic_profile
bprofile = BasicProfile.find_by_user_id(current_user.id)
if bprofile.nil?
client = get_client
profile = client.profile(:fields => [«first-name», «last-name», «maiden-name», «formatted-name» ,:headline, :location, :industry, :summary, :specialties, «picture-url», «public-profile-url»])
basic_profile = profile.to_hash
basic_profile[:location] = basic_profile[«location»][«name»]
new_basic_profile = BasicProfile.new(basic_profile)
new_basic_profile.user = current_user
new_basic_profile.save
new_basic_profile
else
bprofile
end
end

get_full_profile

def get_full_profile
fprofile = FullProfile.find_by_user_id(current_user.id)
if fprofile.nil?
client = get_client
full_profile = client.profile(:fields => [:associations, :honors, :interests])
full_profile = full_profile.to_hash
new_full_profile = FullProfile.new(full_profile)
new_full_profile.user = current_user
new_full_profile.save
new_full_profile
else
fprofile
end
end

get_positions

def get_positions
positions = Position.find_all_by_full_profile_id(current_user.full_profile.id)
if positions.empty?
client = get_client
positions = client.profile(:fields => [:positions]).positions.all
positions.each do |p|
if p.is_current == «true»
Position.create(
title: p.title,
summary: p.summary,
start_date: Date.parse(«1/#{p.start_date.month ? p.start_date.month : 1}/#{p.start_date.year}«),
end_date: Date.parse(«1/#{p.end_date.month ? p.end_date.month : 1}/#{p.end_date.year}«),
is_current: p.is_current,
company: p.company.name,
full_profile_id: current_user.full_profile.id)
else
Position.create(
title: p.title,
summary: p.summary,
start_date: Date.parse(«1/#{p.start_date.month ? p.start_date.month : 1}/#{p.start_date.year}«),
is_current: p.is_current,
company: p.company.name,
full_profile_id: current_user.full_profile.id)
end
end
current_user.full_profile.positions
else
positions
end
end

get_educations

def get_educations
educations = Education.find_all_by_full_profile_id(current_user.full_profile.id)
if educations.empty?
client = get_client
educations = client.profile(:fields => [:educations]).educations.all
educations.each do |e|
new_educations = Education.create(
school_name: e.school_name,
field_of_study: e.field_of_study,
start_date: Date.parse(«1/#{e.end_date.month ? p.end_date.month : 1}/#{e.end_date.year}«),
end_date: Date.parse(«1/#{e.end_date.month ? p.end_date.month : 1}/#{e.end_date.year}«),
degree: e.degree,
activities: e.activities,
notes: e.notes,
full_profile_id: current_user.full_profile.id)
end
current_user.full_profile.educations
else
educations
end
end

Есть несколько примеров в репозитории gem на github, например:

# update status for the authenticated user
client.update_status(‘is playing with the LinkedIn Ruby gem’)
# clear status for the currently logged in user
client.clear_status
# get network updates for the authenticated user
client.network_updates
# get profile picture changes
client.network_updates(:type => ‘PICT’)
# view connections for the currently authenticated user
client.connections

view raw
example1.rb
hosted with ❤ by GitHub

Давайте соединим все это и создадим простое представление для отображения в нашем приложении для отображения сохраненных данных.

Вот path/to/project/linkedin/linkedin_profile.html.erb просмотра path/to/project/linkedin/linkedin_profile.html.erb

<div classrow«>
<div classspan4«>
<div classthumbnail«>
<img src<%= @basic_profile.picture_url %>» stylefloat: left;margin: 5px;«>
<h3><%= @basic_profile.formatted_name %></h3>
<h4><%= @basic_profile.headline %></h4>
<br>
<p><%= @basic_profile.summary %></p>
</div>
</div>
<div classspan4«>
<div classwell«>
<h5>Interests</h5>
<p><%= @full_profile.interests %></p>
<br>
<h5>Associations</h5>
<p><%= @full_profile.associations %></p>
<br>
<h5>Honors</h5>
<p><%= @full_profile.honors %></p>
<br>
</div>
</div>
</div>
<div classrow» stylemargin-top: 16px;«>
<div classspan10«>
<h1>Positions</h1>
<table classtable table-striped«>
<tr>
<th>Title</th>
<th>Summary</th>
<th>Company Name</th>
<th>Is Current</th>
<th>Start Date</th>
<th>End Date</th>
</tr>
<% @positions.each do |p| %>
<tr>
<th><%= p.title %></th>
<th><%= p.summary %></th>
<th><%= p.company %></th>
<th><%= p.is_current %></th>
<th><%= p.start_date %></th>
<th><%= p.end_date %></th>
</tr>
<% end %>
</table>
</div>
</div>
<div classrow» stylemargin-top: 16px;«>
<div classspan10«>
<h1>Educations</h1>
<table classtable table-striped«>
<tr>
<th>School Name</th>
<th>Field of Study</th>
<th>Degree</th>
<th>Activities</th>
<th>Notes</th>
<th>Start Date</th>
<th>End Date</th>
</tr>
<% @educations.each do |e| %>
<tr>
<th><%= e.school_name %></th>
<th><%= e.field_of_study %></th>
<th><%= e.degree %></th>
<th><%= e.activities %></th>
<th><%= e.notes %></th>
<th><%= e.start_date %></th>
<th><%= e.end_date %></th>
</tr>
<% end %>
</table>
</div>
</div>

Завершение

Что ж, я надеюсь, что это руководство будет полезным, и будет хорошим введением в использование гема LinkedIn и API в целом, если вы хотите предложить следующий гем, который мы рассмотрим, мы его выполним и спасибо за чтение.