Tuesday, August 11, 2009

Rails: "comparison of Array with Array failed" error

Today I was trying to fix a rails app by sorting a certain list according to the alphabetical order. This list was stored in an array (let's call it value_array). And it was a pretty huge list.

I didn't know what kind of data was in this array. I only knew that the list would be in the following
value_array: {"Gamma"=>14, "Alpha"=>3, ..}
And the list will be displayed to the user as:
Gamma(14)
Alpha(3)
..
But I want this list to be in alphabetical order so that 'Alpha' would appear before 'Gamma' and so on..

I tried using the ruby array sort method.
value_array = value_array.sort { |x,y| x[0] <=> y[0] }
when I tried this on Scite ruby editor, it worked fine. But when tried on the app it failed with the error "comparison of Array with Array failed"

After about an hour of desperate struggle to find the solution, I stumbled upon this article: "Support for nil values in Enumerable.min or max"

ah.. the nil (or null if you like) object.. a common trouble creator. That is why we should always make sure are data is valid (not nil etc) i guess. So in my app, the huge list must have had some nil values. So I fixed it:
value_array = value_array.sort {|x,y| (  (y[0].nil? || x[0].nil?)  ?  0 :  (x[0] <=> y[0])  ) } 

.. all part of the long journey of learning i guess :)
Read More

Thursday, June 4, 2009

CSV creator for Ruby on Rails

It's been a long time since I wrote anything here. Everyday I think I will write later but it never happens. So I thought I must write something today.

Ok, so this topic does deviate from my last post which was about security. But I thought this might be useful to someone. When working with Ruby on Rails, if you ever needed to create CSV files this tip might be useful to you. If you are wondering what csv files are, they are just like excel spread sheets, where you can store data in tables. In fact you can open these files using excel and make changes to them.

Now, this is not a discovery that I have made. The CSV creator is something I found on the web. The easiest way that I know to create CSV files is to use the FasterCSV gem . You can install it easily. Then to use it, the best 'csv baker' I found was Scott Becker's this article: http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails

It's really great, and you will be creating csv files to store records in no time. And to use this csv creator all you need to do is call you csv creator method that's inside your controller. For example if your instance method (in the controller) that generates CSV files is named 'export_to_csv', then put a link on you web page so the user can click it whenever they want to create a csv file.

example:
<%= link_to 'Export_to CSV', :action=>'export_to_csv' %>

From where does the 'export_to_csv' method get the records that need to be put in the csv file? That's easy too.

If you are retrieving records from a database, for example a 'Products' database, just store your sql conditions in a session variable.

example:
---------
selection_scope = ["product_name = ? AND product_brand = ?", 'mops', 'star_light']

@products = Product.find(:all,
:conditions=> selection_scope,
:order => 'product_name ASC')


session[:selection_scope] = selection_scope #storing selection scope in session varialbe
--------------

Then using the 'session[:selection_scope]' inside your 'export_to_csv' method, you can easily retrieve all the product records according to the last specified selection scope.

That's all good. But sometimes you need to let the user select what type of data they need to be sent into the csv file. For example for a selection of products the user may want 'product_name', 'product_expiry_date', 'warranty_period' etc., in their csv file. So you may want to let the user decide what data columns need to be included in the csv file. For that I have used a menu where the user ticks check-boxes for the field names they want to see in the csv file. But as you know with 'link_to' function, you cannot send the users selection back to the server.

For that purpose we need to use the 'link_to_remote' function. It actually generates an ajax call to the server. Then it submits the user's check-box selection back to our controller. Have a look at the following example -

-----
<%= link_to_remote( "Submit fields to CSV", :url =>{ :action => :export_to_csv},
:submit => 'checkboxes_form' ) %>
-----

'checkboxes_form' is my check-boxes set. I am submitting them to my csv creating instance method inside my controller which is 'export_to_csv'.

But there is a small problem. When you make such an ajax call, the user won't see any response like from the 'link_to' remote function. That means they wont get any file to download. There is a good fix for that and is very well described by Praveen Sinha on his blog: http://anaphoral.blogspot.com/2009/03/sendfile-or-senddata-in-linktoremote.html

And that's it!
I wrote this in a bit of a hurry so apologizes for any mistakes. I am new to ruby and rails and just a bit of a rails enthusiast. Hope someone finds this helpful. If you see any mistakes here, kindly let me know so I can correct them.

Cheers.
Read More

About Me

Popular Posts

Designed By Seo Blogger Templates