techquestion
techquestion

Reputation: 489

Rails how to save data upon creation with an external API?

In my app for bike_rental_shops, I'm making it possible for these shops to manage their bike rentals.

Context Bike rental companies also offer their bikes on website of external parties, therefore I'm connecting my Rails application with these external websites. I'm currently handling this in my controller when a user goes to the index page. Before loading the index page an API call is made to the external rental website and new bike rentals should be saved in the database.

Question How to save only new rentals and not all rentals linked to a certain external rental website?

Current consideration The only thing I can come up with is adding a database column with {external_website}_rental_id for a specific external website, so I can match them. However, this would mean that I need to add a seperate rental_id for every external rental website.

Code

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 output API

{
  "next": null,
  "previous": null,
  "results": [
    {
      "activation_requested": false,
      "id": 21664,
      "slug": "rental-test"
      #more information....
   }
}]

Upvotes: 1

Views: 1063

Answers (1)

PGill
PGill

Reputation: 3521

you can create 2 columns

provider_rental_id id returned in response JSON

provider name of provider, to which request was made

Then to only create new records

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, 
    ...

or if you are using rails 6 you can check upsert_all
Note: It does not instantiate any models nor does it trigger Active Record callbacks or validations.

Additionally try to move this into a background cronjob

Upvotes: 2

Related Questions