8.4. Working with Controllers

Routing is just the first part of the equation, with the second one being the actual code defined within controllers. If you are familiar with ASP.NET, this is conceptually similar to the Code Behind model, and a vital component of every Rails application. The final aim is to have separation of concerns and place just enough logic in the controller to orchestrate the application, while the heavy lifting is performed by the model layer and the presentation is delegated to the view.

8.4.1. Generating Controllers

In the examples presented so far, the controller was never created directly, but rather was generated as a consequence of running the scaffold generator. Controllers are contained within textual files so you could create a file in the right directory and define the code by hand. A more convenient and practical approach, though, is passing the controller argument to the generate script, as shown in the following example:

All controllers inherit from the ApplicationController class defined in application.rb. In Rails 2.3, this file is renamed as application_controller.rb to be more consistent with the naming convention of every other controller.

C:projects> rails chapter8
C:projects> cd chapter8
C:projectschapter8> ruby script/generate controller Account
    exists  app/controllers/
    exists  app/helpers/
    create  app/views/account
    exists  test/functional/
    create  app/controllers/account_controller.rb
    create  test/functional/account_controller_test.rb
    create  app/helpers/account_helper.rb

This generates the controller file (for example, account_controller.rb), a helper to define helper methods that are specific to this controller (for example, account_helper.rb), and a functional test case (for example, account_controller_test.rb).

Use apphelpersapplication_helper.rb to define helpers that can be reused by every controller in the application.

The generated controller will then be:

class AccountController < ApplicationController
end

NOTE

Notice that controllers defined in such a way are not RESTful by default. To make them so, you have to use methods like map.resources in routes.rb, as well as add the corresponding default seven actions. For this reason, when you need to create a RESTful controller, it is usually more convenient to rely on the scaffold generator that does this specific task for you.

The controller generator also accepts a list of actions/views:

C:projectschapter8> ruby script/generate controller BankAccount deposit withdraw
    exists  app/controllers/
    exists  app/helpers/
    create  app/views/bank_account
    create  test/functional/
    create  app/controllers/bank_account_controller.rb
    create  test/functional/bank_account_controller_test.rb

create  app/helpers/bank_account_helper.rb
    create  app/views/bank_account/deposit.html.erb
    create  app/views/bank_account/withdraw.html.erb

This generates the usual controller files as well as the default XHTML code for the views indicated in the given arguments. The generated controller will contain the corresponding actions:

class BankAccountController < ApplicationController
  def deposit
  end

  def withdraw
  end

end

Use ruby script/destroy controller ControllerName to destroy an existing controller and all the associated files that were generated for it.

You can use either CamelCase (like the class name) or snake_case (like the file name) strings to indicate the name of the controller that needs to be generated or destroyed.

8.4.2. Action Processing

Routing directs Rails as to which controller class should be instantiated and which method name (the action) should be invoked. But what happens if the method name is not there? To understand how things work, it is necessary to learn about the algorithm used by Rails for action processing.

Imagine that the incoming request requires the execution of the action deposit. The steps taken are straightforward. Rails will:

  1. Search for a public method deposit in the controller. If the method is found, this is executed.

  2. If the method cannot be found, Rails looks for a method_missing method within the controller. If this exists, it's executed. From within method_missing it's possible to access the action name because this is passed as a parameter.

  3. If method_missing is (fittingly) missing, Rails searches for a corresponding template. If the controller is AccountController and the action requested through a Web browser is deposit, the template desposit.html.erb is searched for in appviewsaccount.

  4. Finally, if none of the above could be found, an "Unknown action" exception appears.

These four steps have a few implications for the developer. The first step is usually the desired outcome, so it's important that your actions are defined as public methods (Ruby's default). If you define them as protected or private, these methods will be available from within the controller, but won't be accessible to the end user as actions.

If you need to hide a method that absolutely must be public, you can also use the method hide_action. Usually this is not necessary though and almost always symptomatic of code that could use some redesigning.

The method_missing method can be used to implement a metaprogramming trick to dynamically determine the code that will be executed for the incoming request:

def method_missing(method)

    #... code ...

end

This can be useful in very specific cases where there's a concrete need for such a feature, but be wary of abusing this option for sake of coolness.

Finally, the third step implies that you can define "static" pages by simply defining a template. The template will still take advantage of the layout defined for the controller at hand, and will still be able to use ERb, but in the controller there will be no corresponding action for it.

Many still find it useful to keep track of all the actions, by defining empty/stub actions in the controller for these templates, even if they are not strictly necessary. Searching Google for "Rails static pages" (without quotes) will lead to a series of articles and blog entries on the topic, and will give you a lot of insight about more elaborate approaches that are taken to serve static content in a highly dynamic Rails application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.217.254.118