Rails如何在使用外部API创建时保存数据?
Rails how to save data upon creation with an external API?
在我的 bike_rental_shops
应用程序中,我让这些商店可以管理他们的自行车租赁。
上下文
自行车租赁公司也在外部网站上提供他们的自行车,因此我将我的 Rails 应用程序与这些外部网站连接起来。当用户进入索引页面时,我目前正在我的控制器中处理这个问题。在加载索引页面之前,对外部租赁网站进行 API 调用,新的自行车租赁应保存在数据库中。
问题
如何只保存新的租赁而不是链接到某个外部租赁网站的所有租赁?
当前考虑
我唯一能想到的是为特定的外部网站添加一个带有 {external_website}_rental_id
的数据库列,这样我就可以匹配它们。但是,这意味着我需要为每个外部租赁网站添加一个单独的 rental_id。
代码
rentals_controller.rb
def index
shop = Shop.find(params[:id])
request_rental_api
@bikes = shop.bikes
end
private
def request_rental_api
# set variables
base_url = "https://www.rentalwebsite.com"
url = "/rest/api/rentals"
token = 'TOKEN'
# init connection object
connection = Faraday.new(:url => base_url) do |c|
c.use Faraday::Request::UrlEncoded
c.use Faraday::Response::Logger
c.use FaradayMiddleware::FollowRedirects
c.adapter Faraday::Adapter::NetHttp
end
# send request
response = connection.get url do |request|
request.headers["Authorization"] = token
request.headers["Accept"] = "application/json"
end
bookings = JSON.parse(response.body['results'])
# check if rental is unique, and if so save it.
# Rental.create(????)
end
JSON输出API
{
"next": null,
"previous": null,
"results": [
{
"activation_requested": false,
"id": 21664,
"slug": "rental-test"
#more information....
}
}]
您可以创建 2 列
provider_rental_id
响应返回的 id JSON
provider
向其发出请求的提供商的名称
然后只创建新记录
rental_ids = bookings['results'].map { |r| r['id'] }
return if rental_ids.none?
existing_rental_ids = Rental.where(provider_rental_id: rental_ids, provider: 'Name of Provider').pluck(:provider_rental_id)
new_rental_ids = rental_ids - existing_rental_ids
new_rental_ids.each do |rental_id|
Rental.create(
provider: 'Name of Provider',
provider_rental_id: rental_id,
...
或者如果您使用的是 rails 6,您可以检查 upsert_all
注意:它不会实例化任何模型,也不会触发 Active Record 回调或验证。
另外尝试将其移至后台 cronjob
在我的 bike_rental_shops
应用程序中,我让这些商店可以管理他们的自行车租赁。
上下文 自行车租赁公司也在外部网站上提供他们的自行车,因此我将我的 Rails 应用程序与这些外部网站连接起来。当用户进入索引页面时,我目前正在我的控制器中处理这个问题。在加载索引页面之前,对外部租赁网站进行 API 调用,新的自行车租赁应保存在数据库中。
问题 如何只保存新的租赁而不是链接到某个外部租赁网站的所有租赁?
当前考虑
我唯一能想到的是为特定的外部网站添加一个带有 {external_website}_rental_id
的数据库列,这样我就可以匹配它们。但是,这意味着我需要为每个外部租赁网站添加一个单独的 rental_id。
代码
rentals_controller.rb
def index
shop = Shop.find(params[:id])
request_rental_api
@bikes = shop.bikes
end
private
def request_rental_api
# set variables
base_url = "https://www.rentalwebsite.com"
url = "/rest/api/rentals"
token = 'TOKEN'
# init connection object
connection = Faraday.new(:url => base_url) do |c|
c.use Faraday::Request::UrlEncoded
c.use Faraday::Response::Logger
c.use FaradayMiddleware::FollowRedirects
c.adapter Faraday::Adapter::NetHttp
end
# send request
response = connection.get url do |request|
request.headers["Authorization"] = token
request.headers["Accept"] = "application/json"
end
bookings = JSON.parse(response.body['results'])
# check if rental is unique, and if so save it.
# Rental.create(????)
end
JSON输出API
{
"next": null,
"previous": null,
"results": [
{
"activation_requested": false,
"id": 21664,
"slug": "rental-test"
#more information....
}
}]
您可以创建 2 列
provider_rental_id
响应返回的 id JSON
provider
向其发出请求的提供商的名称
然后只创建新记录
rental_ids = bookings['results'].map { |r| r['id'] }
return if rental_ids.none?
existing_rental_ids = Rental.where(provider_rental_id: rental_ids, provider: 'Name of Provider').pluck(:provider_rental_id)
new_rental_ids = rental_ids - existing_rental_ids
new_rental_ids.each do |rental_id|
Rental.create(
provider: 'Name of Provider',
provider_rental_id: rental_id,
...
或者如果您使用的是 rails 6,您可以检查 upsert_all
注意:它不会实例化任何模型,也不会触发 Active Record 回调或验证。
另外尝试将其移至后台 cronjob