views:

69

answers:

2

Rails newbie here, trying to get a new controller working.

When I try to show ann existing instance, I get an undefined method error on a helper method. Code follows. Any idea why getRecipes would be undefined?!

Controller:

    def show
       id = params[:id]
       recipe_ids = ConcreteMenu.getRecipes(id)

       respond_to do |format|
          format.html
       end
  end

Model

require 'json/objects'

class ConcreteMenu < ActiveRecord::Base
  has_many :menu_recipes
  has_many :recipes, :through => :menu_recipes

  belongs_to :menu

  def self.getRecipes(id)
      recipes = MenuRecipe.find(:all, :conditions => {:concrete_menu_id => id}, :select => 'id')
   end
end
+1  A: 

As you have it defined there, it should be available. Is there a chance you have something else called ConcreteMenu defined, but in a different context?

To be sure you're calling the correct one, where there may be ambiguity, you can refer to the top-level class:

recipe_ids = ::ConcreteMenu.getRecipes(id)

The other way to check that the method is defined correctly via script/console:

ConcreteMenu.methods.grep(/getRecipe/)
# => ["getRecipes"]

This is presuming, of course, you're having trouble with the getRecipes method. There's a possibility you're mistaking how controller variables are passed to the view:

def show
   @id = params[:id]
   @recipe_ids = ConcreteMenu.getRecipes(@id)

   respond_to do |format|
      format.html
   end
end

Any instance variables defined (@...) will be available within the context of the view, but any local variables will no longer be defined as they are out of scope.

tadman
+2  A: 

It would help if you pasted the error text, because your explanation leaves a lot of possibilities for what could be wrong. BUT, there is an easier way to get what you want. The value of defining "has_many" relationships is that instead of calling a class method and passing the id of a concrete menu to get its associated recipes, you can just do this:

def show
  @concrete_menu = ConcreteMenu.find(params[:id], :include => :recipes)
end

Now you'll have the menu object, and @concrete_menu.recipes returns an array of recipes you need. This feature is already built in, no need to reinvent the wheel.

Also, I noticed you were attempting to collect id's in the controller instead of the objects themselves. This suggests that you're going back and actually retrieving the records in the view itself. This is less efficient, and more difficult to troubleshoot when things go wrong. My example above will do what you need in a better (and more rails-accepted) way.

Jaime Bellmyer