[Bug] !nil returns false for partial instance variable in specific conditions


#1

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 -

  identity is <%= identity.inspect %>
  !identity is <%= (!identity).inspect %>

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

#2

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).

On Dec 7, 3:13 pm, Frederick C. removed_email_address@domain.invalid


#3

On Dec 7, 5:35 am, Vikrant removed_email_address@domain.invalid wrote:

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
http://github.com/rails/rails/commit/acbf2b74aa3001fb6064bba96cd0033495774357

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


#4

On 7 Dec 2008, at 17:19, Vikrant wrote:

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

It took me 4+ hours to figure out what went wrong and where (I’m not
complaining though).