简体   繁体   English

Rails:如何将 gem 的类保存为我的数据库中的模型?

[英]Rails: how to save a gem's class as a model in my database?

I've been building a Google Tasks integration app and just switched to using the Google API Client ( gem 'google-api-client', '~> 0.34' )我一直在构建一个 Google Tasks 集成应用程序,刚刚切换到使用 Google API 客户端( gem 'google-api-client', '~> 0.34'

This gives me some classes that I'm really starting to like:这给了我一些我真正开始喜欢的课程:

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

These classes come with all the attributes I want and I'm thinking it would be nice to actually have these records in my database instead of what I'm doing now, which is HTTP requests with OAuth (using methods provided by the gem)这些类带有我想要的所有属性,我认为在我的数据库中实际拥有这些记录会很好,而不是我现在正在做的事情,即 OAuth 的 HTTP 请求(使用 gem 提供的方法)

With their gem integrated into a custom class, I can do things like:将他们的 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 ...

The items come back as structured classes!这些项目作为结构化类回来了! It's great!这很棒!

However, there's a good amount of latency with every call.但是,每次调用都有大量的延迟。

I'm running these commands in jobs, but I'm also thinking about saving these to my database (postgresql) and just comparing updated timestamps instead of pulling the information every single time I need it.我正在作业中运行这些命令,但我也在考虑将这些命令保存到我的数据库 (postgresql) 中,并且只是比较updated时间戳,而不是每次需要时都提取信息。

So, here's my question:所以,这是我的问题:

How can I take the class as-is and make it a model in my database?我怎样才能按原样使用该类并使其成为我数据库中的模型?

I want to be able to call Google::Apis::TasksV1::Task.create(tasklist_attrs) and other such model-type methods.我希望能够调用Google::Apis::TasksV1::Task.create(tasklist_attrs)和其他此类模型类型方法。

I have noticed that they don't respond exactly like my own classes (that inherit from ActiveRecord::Base ):我注意到它们的响应不像我自己的类(从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?

Seems to me like what you need here is caching:在我看来,您需要的是缓存:

Pseudo-code, please adjust to your case, but something like this would do:伪代码,请根据您的情况进行调整,但这样的事情会做:

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

You can then write a cache invalidator hooked to the API and possibly a cache hot reloader, so your user's cache is always there.然后,您可以编写一个连接到 API 的缓存失效器,可能还有一个缓存热重载器,这样您的用户的缓存总是在那里。

Edit:编辑:
I know this is not what you asked for, but it might be a solution, looking at your use case.我知道这不是你所要求的,但它可能是一个解决方案,看看你的用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM