# How do I make an API?

**URL:** <https://www.ruby-forum.com/t/how-do-i-make-an-api/147944>\
**Category:** Rails\
**Created:** [September 7, 2008, 12:09pm UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944 "2008-09-07T12:09:31Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Charles\_Ju](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/34f0e0/32.png) [@Charles\_Ju](https://www.ruby-forum.com/u/Charles_Ju)\
**Post date:** [September 7, 2008, 12:09pm UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944/1 "2008-09-07T12:09:31Z")

</div>

Hi!

I’m a new developer trying to get into Ruby on Rails. My team is  
developing an iPhone application that wants to call our Ruby on Rails  
web-end to store and retrieve data. I’ve looked on the web and in this  
forum but the only things I could find were dealing with scaffolding,  
which a) didn’t solve the problem clearly for me and b) we’re not  
using scaffolding.

So, I was wondering what would be the best way to create such an API,  
and how can we do it securely?

Thanks!

- Charles

---

<div class="post-metadata">

**Author:** ![Charles\_Ju](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/34f0e0/32.png) [@Charles\_Ju](https://www.ruby-forum.com/u/Charles_Ju)\
**Post date:** [September 7, 2008, 9:56pm UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944/2 "2008-09-07T21:56:55Z")

</div>

Unfortunately I don’t have a good recipe, but I’m trying to develop  
something similar (API for my Rails application) and here are my  
unpretentious results.  
I have made a standalone ruby script and include Rails configuration  
there:  
require File.dirname( **FILE** ) + ‘/…/config/environment’  
Thus I have access to all models and their connections.

I have mod\_rails + Ruby Enterprise installed, but this API script  
works as CGI and doesn’t use Ruby Enterprise gems, so you need to  
install the same list of gems for normal Ruby and Ruby Enterprise.  
Another way is to add a line in your Apache config:  
RailsSpawnMethod conservative  
But somebody claims that it’s too slow.  
Another tip is to check for the same ENV[‘RAILS\_ENV’] value for both  
Rails and API script, because Passenger overwrites it.

Currently I’m researching different approaches in optimizing speed of  
my application. I’m going to make the API script as a daemon, there  
are some great tools in Ruby for that. But I didn’t select any and  
cannot comment them.

A bit messy, sorry 🙂 Maybe this helps.  
Nevertheless it will be great to share good experience.

---

<div class="post-metadata">

**Author:** ![Charles\_Ju](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/34f0e0/32.png) [@Charles\_Ju](https://www.ruby-forum.com/u/Charles_Ju)\
**Post date:** [September 7, 2008, 10:07pm UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944/3 "2008-09-07T22:07:29Z")

</div>

On 7 Sep 2008, at 20:55, Konstantin [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Unfortunately I don’t have a good recipe, but I’m trying to develop  
> something similar (API for my Rails application) and here are my  
> unpretentious results.  
> I have made a standalone ruby script and include Rails configuration  
> there:  
> require File.dirname( **FILE** ) + ‘/…/config/environment’  
> Thus I have access to all models and their connections.

Why is your api not just some extra controllers and actions in your app?

Fred

---

<div class="post-metadata">

**Author:** ![Charles\_Ju](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/34f0e0/32.png) [@Charles\_Ju](https://www.ruby-forum.com/u/Charles_Ju)\
**Post date:** [September 7, 2008, 10:18pm UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944/4 "2008-09-07T22:18:39Z")

</div>

On 7 Sep 2008, at 21:14, Konstantin [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > Why is your api not just some extra controllers and actions in your  
> > app?
> 
> Will I be able to daemonize the script if it’s a controller in my  
> application?  
> I think no. This is why I have chosen this way - I need to make my API  
> script as a daemon.

Why would you need to? You’ve already got mongrel or apache or  
whatever sitting in front of it (unless you’re not doing this over http)

---

<div class="post-metadata">

**Author:** ![Charles\_Ju](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/34f0e0/32.png) [@Charles\_Ju](https://www.ruby-forum.com/u/Charles_Ju)\
**Post date:** [September 7, 2008, 10:15pm UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944/5 "2008-09-07T22:15:07Z")

</div>

> Why is your api not just some extra controllers and actions in your app?

Will I be able to daemonize the script if it’s a controller in my  
application?  
I think no. This is why I have chosen this way - I need to make my API  
script as a daemon.

Btw, eventmachine gem seems to fit my needs 🙂 I’m going to use it.  
If you have worked with it, all useful tips are welcome.

---

<div class="post-metadata">

**Author:** ![Charles\_Ju](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/34f0e0/32.png) [@Charles\_Ju](https://www.ruby-forum.com/u/Charles_Ju)\
**Post date:** [September 8, 2008, 9:36am UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944/6 "2008-09-08T09:36:43Z")

</div>

On Sep 8, 8:27 am, Konstantin [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Moreover, for API script I need a non-standard port (because some  
> clients work badly with 80 and 443 ports), but the whole Rails  
> application should work as normal.
> 
> Can this be done inside a regular Rails application? Will be thankful  
> for good tips 🙂

This could all be done inside a regular rails app and there’s very  
little reason to do otherwise (you might want to run your api off a  
dedicated cluster of mongrels but right now that would probably be  
premature optimisation). You claim to be worry about efficiency, but  
it sounds like you’ve already made it massively inefficient by writing  
it as a script that reloads the rails environment for each request.  
In terms of tips there aren’t really - just do it. You’ll have to  
fiddle around with your apache configs to get it served on a different  
port from the rest of your apps but that’s the only fiddly bit.

Fred

---

<div class="post-metadata">

**Author:** ![Charles\_Ju](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/34f0e0/32.png) [@Charles\_Ju](https://www.ruby-forum.com/u/Charles_Ju)\
**Post date:** [September 8, 2008, 10:51am UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944/7 "2008-09-08T10:51:18Z")

</div>

If you’ve set up your app with RESTful resources, you can access them  
using ActiveResource. Personally, for public APIs I’ve shied away  
from this method.

Instead, I create an apiV1 (or V2, or V3) controller, and make it  
accessible at [http://example.com/api/v1/{api\_method}.api](http://example.com/api/v1/%7Bapi_method%7D.api). This way,  
I’m able to easily work on new versions of the API without affecting  
the previous versions.

For testing the API during development, I use a little library I wrote  
called Bricklayer (available here:  
[http://github.com/heypanda/bricklayer/tree/master](http://github.com/heypanda/bricklayer/tree/master)  
).

The downside to this method is that you don’t (to my knowledge) have  
HTTP verb access restrictions at the routing level, so you’re  
responsible for checking the request type at the controller level. I  
usually drop in a before filter for api methods that should be POSTS  
which just checks if request.post? and handles inappropriate verbs  
accordingly.

If you’re worried about speed… one way I’ve solved this is by moving  
my API implementations to a separate Merb app that piggybacks my Rails  
models. The downside here is that you’re effectively managing two  
applications, which can be a pain both on the development and  
deployment side of things (though I haven’t had much issue yet). To  
make this work, you have to make sure your load balancer/reverse proxy  
is sending requests to the right application. You can either set up  
some rewrite rules to proxy based on the request, or deploy your app  
to something like [api.example.com](http://api.example.com) and set the Merb app up as a  
separate virtual host.

As far as “security” goes… depends on the app. For me, it’s always  
been as simple as having the client send along Basic HTTP  
Authentication credentials over SSL. So if, for your iPhone app, you  
want a user to be able to view his store inventory or something, you’d  
just have him enter his un/pw in the client, and authenticate in The  
Usual Way.

If, however, you want to prevent people from accessing the API by any  
other method than the iPhone app, I’m guessing you’ll want to do some  
kind of handshake procedure to ensure this… which is totally out of  
my realm. I’m guessing that whatever provisions you take could be  
undone with some patience and a decompiler (which is why I’m against  
embedding authentication information in the app itself).

M

---

<div class="post-metadata">

**Author:** ![Charles\_Ju](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/34f0e0/32.png) [@Charles\_Ju](https://www.ruby-forum.com/u/Charles_Ju)\
**Post date:** [September 8, 2008, 9:27am UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944/8 "2008-09-08T09:27:55Z")

</div>

> Why would you need to? You’ve already got mongrel or apache or  
> whatever sitting in front of it (unless you’re not doing this over http)

To say truly, it’s my first API script (and the first daemon script),  
and I have poor theoretical knowledge in this area. So I have tried to  
make something, but maybe in the wrong way.  
I just thought, that if I make a controller in Rails application, it  
will initialize many unnecessary actions and it may be very time  
consumable. In my script I use only limited number of Models, no  
templates, no controllers.  
Moreover, for API script I need a non-standard port (because some  
clients work badly with 80 and 443 ports), but the whole Rails  
application should work as normal.

Can this be done inside a regular Rails application? Will be thankful  
for good tips 🙂

---

<div class="post-metadata">

**Author:** ![Charles\_Ju](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/34f0e0/32.png) [@Charles\_Ju](https://www.ruby-forum.com/u/Charles_Ju)\
**Post date:** [September 8, 2008, 10:55am UTC](https://www.ruby-forum.com/t/how-do-i-make-an-api/147944/9 "2008-09-08T10:55:25Z")

</div>

I guess I kind of started writing my reply with “APIs in general” in  
mind, and shifted to “iPhone accessing the API”. Ignore my comment  
about ActiveResource. 😉
