Rails twitter gem将twitter数据添加到rails数据库

时间:2016-10-02 21:49:03

标签: ruby-on-rails activerecord twitter omniauth

所以我使用omniauth允许用户登录Twitter。他们的数据被传递到用户模型和数据库。这将基于Omniauth数据创建一个带有current_user的新会话。我安装了twitter gem,并将配置信息保存在名为twitter_client的方法中。在视图中,我随后打电话给'粉丝'使用来自数据库的current_user的推特名称在twitter_client上的方法,以显示用户的关注者而非登录。

我想知道如何将用户的关注者存储在数据库中,然后在数据库中的视图中显示关注者,而不是直接从twitter。我知道它涉及迭代模型中的current_user追随者(我创建了一个follower.rb模型和一个追随者控制器)。但是,我正在努力将这一切联系在一起的复杂性。

当前视图index.html.erb

 <div class="twitter_list">
          <p id="list_title">Followers of <%= current_user.name %>:</p>
          <% twitter_client.followers(current_user.twitter_user_name).each do        |follower| %>
            <p><%= follower.name %></p>
            <hr>
          <% end %>
        </div>

用户模型:

class User < ApplicationRecord
  def self.from_omniauth(auth_hash)
  #Look up the user or create them using keys in the auth hash
  user = where(provider: auth_hash.provider, uid: auth_hash.uid).first_or_create
  user.update(
  name: auth_hash.info.name,
  profile_image: auth_hash.info.image,
  twitter_user_name: auth_hash.info.nickname,
  token: auth_hash.credentials.token,
  secret: auth_hash.credentials.secret
 )
  user
end

应用程序控制器:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

  def twitter_client
    @client ||= Twitter::REST::Client.new do |config|
    config.consumer_key        = Rails.application.secrets.twitter_api_key
    config.consumer_secret     = Rails.application.secrets.twitter_api_secret
    config.access_token        = current_user.token
    config.access_token_secret = current_user.secret
  end
 end

# to enable the current_user variable to be used in the view file
helper_method :current_user, :twitter_client

会话控制器:

class SessionsController < ApplicationController
  def create
    # complete omniauth authentication and crate user record in database
    # raise env["omniauth.auth"].to_yaml

  @user = User.from_omniauth(auth_hash)
  session[:user_id] = @user.id
  redirect_to root_path
end

def destroy
  session[:user_id] = nil
  redirect_to root_path, notice: "You are signed out"
end

protected

def auth_hash
  request.env['omniauth.auth']
end

当前对追随者控制器和追随者模型的尝试(不确定如何继续):

class FollowersController < ApplicationController

  def index
    @followers = Follower.all
  end

  def new
    @followers = Follower.new
  end

  def create
    @followers = Follower.new(post_params)
  end

  private

  def post_params
    params.require(:followers).permit(:followers)
  end
end


class Follower < ApplicationRecord

  twitter_client.followers(current_user.twitter_user_name).each do |follower|
    follower.name
  end

end

1 个答案:

答案 0 :(得分:0)

让我们从基本问题开始:

  

显示用户关注者,而不是每次从Twitter获取它   时间。

为每个关注者创建一个数据库实体可能实际上并不是最好的解决方案 - 它的数据实际上并不是你的,你的用户也不会编辑资源。它还增加了保持数据库与twitter同步的需要。

在您的应用中拥有代表关注者的模型仍然是一个好主意,因为它可以让您进行规范化并使用翻译API。它还可以将您的应用程序与外部API中的更改隔离开来。

因此,请创建Follower model that is not backed by the database。用来自twitter的数据填充它。并使用缓存来避免twitter api查询。

# note that it should not inherit from ActiveRecord::Base
class Follower 
  include ActiveModel::Model
  attr_accessor :twitter_uid, :name, :screen_name
end

获取数据

所以我们要做的是从twitter获取数据并使用它创建模型实例 - 这样做的好方法是创建服务:

# app/services/followers_service.rb
module FollowersService
  def self.call(user, client: nil)
    client = client || self.twitter_client(user)
    followers = twitter_client.followers(current_user.twitter_user_name)
    followers.map do |raw|
      # @todo check the actual response from Twitter
      Follower.new do |f|
        f.twitter_uid  = raw["id"]
        f.name         = raw["name"]
        f.screen_name  = raw["screen_name"]
      end
    end
  end

  private 
    def self.twitter_client(user)
      def twitter_client
       secrets = Rails.application.secrets
       Twitter::REST::Client.new do |config|
         config.consumer_key        = secrets.twitter_api_key
         config.consumer_secret     = secrets.twitter_api_secret
         config.access_token        = user.token
         config.access_token_secret = user.secret
      end
    end
end

我们现在可以通过调用FollowersService.call(User.first)来单独测试它。额外的客户端参数允许我们注入一个double来轻松伪造测试中的twitter响应。

缓存结果。

缓存响应的一种方法是使用片段缓存,例如我们在侧边栏中显示关注者:

<%= cache("user-{current_user.id}-followers", expires_in: 1.day)  do %>
  <% FollowersService.call(current_user).each do |f| %>
    <%= f.name %>
  <% end %> 
<% end %>

缓存渲染的视图。如果您在许多不同的地方使用数据,则可能需要使用low level caching代替:

@followers = Rails.cache.fetch("user-{current_user.id}-followers", expires_in: 12.hours) do
  FollowersService.call(current_user)
end

控制器怎么样?

你真的需要一个单独的追随者控制器吗?如果你真的需要一条路线来显示追随者或获取ajax的数据,你可以创建一个简单的控制器:

class FollowersController
  # GET /followers
  def index
    @followers = Rails.cache.fetch("user-{current_user.id}-followers", expires_in: 12.hours) do
      FollowersService.call(current_user)
    end
  end
end

您不需要整个rails CRUD操作集,因为数据是从外部源获取的,而不是由用户创建/修改的。