Datasheet
Chapter 1: Building Resources
19
A couple of the tests also confirm that Rails redirects to the ingredient index listing, with a line like this:
assert_redirected_to ingredient_path(assigns(:ingredient))
This line no longer works because, now that ingredients are a nested resource, the pathnames are all
defined in terms of a parent recipe. Change that line every time it appears to this:
assert_redirected_to
recipe_ingredient_path(assigns(:recipe),
assigns(:ingredient))
This changes the name of the helper method, and adds the recipe object to the arguments. The assigns
method gives access to any instance attributes set in the controller action.
The Controller Object
Because you are going to be testing for it, you need to make sure that every controller method actually
does assign a
@recipe attribute. The best way to do that is with a before filter. The before_filter
method allows you to specify a block or method that is performed before every controller action gets
started. Add the following line to the beginning of the
IngredientController class in app/
controllers/ingredient_controller.rb
:
before_filter :find_recipe
This specifies that the find_recipe method needs to be run before each controller action. To define that
action, add the method to the end of the class as follows:
private
def find_recipe
@recipe = Recipe.find(params[:recipe_id])
end
It ’ s important that the method go after a private declaration; otherwise, a user could hit
/ingredients/find_recipe from their browser, and invoke the find_recipe method, which
would be undesirable. This mechanism ensures that every controller action will have a recipe defined,
and you no longer need to worry about consistency. Readability can be an issue with filters, though,
because it can sometimes be hard to track back into the filter method to see where attributes are defined.
It helps to make smaller controllers where the filters are simple and clear. You ’ ll see another common use
of filters in Chapter 3 , “ Adding Users. ”
Next, you need to clean up the redirections. Two actions in this controller redirect to the show action
using
redirect_to(@ingredient) . Change those as follows:
redirect_to([@recipe, @ingredient])
c01.indd 19c01.indd 19 1/30/08 4:02:26 PM1/30/08 4:02:26 PM