David Tuite
David Tuite

Reputation: 22663

Nested attributes in JavaScript fronted Rails applications

I find that the interactivity that a JavaScript single-page application provides makes it quite easy to build up complicated nested objects on the client side.

For example, in an application I'm writing, I have a Backbone destination and origin models, a route which connects them and then a bus which travels that route. All of this comes together quite naturally on the client side.

# Bus toJSON()
  { 
    seats: 45,
    route: {
      summary: "a route summary",
      origin: {
        latitude: 45.654634,
        longitude: 23.5355
      },
      destination: {
        latitude: 45.654634,
        longitude: 23.5355
      }
    }
  }

However, I find that when it comes time to persist my bus (the user is ready to save everything), the rails models accepts_nested_attributes_for method makes things quite ugly. I end up having to send data to the server which looks like

{ "bus_route_attributes_origin_attributes_latitude" => "45.654634" } 

in order to get ActiveRecord to play nicely.

How should I change my server side to allow me to deal in JSON more easily?

Upvotes: 0

Views: 234

Answers (1)

Christoph Eicke
Christoph Eicke

Reputation: 1144

Well, when you have already setup your models with accepts_nested_attributes, then when e.g. updating your model, you can simply do the following in your controller (I assume you already do something like this):

def update
  bus = Bus.find(params[:id]
  if bus.update_attributes(params[:bus])
    flash[:success] = "Success"
  else
    flash[:error] = "Error"
  end

  redirect_to :back
end

With this in place, Active Record will only update those parts of the model that have really changed, even if it's nested within other models.

This approach however expects the full bus object from the client. If you only want to update one single attribute, then you are stuck with the approach you have so far. I agree that this is ugly, but when you simply serialize your complete bus object and send it to the server every time something changes, then Rails figures out what changed for you.

Upvotes: 1

Related Questions