views:

23

answers:

2

Hi. Here's what I'm trying to do.

when the user clicks new note.. I want the user to be taken to a page when they can start typing a note, and save it to the server all with AJAX..

Problem is, every time the page saves, it's making a new note.

This leads me to believe that when Rails gets the DEF NEW controller, some how I need rails to first make a NEW NOTE record and then redirect to the edit controller of that new note, where the user can create/edit the note all with AJAX.

Thoughts? Thanks.

+2  A: 

I had the same problem once, creating the note first is probably a good idea.

Another way would be to send the user to the new action. When the first save occurs you send the new object back as a JSON object, and replace the form's action with the update url for that record as well as setting the form's method to put.

This way you don't end up with empty records in the database (with your use-case, you might want exactly that, so a User can continue a note later.)

Just my two cents.

Ok a way of implementing this could look like this:

Form

<%= form_for resource, 
             :remote => true, 
             :html => { 'id' => 'autosave' }, 
             :url => resources_path(:format => :json) do |f| %>
  ...
<% end %>

Application JS

var $form = $('#autosave');

// bind to the first success event from the form
$form.one('ajax:success', function(data, status, xhr) {
  // data contains our json object (your note as json)
  // now we update the form
  $form.attr('action', '/notes/' + data.id);
  $form.attr('method', 'put');
  $form.attr('data-method', 'put');
});

Controller

class ExampleController
  ...

  def create
    #
    # respond with the json object if format = json,
    # see the form above I'm passing the format with :url parameter in form_for
    #
    respond_with(resource) do |format|
      format.json { render :json => resource }
    end
  end
end
Max Schulze
@max, thanks that was the idea mentioned above. Any tips on actually implementing this? That's where I'm stuck.
AnApprentice
I've updated my post above, but monocle's solution might be a bit simpler.
Max Schulze
+1  A: 

If you really want use to use #new to create a note and save it, then you can simply do

def new
  @note = Note.create # instead of Note.new
end

Rails will then display this note just like the #edit action, so the note id will be in a hidden field. Then when you send the Ajax calls, you'll be calling #edit. If you want to preserve the behavior of #new for when javascript is turned off, then you might want to create a different action.

def new
  @note = Note.new
end

def new_js
  @note = Note.create
end

When you load the page that has the link to new_note, include some javascript that changes the link to new_js_note. So when JS is off, you get the standard #new form. When JS is on, you get a form that is basically editing a preexisting blank note.

monocle
nice that's a great idea. Thank you... trying that now.
AnApprentice
Question, how do I include new_js in my routes, if this controller note belongs to projects?
AnApprentice
Hm.. Don't use nested routes much. Maybe-- resources :projects { resources :notes { member { post :new_js } } }
monocle
hmm using Rails 3. Not able to figure it out yet. hmmm
AnApprentice
alright I just posted a question on the issue. Thanks
AnApprentice