I looking for the correct way to do the following.
I have a controller action 'show' that really only gets a database entry like:
def show
#photo = Photo.find params[:photo_id]
end
I have four different views that all use the same controller action. How would I implement this?
I have thought of two ways:
1) use a url parameter:
def show
#photo = Photo.find params[:photo_id]
case params[:view]
when 'view1'
render ...view1
when 'view2'
render ...view2
when 'view3'
render ...view3
when 'view4'
render ...view4
end
...or...
2) use respond_to
def show
#photo = Photo.find params[:photo_id]
respond_to |view|
view.one {render ...view1}
view.two {render ...view2}
view.three {render ...view3}
view.four {render ...view4}
end
end
...or... something totally different??
You tell me?
I would call the view the same as params[:view], like such:
def show
#photo = Photo.find params[:photo_id]
render params[:view].to_sym
end
As long as you have view files that cover all possible parameters, that will work.
Related
I am new to Rails.
I want to render layout(.html.erb file) as well as json data from action of controller.
How can I perform it?
Can I render both of them in single action? how?
This is exactly what respond_to is for. From the Rails Action Controller guide:
class UsersController < ApplicationController
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render xml: #users}
format.json { render json: #users}
end
end
end
I have a controller "UserController" that should respond to normal and ajax requests to http://localhost:3000/user/3.
When it is a normal request, I want to render my view. When it is an AJAX request, I want to return JSON.
The correct approach seems to be a respond_to do |format| block. Writing the JSON is easy, but how can I get it to respond to the HTML and simply render the view as usual?
def show
#user = User.find(params[:id])
respond_to do |format|
format.html {
render :show ????this seems unnecessary. Can it be eliminated???
}
format.json {
render json: #user
}
end
end
As per my knowledge its not necessary to "render show" in format.html it will automatically look for a respective action view for ex : show.html.erb for html request and show,js,erb for JS request.
so this will work
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
also, you can check the request is ajax or not by checking request.xhr? it returns true if request is a ajax one.
Yes, you can change it to
respond_to do |format|
format.html
format.json { render json: #user }
end
The best way to do this is just like Amitkumar Jha said, but if you need a simple and quick way to render your objects, you can also use this "shortcut":
def index
#users = User.all
respond_to :html, :json, :xml
end
Or make respond_to work for all the actions in the controller using respond_with :
class UserController < ApplicationController
respond_to :html, :json, :xml
def index
#users = User.all
respond_with(#users)
end
end
Starting from Rails 4.2 version you will need to use gem responder to be able to use respond_with.
If you need more control and want to be able to have a few actions that act differently, always use a full respond_to block. You can read more here.
In the Update action of Rails controllers usually there is code that looks like this:
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
else
render :edit
end
end
In the else case, this will render the edit template. But what if I wanted to use a respond_to, exactly the same way that I have in the edit action, as:
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
else
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #team }
end
end
end
So, if the Update fails, be sure you are returning a json or html depending on the requested format. Does that makes sense? If so, how would you avoid the error: "Render and/or redirect were called multiple times in this action"
Makes sense to me. The answer should be simple, just return after redirect_to.
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
return
else
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #team }
end
end
end
Not sure exactly how you're rendering multiple times, but assuming you are, a well-placed return should tell RAILS to stop processing any further renders after redirecting. If that's all true, it's likely that there's an after_filter interfering from somewhere.
A rails newbie here
I have 2 actions in my controller 1) index 2) refine_existing.
Both of them show the results in the same format.
How do I reuse the index.html.erb file?
When I try the following, it complains about refine_existing.erb not being present.
def refine_existing
...
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #results }
end
end
my index action looks like this
def index
#some logic to get #results
#set some session variables etc.
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #results }
end
end
Do I have to refactor my index view to contain partials that
a) make the headers
b) render #results
and reuse them?
Even though, both index.html.erb and refine_existing.html.erb will look exactly the same
Is there any way I can say in my refine_existing action to use index.erb view?
thanks in advance
By convention, if you don't specify a template name Rails looks for one matching the action. You can override this by calling render explicitly with the desired template name. The only wrinkle is that the path is relative to TEMPLATE_ROOT, which is normally app/views:
def refine_existing
...
respond_to do |format|
format.html { render :template => "<table_name>/index.html.erb" }
end
end
replacing table_name with the "tablized" form of the model. E.g. if your controller is PostsController, then posts. So your template would then live in app/views/posts/index.html.erb -- if you've customized paths somehow adjust as necessary.
I am experimenting with Rails and was wondering what's needed to allow/add support for JSON requests?
I have a vanilla installation of Rails 2.3.5 and the default scaffolding seem to provide support for HTML & XML requests but not JSON.
class EventsController < ApplicationController
# GET /events
# GET /events.xml
def index
#events = Event.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #events }
end
end
# GET /events/1
# GET /events/1.xml
def show
#event = Event.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #event }
end
end
...
I'm new to this but it would appear as though i would need to add a format line in each method along the lines of:
format.js { render :js => #event.json }
couldn't this be done automatically? perhaps there's a template somewhere i need to update...or a flag i can set? Or perhaps, and most likely, I've missed the boat entirely?!?
You do:
format.json {render :json=>#event}
That will render the default activerecord JSON for the model
The option of ease of use is that you can write a private method which takes the format object and an object to render and then, based on the format, renders different things. Example:
class MyController<ApplicationController
def show
#event=Event.find(params[:id])
respond_to do {|format| myRenderer(format,#event)}
end
...
private
def myRenderer(fmt,obj)
fmt.json {render :json=>obj}
fmt.html
fmt.xml {render :xml=>obj}
end