Jan 17, 2014

Accessing Rails Api From C++ [Part 1: Get Request]

blogpost author photo
Michał Gutowski
blogpost cover image
During my work I have encountered a need to communicate between an application written in Ruby on Rails and a C++ desktop application (written using QT framework). While creating the communication code I ran into several problems and solving them took me a lot of time. That’s why I want to show some tricks and save your time :) Instead of creating one big blog post I’ve decided to divide it into parts. In the first part I’ll cover the basic GET requests.

Let’s start with a little theory

GET requests are used to retrieve information from the server. If data is â€just there” the server should return it, and if it needs to be processed before being shown then it will be evaluated. You can find a more formal definition here

Let’s do this, then

I will only show parts of code here, but the entire applications’ source is available on github. * C++ apllication code from here * Rails app from there

Once you have everything set up, compile the C++ app and run rails server.
Put http://localhost:3000/entries/1 in the line edit, push the Send request button and yup, you have just run your very first GET request. You should see something similar to this.

Lets take a closer look at the code

QNetworkAccessManager * manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this,  SLOT(replyFinished(QNetworkReply*)));

QNetworkAccessManager is a class designed to send network requests and receive replies. Callingmanager->get(QNetworkRequest(QUrl(ui->urlLineEdit->text()))); will start the get request for URL taken from the line edit. When the reply arrives QNetworkAccessManager emits a finished signal, which in my example is connected to the replyFinished slot. Let’s take closer look at this slot, then.

void MainWindow::replyFinished(QNetworkReply * reply)
    ui->debugTextBrowser->append(tr("got reply"));
    QVariant statusCodeV =
    ui->debugTextBrowser->append("Status code: " + QString::number(statusCodeV.value<int>()));
    // Or the target URL if it was a redirect:
    QVariant redirectionTargetUrl =
    // see CS001432 on how to handle this
    if (reply->error() == QNetworkReply::NoError)
        QByteArray bytes = reply->readAll();
        QString string(bytes);
        //handle errors

As you can see we got a reply in the form of a QByteArray, which can be easily transformed to QString using it’s constructor. Please mind that this code does not take take care of connection errors, but when used for production it should. You can inform the user that something went wrong by giving them detailed info taken from reply->error(). Take a closer look at reply errors here. Note that when the slot is triggered it gains ownership of the reply object so the slot is responsible for deleting the reply. We shouldn’t delete it directly by calling delete reply and instead we should usedeleteLater. We can take more details on the reply itself by calling reply->attribute<T>(QNetworkRequest::Attribute code). For example we can obtain status code by calling statusCodeV.value<int>(), just note that it’s a template method so you should provide the type of returned data. For the full list of QNetworkReply’s attributes look at Attribute-enum .


This concludes the rundown on basic GET requests in c++. In the next post I will show how to prepare JSON in a RoR application, how to download it using GET request and how to parse it to extract data. Thanks for reading!