Rails working with API

♀尐吖头ヾ 提交于 2019-12-04 16:43:14

I do not use httparty gem when working with APIs instead i use typhoeus gem which allow making parallel http requests and therefore enable concurrency but i believe the example below will also work if you use httparty. I am going to use a simple example to show how i work with APIs. Let's say you are trying to communicate with a JSON api service to fetch a list of products.

The url of the service endpoint is http://path/to/products.json

in your application, you can have a products_controller.rb with an index action that looks like this:

class ProductsController < ApplicationController
  def index
   # make a http request to the api to fetch the products in json format
    hydra = Typhoeus::Hydra.hydra
    get_products = Typhoeus::Request.new('http://path/to/products.json')
    get_products.on_complete do |response|
      products = MultipleProducts.from_json(response.body)
      @products = products.products
    end
    hydra.queue get_products
    hydra.run
  end
end

Let's say that the http request to http://path/to/products.json returns the following json

{"products" [{"id": 1,
  "name": "First product",
  "description": "Description",
  "price": "25.99"}, {"id": 2,
  "name": "Second product",
  "description": "Description",
  "price": "5.99"}]

This json can be wrapped in a class with a name like, multiple_products.rb Which looks like this:

class MultipleProducts
  attr_reader :products 
  def initialize(attributes)
    @products = attributes[:products]
  end
  def self.from_json(json_string)
    parsed = JSON.parse(json_string)
    products = parsed['products'].map do |product|
      Product.new(product)
    end
    new(products: products)
  end
end

You can then use ActiveModel to create a product model like this:

class Product
  include ActiveModel::Serializers::JSON
  include ActiveModel::Validations
  ATTRIBUTES =  [:id, :name, :description, :price]
  attr_accessor *ATTRIBUTES
  validates_presence_of :id, :name, :price

  def initialize(attributes = {})
    self.attributes = attributes
  end

  def attributes
    ATTRIBUTES.inject(ActiveSupport::HashWithIndifferentAccess.new) do |result, key|
      result[key] = read_attribute_for_validation(key)
      result
    end
  end

 def attributes= (attrs)
   attrs.each_pair {|k, v| send("#{k}=", v)}
 end

 def read_attribute_for_validation(key)
   send(key)
 end
end

In your app/views/products/index.html, you can have:

<h1>Products Listing</h1>
 <ul>
   <% @products.each do |product| %>
     <li>Name: <%= product.name %> Price: <%= product.price %> </li>
   <% end %>
 </ul>

This will list all the products fetched from the api. This is just but a simple example and there is much more involved when working with APIs. I would recommend you read Service-Oriented Design with Ruby and Rails for more details.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!