I'm using RABL right now to generate JSON responses of an API in Rails, but I'm finding that while RABL is super handy for mapping models to responses, to create a consistent API I'm having to to duplicate that mapping logic in the update
and create
functions of my controller.
As a simple example, if I just want to change the attribute names in the response to a POST request, I can do this in RABL:
create.rabl
object @car
attributes car_id: :id, badly_named_legacy_column_that_means_color: :color
But if I want the client to be able to use these same "cleaned up" attributes in the JSON POST/PUT request itself (i.e. be able to send { "id": 1, "color": "red" }
instead of { "car_id": 1, "badly_named_legacy_column_that_means_color": "red" }
), I have to manually do this mapping again in the controller:
cars_controller.rb
def create
params[:car_id] = params.delete(:id)
params[:badly_named_legacy_column_that_means_color] = params.delete(:color)
@car = Car.create(params)
end
Now there are two places that I need to map car_id
to badly_named_legacy_column_that_means_color
. Not very DRY.
So far I haven't come across any way to handle this using RABL. Is there one that I'm missing? I also realize this might be outside the scope of RABL, which bills itself specifically as a templating system, so maybe is there another API builder that would allow me to do this? I love the idea of mapping messy database columns to a clean API but having to specify this mapping in both the view and the controller isn't very DRY. Any thoughts appreciated.
Update
The original answer is all about Ruby/Rails => JSON, the question is JSON => Ruby/Rails. This answer about associating columns should explain an approach:
Then you can just reference
new_column_name
in the RABL and Rails will handle the association on the create/update.You should be able to call
render
from thecreate
method and render any view. You could customize a response with acreate
specific template or reuse the genericshow
template. The trick is to re-use the object rabl template (app/views/car/car.rabl
in this case), for example:Where
app/views/cars/car.rabl
isand
app/views/cars/show.rabl
is