!nil returns false for partial instance variable in specific conditions.

Hi, If we call a partial with a name such that there also exists a instance variable with the same name (ex: @identity) in the controller then passing :object => nil to render() and calling (! identity).inspect in '_identity.html.erb' prints false while identity.inspect prints nil.

Here is a more specific description -

Let there be a controller named Check.

class CheckController < ApplicationController   def index     @identity = nil   end end

views/check/index.html.erb contains - <%= render :partial => 'identity', :object => nil %>

views/check/_identity.html.erb contains - <pre>   identity is <%= identity.inspect %>   !identity is <%= (!identity).inspect %> </pre>

calling localhost:3000/check/ prints -   identity is nil   !identity is false

NOTE: 1. There must be a controller instance variable with the same name as of partial. 2. I have been able to trace the problem down to between line 31 and 42 of file http://github.com/rails/rails/tree/dc0411fad78bfc92fe92dc88bbad726eb4d1a883/actionpack/lib/action_view/renderable_partial.rb

I'm using - Rails 2.2.2 Ruby 1.8.6 (2007-09-14 patchlevel 111) [i386-mswin32] RubyGems 1.3.1 Windows XP Home Ed. SP3

I've also uploaded a sample app folder at http://code.google.com/p/googol/source/browse/?r=95#svn/lab/learning/ruby-bug-on-!nil/app/controllers

- thanks

Hi, If we call a partial with a name such that there also exists a instance variable with the same name (ex: @identity) in the controller then passing :object => nil to render() and calling (! identity).inspect in '_identity.html.erb' prints false while identity.inspect prints nil.

The key here is Deprecated implicit local assignments when rendering partials · rails/rails@acbf2b7 · GitHub

What is being deprecated is render :partial => 'foo' automatically taking the value of @foo. The way that this is done is that the foo object in your partial is actually a tiny proxy object. If you try and do anything with that object it will just pass it on to the real object (and print a small deprecation notice - you should see these in your logs). Ruby being ruby, ==, inspect, class etc... can all be passed on to the target objects - they are just method calls after all. That is not true of ! though, which just flips nil/false to true and everything else to false and so you get the behaviour you demonstrate.

Fred

Yes, that might be the "reason" (though not technically strong enough to understand that proxy thing), but still I find it as a bug. It just breaks the common assumptions (assumption is perhaps wrong word, it breaks just how it must work). nil is after all "not true" (and so is ! nil). It took me 4+ hours to figure out what went wrong and where (I'm not complaining though).

Yes, that might be the "reason" (though not technically strong enough to understand that proxy thing), but still I find it as a bug. It just breaks the common assumptions (assumption is perhaps wrong word, it breaks just how it must work). nil is after all "not true" (and so is ! nil).

Short version is that the thing that looks like nil isn't actually nil What it's trying to tell you is that having @identity magically assigned to identity in partials called identity is deprecated

Fred