Oleksandr Verhun
Oleksandr Verhun

Reputation: 854

Using Ajax with rails update_attributes

I have a problem using ajax with rails method update_attributes. In js.coffee file I'm sending an ajax to compute a controller method.This ajax is simple and looks like this:

            $.ajax({
                url: 'tasks/update_data',
                type: 'POST',
                data: { swap: $.cookie("swap") }
            });

What I'm trying to do is save row swaps after refreshing page. And this is what my controller method supposed to do.When I debug this method, this is what happens: if I swap once everything works fine; when I swap twice and output values to console, its outputs something like this third<=>second, second<=> first,but it must do third<=>second, third<=>first. So I think it's some trouble with mechanics of how db is updating and I don't understand why it works in such way.Between that, in all times, when update_attributes is called, it returns true, so no fail updates of db. This is how controller method looks like:

def update_data

      ids = params[:swap].split('&')
      puts ids
      puts "--------------------------------------------------"
      row1 = Task.where( id: ids[0] ).first
      row2 = Task.where( id: ids[1] ).first

      puts "first: " + row1.name 
      puts "second: " + row2.name 

      temp_hash1 = { name: row1.name, status: row1.status, project_id: row1.project_id, dead_line: row1.dead_line }
      temp_hash2 = { name: row2.name, status: row2.status, project_id: row2.project_id, dead_line: row2.dead_line }

      k = row1.update_attributes( temp_hash2 )
      puts "first: " + row1.name
      puts k

      m =row2.update_attributes( temp_hash1 )
      puts "second: " + row2.name
      puts m  

      render nothing: true

  end

Cookie value: $.cookie( "swap", $.cookie("swap") + row_id + "&" + prev_row_id, { path: '/' } ). Thanks for answering.

Upvotes: 0

Views: 901

Answers (1)

Richard Peck
Richard Peck

Reputation: 76774

MVC

Your controller could be a lot better:

#app/controllers/tasks_controller.rb
class TasksController < ApplicationController
   def update_data
      ids = params[:swap].split('&')

      row1 = Task.find ids.first
      row2 = Task.find ids.last

      row1.update row2
      row2.update row1
   end
end

As a rule of thumb, never include direct output (puts) in your controller. Rails is MVC - meaning all the "output" should be placed into your views. Whilst you render "nothing", you should really translate this into some sort of response for your view / controller

--

Ajax

When you call ajax requests, it's just going to be the same as if you call a "normal" request. You still need to handle them in the same way, even if you don't want to have a response come through

What I mean by this is that if you want to receive success or error callbacks, you'll want to do something like the following:

#app/controllers/tasks_controller.rb
class TasksController < ApplicationController
   def update_data
       ...
       @message = "Success"
       respond_to do |format|
          format.js #-> app/views/tasks/update_data.js.erb
       end
   end
end

#app/views/tasks/update_data.js.erb
alert("<%=j @message %>");

--

Fix

In order to fix your issue, I would recommend taking a step back & considering what you're trying to achieve. You mention you're trying to swap row positions - why don't you just create a position attribute in your Task model?

This would allow you to do the following:

#app/controllers/tasks_controller.rb
class TasksController < ApplicationController
   def update_data
      ids = params[:swap].split('&')

      @row1 = Task.find ids.first
      @row2 = Task.find ids.last

      @row1.update_attributes(position: @row2.position)
      @row2.update_attributes(position: @row1.position)

      #response here
   end
end

The reason I write this is because your application needs to be object orientated - meaning that each record needs to be stored independent to any other.

The reason this is important is because you're currently trying to manipulate the objects themselves - "swapping" them in the literal sense. This is nonsensical & inefficient - you'd be much better suited to just changing the "position" of the respective objects - allowing you to just change the objects as required

In regards to your issue about the second call - you'll need to update your $.cookie("swap") value in order to make it work correctly

Upvotes: 2

Related Questions