I have a Rails controller which provides both HTML and PDF responses, and thus I have view.pdf.haml and view.html.haml files. These are either identical or extremely close to identical.
How can I have Rails use a single view for multiple formats?
You can specify what format to render with :formats option:
# Both will render view.html.haml
respond_to do |format|
format.html { render :view }
format.pdf { render :view, formats: :html }
end
https://guides.rubyonrails.org/layouts_and_rendering.html#the-formats-option
Do you mean have the same action serve up different resource types - i.e. both a web page and a PDF? If I understand the problem, you can use the respond_to method.
def show
#object = Object.find params[:id]
respond_to do |format|
format.html
format.pdf { ..code to render the pdf.. }
end
end
That ..code to render the pdf.. is the tricky part. There are PDF gems that support inline rendering, but you may end up using send_data or similar to set a file name, disposition, etc and deliver the PDF document to the end user.
Related
If I have the following code, Rails is setup to automatically look in the views folder and find photos/feed.js.erb. But what I want to do is to tell it to run users/feed.js.erb instead.
PhotosController
def feed
#title = "Favorites"
#user_feed_items = current_user.favorites.order('created_at desc').paginate(page: params[:page], per_page: 15)
respond_to do |format|
format.html {
render 'users/feed' }
format.js
end
end
Rails: Render a .js.erb from another controller?
format.js { render :file => "/users/feed.js.erb"}
render accepts the full path (relative to app/views) of the template to render. So, you can just enter users/feed
render "users/feed"
Rails knows that this view belongs to a different controller because of the embedded slash character in the string. If you want to be explicit, you can use the :template option.
render template: "users/feed"
http://guides.rubyonrails.org/layouts_and_rendering.html#using-render
I have problem collection of pdfs file and save it to file. I create this for show action so when I clink the link it generate pdf and store them in public folder:
def show
add_breadcrumb "Inovice details"
respond_to do |format|
format.html
format.pdf do
render :pdf => "file_name", :save_to_file => Rails.root.join('public', "Invoice no. #{#invoice.format_id}.pdf")
end
format.csv {send_data Invoice.where(id: #invoice.id).to_csv,
filename: "Invoice no. #{#invoice.format_id}.csv"}
end
end
Now I want to create the same functionality but for collection of objects. For examples I have 10 invoices and I want for all of them generate pdf and save it to public folder. I was trying something like that:
def index
#invoices = #company.invoices
respond_to do |format|
format.html
format.js
format.csv { send_data #invoices.to_csv }
format.pdf do
#invoices.each do |invoice|
render :pdf => "file_name", :save_to_file => Rails.root.join('public', "Invoice no. #{invoice.format_id}.pdf")
end
end
end
authorize #invoices
end
But it didnt work. I have no ideas how to solve this problem. I will be grateful for every help.
You can not send multiple PDF's in the same request.
I think a best solution is generate the PDF's in a background job ( https://github.com/mileszs/wicked_pdf/wiki/Background-PDF-creation-via-delayed_job-gem ) and present an HTML page with links to all you PDF's.
If that doesn't work for you, you can merge all the content in a big PDF file.
I have seen some people using code like this
respond_to do |format|
format.html
format.js
end
What is the purpose of this if we have template.html and template.js. Either can be rendered without specifying respond_to
Your snippet doesn't do anything special, but the formatting options allow you to provide additional custom behavior if it is necessary.
For example, if you want to render your #products as a JSON:
respond_to do |format|
format.html
format.js { render :json => #products }
end
This is just one of the many things you can do with the format blocks. For more information, see Ruby on Rails Guides: Layouts and Rendering
The format options can take a block so that you can do some custom rendering such as rendering a file or :head response. Have a look at some of the examples here
If you don't specify different behavior for the different formats there is no reason to use respond_to. If you have templates they will automatically be picked up by rails. The respond_to method is useful if you need different behavior per format:
respond_to do |format|
format.html { render :edit }
format.json { render :json => '{}' }
end
I'm a newcomer to Rails, and have been following the tutorial on the rails webpage.
Using the scaffold instruction to create a "post" model, I found that the new action in the controller has a special directive for XML format:
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #post }
end
end
I can't see the reasoning for supporting an XML request when creating a new post. Browsing to /posts/new.xml returns nothing. What is the purpose of this?
The reasoning for it behind the new action is simply to provide a xml client with the default data (or something else if you want).
The format directive is being used by all routes, and you don't need to support a format unless you want to.
The above code could might as well have looked like:
respond_to do |format|
format.html # renders new.html.erb
format.xml { render :xml => {:message => "XML is not supported"} }
format.json { render :text => #post.to_jsonĀ }
format.js # renders new.js.erb
end
Also, this is not limited to the new action, but is available in all your actions. The format to use is either taken from the url (if the route is set up to use it), or from the HTTP-Accept header that the browser sends.
This is probably more a design or usage question but the main issue is using the Prawn plugin with Rails 2.3.4 and accessing the resulting PDF object to render it to a file.
The scenario is basically;
a controller with the respond_to block setup
a view with code for rendering the text, graphics etc to PDF
It looks like:
From Customer Controller
def show
#customer = Customer.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #customer }
format.pdf { render :layout => false }
end
From Customer View
pdf.text "Hello World"
pdf.text "Customer is #{#customer.name}"
This works fine, producing a PDF file in response to /customers/1.pdf, as expected with a PDF file being generated.
One of the other requirements is to render the pdf to a file and store a copy on the server. Prawn provides the method:
pdf.render_file {path_tofile}
So now if I include this in the View code I can of course save the file on the server. But I'd like to manage this in the controller, as it's related to logic, not view per se.
The first attempt was :
def show
#customer = Customer.find(params[:id])
#pdf = Prawn::Document.new()
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #customer }
format.pdf { render :layout => false }
pdf.render_file {path_to_file}
end
From Customer View
pdf.text "Hello World"
pdf.text "Customer is #{#customer.name}"
PROBLEM
The problem with this attempt is that the PDF is not rendered. I suspected the Controller instance variable is clashing with the Prawnto Plugin pdf variable. But even changing the PDF variable didn't work.
Any suggestions ?
This is how I use prawn in my rails app: http://yob.id.au/2009/05/30/prawn-and-x-accel-redirect.html - it doesn't use prawnto at all.
You can ignore the X-Accel-Redirect stuff unless you use nginx.
Alternatively, another one of the prawn core devs has put together this guide: http://wiki.github.com/sandal/prawn/using-prawn-in-rails