Connecting to web services using Rails (HTTP requests)? - ruby-on-rails

I am using Ruby on Rails 3 and I am trying to implement APIs to retrieve account information from a web service. That is, I would like to connect to a web service that has the Account class and get information from the show action routed at the URI http://<site_name>/accounts/1.
At this time, in the web service accounts_controller.rb file I have:
class AccountsController < ApplicationController
def show
#account = Account.find(params[:id])
respond_to do |format|
format.html
format.js
format.json { render :json => #account.to_json }
end
end
end
Now I need some advice for connecting to the web service. In the client application, I should have a HTTP GET request, but here is my question: What is "the best" approach to connect to a web service making HTTP requests?
This code in the client application works:
url = URI.parse('http://<site_name>/accounts/1.json')
req = Net::HTTP::Get.new(url.path)
res = Net::HTTP.start(url.host, url.port) {|http|
http.request(req)
}
#output = JSON(res.body)["account"]
but, is the above code "the way" to implement APIs?
Is it advisable to use third-party plugins and gems?

Yes, since you're using RESTful routes, they are your basic API. You're also returning structured JSON data easily consumable by an application.
There are other ways to implement a web services API (e.g. SOAP), but this is a good and proper way.
Since it's a web services API, connecting to the correct URL and parsing the response is the way to go on the client side. Though if you need to access many different resources it might be a good idea to create a flexible way of building the request URL.

If you don't need low-level tweak-ability offered by Net::HTTP, instead take a look at using Open-URI, which comes with Ruby. It makes it easy to request a page and receive the body back. Open-URI doesn't have all the bells and whistles but for a lot of what I do it's plenty good.
A simple use looks like:
require 'open-uri'
body = open('http://www.example.com').read
The docs have many other examples.
These are other HTTP clients I like:
HTTPClient
Typhoeus
They are more tweakable and can handle multiple connections at once if that's what you need. For instance, Typhoeus has a suite of simplified calls, similar to Open-URI's. From the docs:
response = Typhoeus::Request.get("http://www.pauldix.net")
response = Typhoeus::Request.head("http://www.pauldix.net")
response = Typhoeus::Request.put("http://localhost:3000/posts/1", :body => "whoo, a body")
response = Typhoeus::Request.post("http://localhost:3000/posts", :params => {:title => "test post", :content => "this is my test"})
response = Typhoeus::Request.delete("http://localhost:3000/posts/1")
HTTPClient has similar shortened methods too.

I'd recommend using Rails' ActiveResource for most cases. Failing that, httparty.

I would use ActiveResource if you just need a simple way to pull in rest-based resources. It's already included in rails and pretty trivial to set up. You just specify a base url and resource name in your ActiveResource subclass and then you can CRUD rest-based resources with an interface similar to that of ActiveRecord.

rest-client is the most popular gem for easily connecting to RESTful web services

I think one of the best solutions out there is the Her gem. It encapsulates restful requests providing objects with active-record like behavior.

Related

How to connect 2 rails 5 apps together API (rails) and front-end (rails as well)

As i mentioned on the question title, I want to know the best approach to get this to work and i'll need and example ( very simple one as the follow: )
Let's say i have an API which has 1 controller and 1 action for example simplicity
root 'main#index'
and inside the index action i have
def index
#date = Data.today
end
Then i have another rails app which will work for front-end rendering
How can i pass this #date as JSON from the API to the other app to render it ?
Should i have same controller on the other app ?
How can i connect and send http request and receive response ?
Thanks in advance
For such a simple example, you can do something as simple as:
def index
#date = Date.today
respond_to do |format|
format.json #date
end
end
However, you're most likely going to want to deal with more complicated JSON responses, so before long you'll probably want to use something like the Jbuilder gem or ActiveModel Serializers (my preferred approach).
On the other end, your front-end will need to make an HTTP GET request. Lots of ways (and gems) to do this, but one common approach is just to use the built in Net::HTTP class.
require 'net/http'
url = URI.parse('http://backend.dev/main/index')
request = Net::HTTP::Get.new(url.to_s)
response = Net::HTTP.start(url.host, url.port) do |http|
http.request(request)
end
raise response.body.inspect
In your situation, a better approach might be to use the Active Resource gem. This gem allows you to create models that are backed by a REST API rather than a database. For example, if your API app provides basic Create-Read-Update-Destroy actions for a particular model (let's call it Widget) at the following URLs:
GET http://backend.dev/widget # listing of widgets
GET http://backend.dev/widget/1 # Read for widget id: 1
POST http://backend.dev/widget # Create new widget
UPDATE http://backend.dev/widget/1 # Update widget id: 1
DELETE http://backend.dev/widget/1 # Destroy widget id: 1
then in your front-end app you could declare an Active Resource like this:
class Widget < ActiveResource::Base
self.site = "http://backend.dev"
end
which will auto-magically access all of those methods in your API, and behave much like a regular Active Record model. That way, you basically design your front-end app like a "normal" rails app, but using ActiveResource-based models in place of ActiveRecord.
I would note, however, that a more common thing to do these days would be to build your API in Rails, and build your front-end with client-side Javascript, using something like JQuery or Angular to make requests from the API. I'm not sure what you're gaining by splitting API and front-end, where both of them are Rails apps - unless you've got a compelling reason, I'd just build one Rails app that handles both API and front-end, or build a Rails API + Angular (or similar) front-end.

Streaming API with Rails not able to get streamed data

I am trying to fetch data from Twitter Streaming API in my rails app and i have created my own module which gives me twitter Authorization Head. I am able to get authorized but i am not getting the response back... all i see is the request in pending state (i am guessing as its streaming and connection not being closed). What can i do to my below code so that i can start printing the response as i get from Streaming API ?
class MainController < ApplicationController
include Oauth::Keys
def show
#oauth_signature_string = Oauth::Signature.generate(signature_params)
#header = Oauth::HeaderString.create(header_params)
RestClient::Request.execute(method: :GET, url: 'https://stream.twitter.com/1.1/statuses/sample.json', :headers => {:Authorization => %Q(OAuth ****************************)} )
end
end
Because Twitter is "streaming" the data and not closing the connection, your RestClient request is not being ended and your show action is hanging there and not "finishing". So, rails can't continue and render the default main/show.html.erb page.
So, you might want to look into ActionController::Streaming class and see if you can rewrite you views and HTTP call to utilize it. Or, it would be much easier to use a non-streaming API edge.
Also, what you are doing seems to be a better fit for javascript. You might want to use Twitter's official Javascript api to do all authentications and status streams.

How to process soap data in rails app?

I wanna process soap data in my rails app, requirements is like this: 3rd party app connect to my app and post the soap data using http protocol, then in my controller, my app has to parse these soap data, store them and then send the result to the requestor using soap format. Now the problem is I do not know how to deal these in my controller. Which gem shoud I used? wash_out or sovan?? Could someone give a detail example? Thanks for helping.
I'm not a fan of using SOAP, but there are a lot of documentation on internet, like this
Basically you need to include the next code in your model
def initialize(zip)
client = Savon::Client.new("http://theserver.com?WSDL")
response = client.request :web, :info, body:{"foo" => foo}
if response.success?
#do code
end
end
This railscast haves a good explanation too.

How do I refactor an API call to use HTTParty?

I have a working API call to Twitter. Yay me! But the problem is is that I would much rather refactor it into HTTParty and then I can extend it later. There are an assortment of reasons as to why I am not using something like the twitter gem. They are mainly due to some limitations that need to be overcome for the application.
Here, I have a working piece of code that calls to Twitter:
class Twitter
def validate
consumer_key = OAuth::Consumer.new(
ENV['TWITTER_CONSUMER_KEY'],
ENV['TWITTER_CONSUMER_SECRET']
)
access_token = OAuth::Token.new(
ENV['TWITTER_ACCESS_TOKEN'],
ENV['TWITTER_ACCESS_SECRET']
)
baseurl = "https://api.twitter.com"
address = URI "#{baseurl}/1.1/account/verify_credentials.json"
http = Net::HTTP.new address.host, address.port
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
request = Net::HTTP::Get.new address.request_uri
request.oauth! http, consumer_key, access_token
http.start
response = http.request request
puts "The response status was #{response.code}"
end
end
It is dependent on only the oath gem.
Key Question: How would one wrap this into HTTParty to make it more modular?
You could just replace NET::HTTP with HTTParty to get the benefits of the latter, or you could go the extra mile and make your Twitter model include HTTParty so that it responds to an ActiveRecord-like interface while it abstracts that in the background is issuing all these API requests.
The decision really depends on your needs. Do you just need to issue a specific request to Twitter and display the results or you want to interact more heavily with Twitter and treat it as a model where you can create, retrieve, delete etc.
Regardless of your choice, I believe that the official readme has all the information you might need (it even has a great example with StackExchange!).

Access URL on another website from a model in rails

I want to access a URL of another website from one of my models, parse some information and send it back to my user. Is this possible?
For example, the user sends me an address through a POST, and I want to validate the information through a third party website (USPS or GMaps)
What methods would I use to create the request and parse the response?
This is not a redirect. I want to open a new request that is transparent from the client.
There are a lot of libraries to handle this such as:
HTTParty on http://github.com/jnunemaker/httparty
Curb on http://curb.rubyforge.org/
Patron on http://github.com/toland/patron
Example using Patron:
sess = Patron::Session.new
sess.timeout = 10
sess.base_url = "http://myserver.com:9900"
sess.headers['User-Agent'] = 'myapp/1.0'
resp = sess.get("/foo/bar")
if resp.status < 400
puts resp.body
end
Each solution has its own way of handling requests and parsing them as well as variations in their API. Look for what fits your needs the best.

Resources