A few weeks ago, I wrote 9 Ways to Use Rails Metal. The third way to use Rails Metal was implementing a simple API.
Before I provide the code and an explanation, I’d like to cover a few things. First, this API only requires an API key. If you want an authentication token or some other identifier, look at Rails Metal Example #1: Authentication for some ideas of how to manage authentication for your API. Second, I didn’t filter any contents on the User model, so the password is passed back by the API. A simple delete call for the keys you want to omit from the hash returned by the find_by_sql call should clear up any data you don’t want to pass back.
Here’s the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # Allow the metal piece to run in isolation
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)
class ApiHandler
def self.call(env)
req = Rack::Request.new(env)
@params = req.params
if (env["PATH_INFO"] =~ (/^\/api\/(xml|json)\/user\//)) && ApiKey.find_by_key(@params["key"]) && env["REQUEST_METHOD"] == "POST"
format = env["PATH_INFO"].split("/")[2]
return [200, {"Content-Type" => "application/xml"}, [User.find_by_sql(["SELECT * FROM users WHERE id = ?", @params["id"]]).to_xml]] if format == "xml"
[200, {"Content-Type" => "application/json"}, [User.find_by_sql(["SELECT * FROM users WHERE id = ?", @params["id"]]).to_json]] if format == "json"
else
[404, {"Content-Type" => "text/html"}, ["Not Found"]]
end
end
end |
The code here is pretty simple. You check the path to make sure it matches the api path for XML or JSON, then find the record, convert it, and send it off to the user.
A few things to note are that the Rails methods to_json and to_xml are available in Rails Metal. I also had to explicitly return on the xml format because it isn’t the last execution and therefore isn’t returned.
API, JSON, MySQL, Rails Metal, tutorial, XML