所以我使用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
答案 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操作集,因为数据是从外部源获取的,而不是由用户创建/修改的。