Net::HTTP
, blocking the reactor of the event machine I was aiming at. Also in terms of documentation for some reason, everything was very sad, and I had to constantly read the source code.faraday
, the library supports calling any API methods, uploading files to VKontakte servers and optional authorization, not accepting the decisions mentioned in the previous paragraph as a programmer.vkontakte_api
. As an example, an uncomplicated web application that displays a news feed (API method newsfeed.get ), a list of friends ( friends.get ) and groups ( groups.get ) of a user who has passed OAuth2 authorization will fit. And it will look something like this:VkontakteApi.configure
block, which is conveniently placed in config/initializers/vkontakte_api.rb
; In the rails application, you can generate this file with default settings using the built-in generator. $ rails generate vkontakte_api:install
# config/initializers/vkontakte_api.rb VkontakteApi.configure do |config| config.app_id = '123' # ID config.app_secret = 'AbCdE654' # config.redirect_uri = 'http://vkontakte-on-rails.herokuapp.com/callback' end
omniauth
via VKontakte, so omniauth
will be inappropriate to use omniauth
- we use the capabilities of vkontakte_api
.code
parameter to the URL. Then the application, using this code, receives the token and user_id
user with a separate request and saves them in the session.state
parameter with an unanticipated value when sending a user for authorization, having previously saved it in a protected place; and when the user returns, check the state
parameter with the saved value.vkontakte_api
provides the VkontakteApi.authorization_url
helper to generate the URL of this page; in the parameters you need to transfer the scope
- these are the rights that the application will receive in the form of an array of characters (or strings with names separated by commas) - and the state
described above. # app/controllers/sessions_controller.rb class SessionsController < ApplicationController def new # state srand session[:state] ||= Digest::MD5.hexdigest(rand.to_s) # URL @vk_url = VkontakteApi.authorization_url(scope: [:friends, :groups, :offline, :notify], state: session[:state]) end end
<!-- app/views/sessions/new.html.erb --> <%= link_to @vk_url, class: 'btn btn-primary' do %> <i class="icon-home icon-white"></i> <% end %>
state
if notify
is not specified in scope
.redirect_uri
settings (containing the path to SessionsController#callback
), while the state
and code
parameters will be passed to the URL. As mentioned above, the state
needs to be checked against the one already saved; and code
stop on code
in more detail.vkontakte_api
also provides a helper - VkontakteApi.authorize
, the only parameter - the notorious code
. # encoding: utf-8 class SessionsController < ApplicationController def callback # state if session[:state].present? && session[:state] != params[:state] redirect_to root_url, alert: ' , .' and return end # @vk = VkontakteApi.authorize(code: params[:code]) # session[:token] = @vk.token # id - session[:vk_id] = @vk.user_id redirect_to root_url end end
class SessionsController < ApplicationController def destroy session[:token] = nil session[:vk_id] = nil redirect_to root_url end end
VkontakteApi::Client
object. In the constructor you just need to pass the token.vk.users.get(params)
. In accordance with the conventions adopted in the ruby ​​community, the names of the methods are written in snake_case
: the API method likes.getList
can be called as vk.likes.get_list
.vk.users.get(uid: 1)
. If the API expects to receive a parameter with a collection of objects listed separated by commas, then they can be passed as an array - vkontakte_api
stick it together automatically (the scope
parameter in the authorization is processed in the same way). In this case, instead of strings, you can use symbols.newsfeed.get
, friends.get
, groups.get
and users.get
respectively (the latter will be called by passing the id parameter of our user). The result of newsfeed.get
contains separately the news itself, containing the id of users and groups, and separately the arrays with the mentioned users and groups; The MainController#process_feed
method, not shown here, adds to each news its source (user or group that wrote a post) under the key source
. class MainController < ApplicationController def index # API vk = VkontakteApi::Client.new(session[:token]) # @user = vk.users.get(uid: session[:vk_id], fields: [:screen_name, :photo]).first # @friends = vk.friends.get(fields: [:screen_name, :sex, :photo, :last_seen]) # , @friends_online = @friends.select { |friend| friend.online == 1 } # @groups = vk.groups.get(extended: 1) # - - ; @groups.shift # raw_feed = vk.newsfeed.get(filters: 'post') # @newsfeed = process_feed(raw_feed) end end
Hashie::Mash
- this is an extension of the standard Hash
from the hashie gem , which allows accessing the element through a method whose name corresponds to the key of this element in the hash ( user.name == user[:name]
). <%= link_to vk_url(@user), target: '_blank' do %> <%= image_tag(@user.photo, width: 20) %> <%= "#{@user.first_name} #{@user.last_name}" %> <% end %>
vk_url
, name_for
, avatar_for
etc.) are used, defined in the application - they are all quite trivial, if you wish, you can read the code here . <!-- app/views/main/index.html.erb --> <% @newsfeed.each do |item| %> <tr> <td> <%= link_to vk_url(item.source), target: '_blank' do %> <%= image_tag avatar_for(item.source) %> <% end %> </td> <td class="wide"> <div class="pull-right"><%= formatted_time_for(item.date) %></div> <%= link_to name_for(item.source), vk_url(item.source), target: '_blank' %> <p><%=raw render_links(item.text) %></p> <% item.attachments.each do |attachment| %> <%= render 'attachment', attachment: attachment %> <% end if item.attachments? %> </td> </tr> <% end %> <!-- app/views/main/_attachment.html.erb --> <p> <% case attachment.type %> <% when 'link' %> <%= link_to attachment.link.title, attachment.link.url, target: '_blank' %> <% when 'photo' %> <%= image_tag attachment.photo.src_big %> <% when 'video' %> <%= image_tag attachment.video.image_big %> <% end %> </p> <div class="clearfix"></div>
<!-- app/views/main/_sidebar.html.erb --> <div class="tab-pane active" id="friends_online"> <h6> </h6> <%= render 'friends', friends: @friends_online %> </div> <div class="tab-pane" id="friends"> <h6> </h6> <%= render 'friends', friends: @friends %> </div> <div class="tab-pane" id="groups"> <h6></h6> <%= render 'groups' %> </div> <!-- app/views/main/_friends.html.erb --> <table class="table"> <% if friends.empty? %> <tr> <td> </td> </tr> <% else %> <% friends.each do |friend| %> <tr> <td> <%= link_to image_tag(friend.photo), vk_url(friend), target: '_blank' %> </td> <td class="wide"> <i class="icon-user"></i> <%= link_to "#{friend.first_name} #{friend.last_name}", vk_url(friend), target: '_blank' %> <br /> <%= online_status(friend) %> </td> </tr> <% end %> <% end %> </table> <!-- app/views/main/_groups.html.erb --> <table class="table"> <% if @groups.empty? %> <tr> <td> </td> </tr> <% else %> <% @groups.each do |group| %> <tr> <td> <%= link_to image_tag(group.photo), vk_url(group), target: '_blank' %> </td> <td class="wide"> <i class="icon-comment"></i> <%= link_to group.name, vk_url(group), target: '_blank' %> </td> </tr> <% end %> <% end %> </table>
vkontakte_api
Source: https://habr.com/ru/post/151585/
All Articles