Reputation: 2445
I am writing a Ruby on Rails application with a controller called "pages_controller" that is responsible for displaying pages to users. There are 3 different types of pages that can be displayed, and different things have to happen on the back end in each case, so I decided to break the functionality out into 3 methods within the controller. When the user requests a page, the "show" method is called, which figures out whether the page: 1. Belongs to the user 2. Belongs to another user, and can be viewed by the user requesting it 3. Belongs to another user, and cannot be viewed by the user requesting it (unauthorized)
The appropriate method is then called from there to display the page. The code looks something like this:
def show
if (something)
showMine
elsif (something else)
showAnother
else
showUnauthorized
end
end
def showUnauthorized
respond_to do |format|
format.html # showUnauthorized.html.erb
end
end
def showMine
respond_to do |format|
format.html # showMine.html.erb
end
end
def showAnother
respond_to do |format|
format.html # showAnother.html.erb
end
end
I am getting a template missing error because rails wants to render a view when "show" is called, but I do not want any views to be rendered when "show" is called. I simply want "show" to call the correct method from there, and the corresponding view for that method (showMine, showAnother, or showUnauthorized) to be rendered. How can I do this? Or am I going about this the wrong way entirely?
Upvotes: 4
Views: 2447
Reputation: 1578
I basically agree with Samy's comment, but here's some background:
The method that tells Rails what view to use is render
. If there's no call to that method in your show
method, Rails assumes you have a view called show.xxx.xxx
, e.g. show.html.erb
, that is supposed to be rendered. Note that it doesn't assume template will be prefixed with show
because that's the name of the method. It assumes it will be show
because that's the name of the action. The name of the action is passed to the controller as part of the request; it's not simply derived from the name of whatever method has a respond_to
block in it.
All the respond_to
blocks do is specify different view templates based on the MIME type of the request, but since you never call render
, all of those extra methods are still trying to call the show
view (show.html.erb
in every case), because you never told Rails to render
any other view, and the action name is show
.
So, instead of the respond_to blocks, just call render [some_view]
in each of your other methods.
This might not be the clearest answer, but I'd suggest also reading the following:
http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to/
It describes what respond_to
does, in particular how it keys off the action name to determine what view to render.
Upvotes: 2
Reputation: 10769
You need to declare these new actions that you have created in the routes file, as they don't belong to the RESTful routes.
I sugest to keep only the show action in your controller and create the IFs in the show view using the render method to include the partials(_showMine.html.erb, showAnother.html.erb, showUnauthorized)
example:
show view:
if (something)
<%= render 'showMine' %>
elsif (something else)
<%= render 'showAnother' %>
else
<%= render 'showUnauthorized' %>
end
I hope it helps...
Upvotes: 3