What is @controller instance variable?

In a book I'm reading the author tries to do the following from within
his controller test file:

class PagesControllerTest < ActionController::TestCase
  def test_create_link_in_index
    get :index
    assert_select "a[href=?]", url_for(:action => :new), :text => 'Neue
Seite'
  end
end

However the method 'url_for' is unknown within the class
PagesControllerTest, as it is defined in ActionController::Base.

To get around this he writes (although this is not the final solution):

assert_select "a[href=?]", @controller.url_for(:action => :new,
:only_path => true), :text => 'Neue Seite'

How is he able to reference a method defined in another class, simply by
prefixing the method call with '@controller'

Could someone explain what is '@controller' in this context?

I tried Googling it, but as Google ignores the '@' I couldn't get very
far.

Thanks in advance

it's an instance of the controller class that you're testing
(ActionController::TestCase sets one up for you)

Fred

Hi Jim,

'@controller' is an instance variable in ActionController::TestCase.
ActionController::TestCase sets up this variable to contain an
instance of the controller class you are testing (in this case,
PagesController).

In other words, ActionController::TestCase does something like this:

@controller = PagesController.new

which is why you're able to call PagesController methods on @controller.

(The '@' symbol before a variable in Ruby just means that it is an
instance variable, as opposed to an ordinary local variable.)

Chris

Hi,

Thanks for all of the replies.
That has really made things a lot clearer for me.

So, to summarize:

'url_for' is a method defined in ActionController::Base.

@controller is an instance variable initiated by
ActionController::TestCase containing a reference to my controller
(PagesController).

PagesController inherits from ApplicationController.

ApplicationController inherits from ActionController::Base.

Therefore, in ActionController::TestCase, by prepending a method call
with @controller, owing to the aforementioned class hierarchy, I can
access methods defined in ActionController::Base.

Would that be correct?

Thanks again for your help.

Hi,

Thanks for all of the replies.
That has really made things a lot clearer for me.

So, to summarize:

'url_for' is a method defined in ActionController::Base.

@controller is an instance variable initiated by
ActionController::TestCase containing a reference to my controller
(PagesController).

PagesController inherits from ApplicationController.

ApplicationController inherits from ActionController::Base.

Therefore, in ActionController::TestCase, by prepending a method call
with @controller, owing to the aforementioned class hierarchy, I can
access methods defined in ActionController::Base.

Some of the way you phrased that seems a bit awkward to me. It not
that @controller contains a reference to you controller - it is an
actual instance of it.
And 'prepending a method call' sounds like you think there is some
magic going on - there isn't - methods are always called on a certain
object (omitting the object means the method is called on self)

Fred

It not that @controller contains a reference to you controller -
it is an actual instance of it.

OK, I phrased that badly.

And 'prepending a method call' sounds like you think there is some
magic going on - there isn't - methods are always called on a certain
object (omitting the object means the method is called on self)

And that too :slight_smile:
Thanks for clearing that up.