Download Wiley Professional Ruby on Rails
Transcript
Chapter 1: Building Resources 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]) 19