Question about variable assignments/scoping after render call

I’ve got a question about how variables are made available to templates. We have a test that looks something like this:

def test_variable_assigned
xhr :get, :do_stuff, :id => 1
assert_not_nil assigns(:thing)

end

And our app code looks like this:

class SuperClass < ActionController
def do_stuff
@parent_model = ParentModel.find(params[:id])
render :template => ‘superclass/do_stuff’
end
end

class SubClass < SuperClass
def do_stuff
super
@thing = @parent_model.thing
end
end

When we run our tests with the code above, it fails saying that assigns(:thing) is nil. If we redefine do_stuff in SubClass to look like:

def do_stuff
@thing = ParentModel.find(params[:id])
super
end

then the test will pass. Unfortunately, this requires an extra database query to find the parent model twice. Is there a way of telling the view to reload its member variables after render has been called, but still render whatever the chosen template is?

-dmg

David Goudreau wrote:

I've got a question about how variables are made available to templates. We have a test that looks something like this:

  def test_variable_assigned
    xhr :get, :do_stuff, :id => 1
    assert_not_nil assigns(:thing)
  end

And our app code looks like this:

class SuperClass < ActionController
  def do_stuff
    @parent_model = ParentModel.find(params[:id])
     render :template => 'superclass/do_stuff'
  end
end

class SubClass < SuperClass
   def do_stuff
      super
      @thing = @parent_model.thing
   end
end

When we run our tests with the code above, it fails saying that assigns(:thing) is nil. If we redefine do_stuff in SubClass to look like:

   def do_stuff
      @thing = ParentModel.find(params[:id])
      super
    end

then the test will pass. Unfortunately, this requires an extra database query to find the parent model twice. Is there a way of telling the view to reload its member variables after render has been called, but still render whatever the chosen template is?

Perhaps write either:

class SuperClass < ActionController
   def do_stuff(parent_model = nil)
     @parent_model = parent_model
     render :template => 'superclass/do_stuff'
   end
end

class SubClass < SuperClass
   def do_stuff
     parent_model = ParentModel.find(params[:id])
     @thing = parent_model.thing
     super(parent_model)
   end
end

or

class SuperClass < ActionController
   def do_stuff(obj = nil)
     @parent_model = ParentModel.find(params[:id])
     instance_variable_set('@'+obj, @parent_model.send(obj)) if obj
     render :template => 'superclass/do_stuff'
   end
end

class SubClass < SuperClass
   def do_stuff
     super('thing')
   end
end