首页 > 解决方案 > Rails:如何将 gem 的类保存为我的数据库中的模型?

问题描述

我一直在构建一个 Google Tasks 集成应用程序,只是切换到使用 Google API 客户端(gem 'google-api-client', '~> 0.34'

这给了我一些我真正开始喜欢的课程:

Google::Apis::TasksV1::Task
Google::Apis::TasksV1::TaskList
Google::Apis::TasksV1::Tasks # (for multiple records)
Google::Apis::TasksV1::TaskLists # (for multiple records)

这些类带有我想要的所有属性,我认为在我的数据库中实际拥有这些记录而不是我现在正在做的事情会很好,这是使用 OAuth 的 HTTP 请求(使用 gem 提供的方法)

将他们的 gem 集成到自定义类中后,我可以执行以下操作:

> ts = TaskService.new(user)
=> #<TasksService:0x00007f973be03bc8 @user=#<User #userstuff>, @service=#<Google::Apis::TasksV1::TasksService:0x00007f973be03b28 @root_url="https://www.googleapis.com/", @base_path="tasks/v1/", @upload_path="upload/tasks/v1/", @batch_path="batch/tasks/v1", @client_options=#<struct Google::Apis::ClientOptions #morestuff>, @request_options=#<struct Google::Apis::RequestOptions authorization=#<Signet::OAuth2::Client:0x00007f973be02020 @authorization_uri=#<Addressable::URI:0x3fcb9df05304 URI:https://accounts.google.com/o/oauth2/auth>, @token_credential_uri=#<Addressable::URI:0x3fcb9db99f08 URI:https://accounts.google.com/o/oauth2/token>, @client_id="secret", @client_secret="secret", @code=nil, @expires_at=nil, @issued_at=nil, @issuer=nil, @password=nil, @principal=nil, @redirect_uri=nil, @scope=nil, @state=nil, @username=nil, @access_type=:offline, @expiry=60, @extension_parameters={}, @additional_parameters={}, @access_token="secret", @id_token=nil>, retries=0, header=nil, normalize_unicode=false, skip_serialization=false, skip_deserialization=false, api_format_version=nil, use_opencensus=true>>>

> ts.service.list_tasklists
Sending HTTP get https://www.googleapis.com/tasks/v1/users/@me/lists?
200
#<HTTP::Message:0x00007f973b79ceb0 #all the stuff>
Success - #<Google::Apis::TasksV1::TaskLists:0x00007f973e032168
 @etag="\"LTY2NzExNzU1Mg\"",
 @items=
  [#<Google::Apis::TasksV1::TaskList:0x00007f973e0a2a58
    @etag="\"Mzk0NzU3MDky\"",
    @id="MDc1MjQ5ODU0NzUwMjI4NDkwMTM6MDow",
    @kind="tasks#taskList",
    @self_link=
     "https://www.googleapis.com/tasks/v1/users/@me/lists/MDc1MjQ5ODU0NzUwMjI4NDkwMTM6MDow",
    @title="My list",
    @updated=Wed, 18 Dec 2019 05:42:34 +0000>,
   #<Google::Apis::TasksV1::TaskList:0x00007f973bf298b8
    @etag="\"Mzk0OTEzMTI0\"",
    @id="eHFkTG9UUkl3d1ZQcTdCOA",
    @kind="tasks#taskList",
    @self_link=
     "https://www.googleapis.com/tasks/v1/users/@me/lists/eHFkTG9UUkl3d1ZQcTdCOA",
    @title="Another List",
    @updated=Wed, 18 Dec 2019 05:45:10 +0000>,
   ... # brevity is the soul of ...

=> #<Google::Apis::TasksV1::TaskLists:0x00007f973e032168 @etag="\"LTY2NzExNzU1Mg\"", @items=[#<Google::Apis::TasksV1::TaskList:0x00007f973e0a2a58 @etag="\"Mzk0NzU3MDky\"", @id="MDc1MjQ5ODU0NzUwMjI4NDkwMTM6MDow", @kind="tasks#taskList", @self_link="https://www.googleapis.com/tasks/v1/users/@me/lists/MDc1MjQ5ODU0NzUwMjI4NDkwMTM6MDow", @title="FamilyPromiseGR's list", @updated=Wed, 18 Dec 2019 05:42:34 +0000>, #<Google::Apis::TasksV1::TaskList:0x00007f973bf298b8 @etag="\"Mzk0OTEzMTI0\"", @id="eHFkTG9UUkl3d1ZQcTdCOA", @kind="tasks#taskList", @self_link="https://www.googleapis.com/tasks/v1/users/@me/lists/eHFkTG9UUkl3d1ZQcTdCOA", @title="Vinewood Ave NE", @updated=Wed, 18 Dec 2019 05:45:10 +0000>, ... # brevity is the soul of ...

这些项目以结构化类的形式回归!这很棒!

但是,每次通话都会有大量延迟。

我在作业中运行这些命令,但我也在考虑将这些命令保存到我的数据库(postgresql)中,并且只是比较updated时间戳而不是每次需要时都提取信息。

所以,这是我的问题:

如何按原样上课并使其成为我数据库中的模型?

我希望能够调用Google::Apis::TasksV1::Task.create(tasklist_attrs)和其他此类模型类型的方法。

我注意到它们的响应与我自己的类(继承自ActiveRecord::Base)不同:

2.6.3 :008 > User.new
 => #<User id: nil, name: nil, title: nil, phone: nil, admin: false, staff: false, client: false, volunteer: false, contractor: false, email: "", oauth_provider: nil, oauth_id: nil, oauth_image_link: nil, oauth_token: nil, oauth_refresh_token: nil, oauth_expires_at: nil, created_at: nil, updated_at: nil, discarded_at: nil>

2.6.3 :009 > Google::Apis::TasksV1::Task.new
 => #<Google::Apis::TasksV1::Task:0x00007f973e2d8908> # no nil attributes by default?

标签: ruby-on-railsactiverecordgoogle-api

解决方案


在我看来,您需要的是缓存:

伪代码,请根据您的情况进行调整,但这样的事情会做:

ts = TaskService.new(user)
tasklist = Rails.cache.fetch("list-tasklists-#{user.id}", expires_in: 2.hours) do
  ts.service.list_tasklists
end

然后,您可以编写一个与 API 挂钩的缓存失效器,并可能编写一个缓存热重载器,因此您的用户缓存始终存在。

编辑:
我知道这不是你所要求的,但它可能是一个解决方案,看看你的用例。


推荐阅读