views:

531

answers:

3

Hi guys,

Quick question. Here is my code:

#routes
map.resources :customers, :has_many => [:addresses, :matchings]
map.connect ":controller/:action/:id"

#url path:
http://127.0.0.1:3000/customers/index/3

#customers controller
def index
  @customer = Customer.find(params[:id])
end

#customers view/index.html.erb
...
<%= @customer.name %>
...

Error: undefined method `name' for nil:NilClass.

Here's my reasoning. The parameter :id is coming from my url path (i.e. we're looking for customer #3 in the above path). @customer should find that array easily, then @customer.name should produce the name, but apparently @customer is blank. Why?

I assume the problem is that I'm not producing an array in my controller?

------UPDATE------

Hi Larry, thanks very much for the comments.

What I mean by 'index' is actually a home page that customers will hit when they log in to the site. (I also have separate logins for other users like employers and they go to their own index). I'm currently using 'list' as a list of customers and 'show' for one individual... is there a better way?

Second and MOST important: the logs are not giving me the answer to the fundamental problem, which is the inability to render the page.

Processing CustomersController#index (for 127.0.0.1 at 2010-05-16 16:56:19) [GET]
Parameters: {"action"=>"index", "id"=>"10", "controller"=>"customers"}
...
[4;36;1mCustomer Load (2.0ms)[0m   [0;1mSELECT * FROM "customers" WHERE ("customers"."id" = 10) [0m
[4;35;1mMatching Load (24.0ms)[0m   [0mSELECT * FROM "matchings" WHERE ("matchings".customer_id = 10) [0m
Completed in 153ms (View: 18, DB: 26) | 200 OK [http://127.0.0.1/customers/index/10]

------UPDATE #2 (last!) ------

I read through all of your comments and they have helped me not only make progress on my problem but also learn more about how the pieces fit together. For that, thanks everyone.

Alex is right - my routes are not lining up how they need to. I created a new action in my customer controller called Home. This is the customer's home base when they log in (it doesn't display info about one customer so it probably shouldn't be show, and it isn't a list so shouldn't be index or list).

Rake routes # ...gives me a list of routes that does NOT include home. Why?

Second, if the route displayed has, for example:

:action => "home"
/customers # (instead of what I need, '/customers/:id')

what do I have to do to change that route to accept an :id?

A: 

Look in your log to see the params being sent to your controller and action.

Also, you're not covering the case where an invalid id is given to your controller.

Eg, should be more like:

#customers controller
def index
  @customer = Customer.find(params[:id])
  flash[:error] = "Customer not found" and return unless @customer
end

Added:

Also note that in standard REST style, index should be a list of the customers. To view a specific customer, usually a "show" action is used.

Your query of Customer.find(params[:id]) will return one instance of the Customer model, or nil. If you want an array of Customers, it'd be more like Customer.find(:all)

Added --

Your log is showing that your action is being called correctly. Looks like your find statement isn't working. Use the console and make sure that Customer.find("10") gives you the result you're expecting.

Larry K
A: 

I think you're really making a request to the show action, not the index action. Put that code inside the show action.

Ryan Bigg
Hi Ryan,I also have the 'index' controller code in my 'show' action too. It's still not giving me the answer. A check of the logs does seem that it is properly looking within the index action.
sscirrus
@sscirrus: Is there anything more in your routes file? There may be something else interfering. I also strongly recommend using the show action for finding singular resources. If you're using it to find nested resources, then the customer id should be passed in as customer_id by using the nested routes helpers.
Ryan Bigg
A: 

Have a look at rake routes. The index action for a resource doesn't match an id. I suspect Rails doesn't even put the id into params for index action. Like Ryan said, you should be using the show action for that, and the URL for the show action will be http://localhost:3000/customers/3.

If you're going to use RESTful resources, you probably want to get rid of the default map.connect ":controller/:action/:id" route.

Alex - Aotea Studios
Even if the 'show' is not showing details on a customer at all? My home page for the customer actually displays information about a related model, Matching. THAT model needs to 'show' information to both customers (on their landing page) and employers (on their landing page). The information shown is different to each party, and each landing page shows info about the other. (Customer :has_many :employers, :through => :matchings). So should I do 'showcustomer' and 'showemployer' in the matching controller instead?
sscirrus
@sscirrus: if you *need* the show action to show user details on another page, then by all means use it for that. In that case you can introduce an extra action in the user controller called `matchings` and use that to show the landing page (the URL will be /customers/3/matchings). Alternatively, you could make matchings a nested resource to customers, which will route the same URL to the index action in the Matchings controller, but I'm not sure if that's possible given that you have a many-to-many relationship (i.e. Matchings has to be a nested resource in both customers and employers).
Alex - Aotea Studios