Introducing acts_as_api

As you may have noticed we are happily developing here at flinc using Ruby on Rails.

Rails makes it very easy to respond to clients in different formats like HTML, XML or JSON.

But only if you want to send the complete XML or JSON representation of a record.

If you want to exclude special fields or add some additional ones to the response it can get messy.

When we thought about a solution for this problem we had these requirements:

  • It should allow API responses with XML and JSON.
  • Keep it DRY. We didn’t want to create a template or builder for every response format.
  • Use the default XML, JSON renderers of the Rails application. (In case we want to exchange the renderer engines we will do this consistently for the complete app.)
  • Do it the Rails way. 🙂

The library acts_as_api is our approach to solve this problem in Rails 3 (at the moment it doesn’t support earlier versions).

Let’s do it:

When you installed the gem and added the dependency to the Gemfile of your Rails project your ActiveRecord models and your controllers are enriched with a couple new methods.

Prepare the models

This example assumes that you have a model called User. The User has probably a lot of attributes (password, email, created_at and so on) but you only want to expose first_name and last_name.

Now the model knows that it can „act as api“ and you determined the attributes you want to render. That was easy right?

Prepare the controller

Your controllers knows a new method too: render_for_api. Just replace the old render with it if you want to render XML or JSON. You can pass any parameter you would also pass to the render method.

That’s it!

Now no matter how many attributes your User model has, your API response will only render the attributes specified in api_accessible. An XML response would look like this:

And JSON like that:

But wait! There’s more…

Besides excluding attributes you can also easily include virtual attributes. Let’s say you want to combine the first_name and last_name attributes into a new one called full_name.

Just create a method in the model and make it accessible for the API:

And the result will look like this:

You also can rename the nodes/fields in the response by simply passing a hash instead of a symbol:

Now the first_name attribute is rendered as a node/field called but_call_me:

And there is even more…

acts_as_api offers you even more options to customize XML/JSON requests the way you want. For example you can…

  • Include attributes and all other kinds of methods of your model
  • Include child associations (if they also act_as_api this will be considered)
  • Call methods of a parent association
  • Rename attributes, methods, associations
  • Create your own hierarchies

Take a look at the readme on github or our example Rails app to see what is possible.

Yep, it’s open source!

The acts_as_api gem is hosted at rubygems.org so you should be able to install it using ruby gems:

The code is hosted at github and we also provide an example application to play around with.

The app uses SQLite as database so you can just clone it and start messing around. 😉

To dive into the single methods you can take a look at the documentation.

If you face any problems, bugs or you just want to help us enhancing the code please let us know in the comments or create an issue on github.

Let us know what you’re thinking!

Autor: Christian BĂ€uerlein

7 Kommentare

  1. Pingback: Twitted by flowdi
  2. One minor idea for the api: I like the way authlogic handles its configuration. They accept the whole configuration in a block, this way it can’t get scattered in the model.

    In their example, it looks like this:
    acts_as_authentic do |c|
    c.my_config_option = my_value
    end # the configuration block is optional

    For your gem, this could become:
    acts_as_api do |api|
    api.accessor :first_name, :last_name
    api.writer :password
    api.reader :id
    end
    Names are based on standard ruby class-methods attr_(reader|writer|accessor).

    Good work!

    1. That’s a very nice idea.

      I will consider it the next time I overhaul the api. 🙂

  3. sorry, the form butchered my formatting. Think of it as beeing neatly indented with 2 spaces in the blocks 😀

  4. Good post and this fill someone in on helped me alot in my college assignement. Say thank you you on your information.

  5. Hello Christian,

    Great plugin. However I am having some trouble in generating the same output as to_json. I have a posts collection in @posts that I am trying to render as json. However, it would put it like

    [{„post“:“first_post’s_json“},{„post“:“second_post’s_json“}]

    The plugin generates the json as

    {„posts“:[{first_post’s_json}, {second_post’s_json}]

    How do I fix this?

    Thanks,
    Prateek

    1. Hi Prateek,

      at the moment your desired scheme is only possible if you wrap the desired into another hash (see the sub_node example on github https://github.com/fabrik42/acts_as_api)

      If you have further questions or feature requests please feel free to contact me, open a issue on github or fork my project.

      Best,
      Christian

Kommentarfunktion geschlossen.