0

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.

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

6 Comments

I appreciate your answer.I was using "puts" just to see what's happening there. Thx for making this code look nicer, I think due to my inexperience, I still write not good code. Now about your fix: I don't understand, why you need to create instances of rows, maybe cause I come from system lang like C++, and there it's better to do local variables, because of memory or I don't understand something; you propose to create another column in db 'position' and then order by position, yep it's more efficient, but a little bit more complex then just update_attr, it makes sense.Then to sum up ->
Hey thanks for the comment! I guessed you were either native developer, or a Ruby dev. If you want to test in Rails you can use Rails.logger.info("your output here").
In the end I need to always put respond_to whenever I have ajax calls, create position in db, order by db, cookies values are easy to change, and put all render stuff in views, am I thinking in right direction?
The efficiency is in the DB call - native apps don't have such a big deal with this; but Rails apps' biggest Achilles Heal is the connection to the database. If you are pulling loads of DB data - you're going to get a big problem. That's why it's best to keep your app structured around objects
Yes, you're thinking in the right direction - you just need to ensure you're keeping everything succinct & efficient
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.