Rails working with API

2019-04-14 14:52发布

I am beginner in working with API. I'm trying to work with the Forecast API. I don't want to use its official wrapper, because first I like to study and learn.

class Forecast
  include HTTParty

  base_uri "api.forecast.io/forecast/#{@api_key}/#{@latitude},#{@longitude}"

  def initialize(api_key,latitude,longitude)
     self.api_key = api_key
     self.latitude = latitude
     self.longitude = longitude
  end


end

Now what should be the next step after initialization. I've tried to understand using the httparty gem examples, but cant figure out what exactly to do.

Could you help me to fix it & point related resources with APIs?

1条回答
做个烂人
2楼-- · 2019-04-14 15:22

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.

查看更多
登录 后发表回答