www.flickr.com
Michael Kovacs' photos More of Michael Kovacs' photos
Recommend Me Cable Car Software logo

Saturday, January 07, 2006

Rails realities part 4 (scope)

A short one here. I was working on a new action and view when during my POST I received the following exception:


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


The source of this error was this line:


if params[:commit] == 'Cancel'


Which confused me because params is the hash that's created by default containing all of the form elements I'm posting. A quick look over my code and I saw that I had created a local variable named 'params' in a branch of logic that doesn't even get executed on a POST. So my code looks similar to this:


def my_action

if request.get?
params = Hash.new
# do stuff
else
if params[:commit] == 'Cancel' # <-- NoMethodError on a nil object here
#do stuff
end
end
end


Renaming my local variable to something else fixed the problem so this means that despite never being executed the local variable declared 'params' is overriding the default created by rails. I'm still a newbie to ruby and rails but this doesn't seem correct to me as the 'else' clause above never executes the initialization of the new Hash. Perhaps some ruby expert out there can tell me why this is the case, or have I found a bug in rails?

Comments:
major, dude. if that were really the case, it's not a bug in rails, there's a bug in rubeee. maybe your rubeee version is 1.9 or something.
 
Well I'm using whatever ruby is in the locomotive rails distribution for rails 1.0 which I believe is 1.8.2. It does seem hard to believe that this could be broken like this. I'm going to come up with a test case to verify as the code I put in here is paraphrased but the logic flow is exactly the same. I'll post more if I find out how it's broken especially if I end up being incorrect :-)
 
params != @params

" if @params[:commit] == 'Cancel' "

makes your code work.
 
but I didn't defined params to be a class level instance variable just a local one within the scope of my action. I'll have to give your snippet a try and see if it works but I guess I don't understand how local and instance variables work if that snippet does work.
 
This is how it works: As Ruby parses a method definition it needs to determine what is a method call and what is local variables (as method calls to "self" and reads of local variables look exactly the same). The way it does this is that if it encounters an assignment to the symbol in the method scope it will assume that symbol is a local variable and not a method call. You can fix this by either using a different local variable name for "params", or use "self.params", or simply by assigning "params = self.params" in the beginning of the method.

Cheers,
Jon
 
Thanks Jon! That's very good to know and it makes sense now. I guess this is one of the side effects of having local variables look the same as method calls. Not sure how I feel about this but it's not exactly intuitive :-). I wonder if it's possible to create an error message for situations like this that is clearer about the problem. I suspect not though because it seems the reader of the code needs to understand the parsing rule you described above regardless.
 
Nice information on Ruby on Rails Online Training India
 
Congratulations on your article, it was very helpful and successful. 874811a90f33a85894f2fd1b1289a2e5
numara onay
website kurma
sms onay
 
Thank you for your explanation, very good content. e61d72265a2a008d0d601cfcb816b399
altın dedektörü
 

Thanks for you
pleas share more topics
you can visit my website from this url
شركة تصليح افران بالمدينة المنورة
صيانة جليم غاز بالمدينة

 
Good text Write good content success. Thank you
betpark
bonus veren siteler
slot siteleri
tipobet
mobil ödeme bahis
kibris bahis siteleri
kralbet
betmatik
 
hatay
kars
mardin
samsun
urfa
0GVJH
 
عوازل اسطح
كوله

 

Post a Comment





<< Home

This page is powered by Blogger. Isn't yours?