rack-backend-api

Added by mig-hub at September 21, 2011 15:25 Star_smallStar_smallStar_smallStar_small_grayStar_small_gray
GitHub stats:
Magnifier watcher(s)
Arrow_branch fork(s)
Wrench

About

The purpose of this Rack Middleware is to provide an API that interfaces with database actions in order to build a CMS.

Usage

HOW TO USE IT

BackendAPI is a Rack middleware that you have to put before your actual backend/CMS, and generally after an authentication middleware. And it takes care of everything involving interaction with your database.

In reality, it does not HAVE to be with the Backend but it makes sense and that way, both share the authentication middleware.

A rackup stack for your application might look like this:

map '/' do
  run Frontend
end

map '/admin' do
  use Rack::Auth::Basic, "your-realm" do |username, password|
    [username, password] == ['username', 'password']
  end
  use BackendAPI
  run Backend.new
end

Your backend receives every request that the Restful API doesn't recognise. The BackendAPI recognises requests following this scheme:

METHOD /Backend-path/model_class/ID

The ID is not always relevant. So if you have a model class called BlogPost and you want to get the form for the entry with ID 4:

GET /admin/blog_post/4

If you don't put an ID, it means you want the form for a brand new entry:

GET /admin/blog_post

Then if you need to delete the entry with ID 4:

DELETE /admin/blog_post/4

The API also understands a CamelCased class name:

DELETE /admin/BlogPost/4

This is my fave personally, but unfortunately it seems that windows servers are case insensitive. Which means that if you have one, you need to stick with the under_scored names.

To be honest, that is almost everything you need because the ORM adapter builds the forms and therefore use the right action and method for POST and PUT requests.

The problem sometimes with a Restful API is that in real life, in spite of the fact that not every requests are GET or POST it is sometimes forced. The href of a link is always a GET, and the method for a form is overridden if it is not GET or POST.

This is why Rack has a very handy middleware called MethodOverride. You don't have to use it because BackendAPI puts it on the stack for you. Basically when you have it, you can send the method you really wanted in the POSTed parameter called "_method", and the middleware override the method for you. This is how the adapter makes forms with PUT requests.

But unfortunately you can only use MethodOverride on POST requests, but you might want to have it on links.

Here is a concrete example:
You want to put in your CMS a link for deleting blog post. But a link is going to be a GET request. Of course you could use Ajax and anyway you probably will, but it is a good practice to make it possible without javascript. So your link could look like this:

<a href="/admin/blog_post/4?_method=DELETE"> X </a>

But it doesn't work because links are GET requests. Fortunately this is a common task so there is a method that makes DELETE buttons available as a form:

@blog_post.backend_delete_form("/admin/blog_post/4", { :destination => "/admin/list/blog_post" })

The :destination is where you go when the job is done. You also can change the option :submit_text which is what the button says. By default, the DELETE form button says "X".

The :destination option is also in the API as _destination. Use it in order to specify where to go when the entry is validated. Because before it is validated you'll get the form again with error messages.

Say we need a link for creating a blog post, and then when validated, we want to go back to the list page:

<a href="/admin/blog_post?_destination=%2Fadmin%2Flist%2Fblog_post"> Create new Blog Post </a>

Of course, the page /admin/list/blog_post is a page of your Backend/CMS. The form will be POSTed because there is no ID, which means it is a new entry. On that list page, you could have a list of your posts with an "Edit" link:

My Interesting Post Number 4 - <a href="/admin/blog_post/4?_destination=%2Fadmin%2Flist%2Fblog_post"> Edit </a>

You also have another option called fields which allows you to say which fields you want in that form. The purpose of that is mainly to be able to edit a single value at a time:

Title: My Super Blog - <a href="/admin/blog_post/4?fields[]=title&_destination=%2Fadmin%2Flist%2Fblog_post"> Edit </a>

This will make a link to a form for editing the title of that Blog Post. Please note that the option fields is an array.

Also don't forget to escape the URI like in the examples above. You can do that with Rack::Utils :

::Rack::Utils.escape "/admin/list/blog_post"

The option :submit_text is also available through the API as _submit_text. It says "SAVE" by default but you might want it to say "CREATE" and "UPDATE" in appropriate cases, like we did in the example.

Another thing to note is that you don't have to use a destination for when something is created or updated. If you do not use destination, the API will call the instance method Model#backend_show on the entry. By default it just says 'OK' but you can override the method in order to send whatever you want. This comes handy when you use ajax and want a representation of the entry once it's created.

More Info

For further details on how to use the middleware, please visit the github page of the project.

blog comments powered by Disqus