6

I would like to send a javascript array of arrays to my ruby controller. I am a bit lost. My question is in the controller. Here is what I have so far:

(totalChanges is an array of arrays. JSON.stringify(totalChanges) might look like this:

[[4,2,"","15"],[4,3,"","12"],[4,4,"","14"]]

app/views/index.html.erb:

<div id="dataTable" class="dataTable" style="width: 680px;height: 300px; overflow: scroll"></div>
<button>Save!</button>
<script>
    var first = true;
    var totalChanges = new Array();
    $("#dataTable").handsontable({
         //...some code that generates appropriate array totalChanges
    });
    var data = //..some code
    $("#dataTable").handsontable("loadData", data);
    $(function() {
            $( "button").button();
            $( "button" ).click(function() { 
                    alert("clicked"); 
                    $.ajax({
                            type: "POST",
                            url: "/qtl_table/save",
                            data: {total_changes: JSON.stringify(totalChanges)},
                            success: function() { alert("Success!"); }
                    });
            });
    });

</script>

app/controllers/qtl_table_controller.rb:

def save
  //Adding some things suggested by answers:
  logger.debug "\n#{params[:total_changes].first}, #{params[:total_changes][1]}\n"
  ar = JSON.parse(params[:total_changes])
end

I end up with these errors:

NoMethodError (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.first):

EDIT: I also had contentType: "application/json", and Accepts: "application/json" and when I took those out everything worked out. Thanks guys :)

warpech
  • 6,293
  • 4
  • 35
  • 36
bdeonovic
  • 4,130
  • 7
  • 40
  • 70

3 Answers3

12

JSON.parse is your friend:

ar = JSON.parse(params[:total_changes])
#=> [[4, 2, "", "15"], [4, 3, "", "12"], [4, 4, "", "14"]]

Most likely you'll need to update your AJAX call to something like:

$.ajax({
  type: "POST",
  url: "/qtl_table/save",
  data: { total_changes: JSON.stringify(totalChanges) },
  success: function() { alert("Success!"); }
});

to give your array parameter total_changes name.

KL-7
  • 46,000
  • 9
  • 87
  • 74
  • Thanks, this looks great. I am also confused on what to render or how that works. How can I get the page to just reload index.html.erb after I do some logic in my controller – bdeonovic Jun 26 '12 at 15:58
  • After finishing all the work you can do `redirect_to :action => :index` that will redirect user to the `index` action that should have refreshed content by then. – KL-7 Jun 26 '12 at 16:05
  • I now have: NameError (uninitialized constant QtlTableController::JSON): app/controllers/qtl_table_controller.rb:26:in `save' – bdeonovic Jun 26 '12 at 16:09
  • Hm, maybe you're missing `require 'json'` at the top of your controller file. Or you can try [`ActiveSupport::JSON.decode`](http://apidock.com/rails/v3.2.1/ActiveSupport/JSON/decode/class) instead. – KL-7 Jun 26 '12 at 16:12
  • also I was missing gem 'json' in Gemfile – bdeonovic Jun 26 '12 at 21:14
4

In javascript assign a root node for the JSON data

data: {qtls: totalChanges}

Now in the controller:

params[:qtls] # contains the Ruby array
params[:qtls].first # [4,2,"","15"]
Harish Shetty
  • 64,083
  • 21
  • 152
  • 198
  • Is stringifying the whole data hash necessary? Don't remember and can't check at the moment. – KL-7 Jun 26 '12 at 16:03
  • @KL-7, no it is not(http://api.jquery.com/jQuery.post/). I just copied and pasted his code. – Harish Shetty Jun 26 '12 at 16:08
  • what do you guys recommend? I am just trying to tie bits and pieces that I am learning from around the wonderful internet – bdeonovic Jun 26 '12 at 16:11
  • @KandadaBoggu, will be the array automatically dumped and restored in the controller without `JSON.stringify` and `JSON.parse`? – KL-7 Jun 26 '12 at 16:13
  • As long as the user posts to .json extension the data will be converted automatically. – Harish Shetty Jun 26 '12 at 16:19
  • I get this method error when I do it like this with no JSON.stringify and assigning root node: NoMethodError (You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.first): – bdeonovic Jun 26 '12 at 16:26
1

The data being passed should be located somewhere in your params environment variable. It seems though that you don't know which environment variable it is in. If you know which one it is, that variable will holding the variable that you are passing, in your case the json string that is the array. Once you know how to access it, you can then update/create/save or what ever you need to do, and then do a redirect to your index:

redirect_to qtl_tables_path

Usually inspecting the params will show you how it is being passed if you don't know what the variable is called. When I want to know something like this and see everything that is being passed to the controller, I make it send it to a different controller action that has a view. In that view I will put something like:

<%= debug params %>

or

<%= inspect params %>

That way it prints out the params that are being passed, I can see where that variable is and how to access it in the params and then use it in the correct controller.

Does this make sense? The answers in this post should help you too:

Rails: How do I print the request parameters?

It has some nice examples of using your rails logger to print it as well.

I hope that is answer helps you out.

Community
  • 1
  • 1
de_an777
  • 1,137
  • 1
  • 14
  • 15