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.