How could I display the raw file content as done in GitHub when displaying the file after clicking a "view raw" link?
E.g. I wanted to diplay *.html file's source but rails takes html in params[:format] and renders in its own way.
How could I achieve this?
Here's how I got this to work, though I am not exactly sure how you would want to use this in your application. Consider this a proof of concept that hopefully helps you achieve your goal.
Let's say you want to render the raw contents of the index action for your products controller if someone requests the "text" format:
def index
#products = Product.all
#raw = render_to_string('products/index.html', :content_type => 'text/html')
respond_to do |format|
format.html
format.text do
render :text => #raw, :content_type => 'text/plain'
end
end
end
This obviously isn't ideal since you're stuffing the "raw" version of the view in a variable even if someone requests the normal html format, but putting it in the format.text block screws up the content type for the partials inside index.html.erb. Again, this is just a proof of concept I came up with.
At any rate, now when you hit:
/products.txt
You will get the raw HTML of the page. And if you hit:
/products
It will render the normal, interpreted HTML in the browser.
Related
I want to store pages in the database that are dynamically added/edited/etc. Along with the page title and content I also supply which layout to use and a controller name and view name in order to support the instantiation of models which the view (e.g. text field in the pages table) will use.
I'm having trouble rendering the text from the database and having the layout still be used.
class AboutController < BaseController
def index
#model_data = ...
render_dynamic_page("about", "index")
end
end
class BaseController < ApplicationController
layout "public"
def render_dynamic_page(controller_name, action_name)
page = Page.where("`controller_name` = :controller_name AND `action_name` = :action_name", { :controller_name => controller_name, :action_name => action_name }).first
render :layout => page.layout_name, :text => page.content
end
end
I'm using :text here and I've also tried :inline but both seem to not render the content within the layout.
How can I accomplish this?
Normally if you want to allow users to edit the html pages in a rails application, and store the pages in a DB, the standard way is to use the template language called liquid.
It allows you to define dynamic content, ideal for CMS systems in rails, I think its better you have a look first.
following are some important links
liquid home page
rails cast about liquid
git hub page
and there are lots of resources in SO itself. :)
I was so close - I just had to switch the order of the parameters to the render method:
render :inline => page.content, :layout => (page.layout_name || "public")
I also added a default layout to use public in case a page.layout_name was not specified in the database. The other thing that's worth mentioning is the difference between :text and :inline - only :inline seems to actually "process" the content as if it were an ERB whereas the :text option just literally outputs the raw text.
Note : I ended up creating an ERB for each page using ERB.new(page.content), caching the list of dynamic ERBs and then pulling the pre-rendered ERB from the cache and displaying it using:
render :inline => the_cached_erb.result(binding), :layout => (page.layout_name || "public")
There is still some weird behavior going on but I think it will work in the end.
Just FYI and for greater tools variety you may want to check out Mercury editor:
http://jejacks0n.github.io/mercury/
https://github.com/jejacks0n/mercury
http://railscasts.com/episodes/296-mercury-editor
In my rails application I've created a business daily report. There is some non-trivial logic for showing it (all kind of customizable parameters that are used for filtering in the model, a controller that calls that model and some non-trivial view for it, for example, some of the columns are row-spanning over several rows).
Now I wish to send this report nightly (with fixed parameters), in addition to the user ability to generate a customize report in my web site. Of course, I wish not to re-write/duplicate my work, including the view.
My question is how can I call the controller action from my mailer so that it will be as if the page was requested by a user (without sending a get request as a browser, which I wish to avoid, of course)?
In answer to your question is if you are generating some sort of pdf report then go with using the wicke_pdf gem does exactly that generates pdfs. To send a report on a nightly basis the best thing for this is to implement some sort of cron job that runs at a particular time which you can do using the whenever gem. You can do something like:
schedule.rb
every :day, :at => '12:00am'
runner User.send_report
end
With this at hand you can see that you call the send_report method sits inside the User model class as shown below:
User.rb
class User < ActiveRecord::Base
def self.send_report
ReportMailer.report_pdf(#user).deliver
end
end
Inside send_report we call the mailer being ReportMailer which is the name of the class for our mailer and the method being report_pdf and pass in the user. BUT remember this is an example I have here I am not sure the exact specified information you want in a report.
Mailer
class ReportMailer< ActionMailer::Base
default :from => DEFAULT_FROM
def report_pdf(user)
#user = user
mail(:subject => "Overtime", :to => user.email) do |format|
format.text # renders report.text.erb for body of email
format.pdf do
attachments["report.pdf"] = WickedPdf.new.pdf_from_string(
render_to_string(:pdf => "report",:template => 'report/index.pdf.erb',
:layouts => "pdf.html"))
end
end
end
end
Inside the mailer there are a variety of things going on but the most important part is inside the format.pdf block that uses a variety of wicked_pdf methods (this is assuming that you are using wicked_pdf btw. Inside the block you create a new WickedPDF pdf object and render it to a string. Then provide it with the name of the report, the template and the layout. It is important that you create a template. This usually will where the report will be displaying from. The file type is a .pdf.erb this means that when this view or report is generated in the view the embedded ruby tags are being parsed in and the output is going to be a pdf format.
UserController
def report
#user = User.scoped
if params[:format] == 'pdf'
#Do some stuff here
User.send_report(#users)
end
respond_to do |format|
format.html
format.pdf do
render :pdf => "#{Date.today.strftime('%B')} Report",
:header => {:html => {:template => 'layouts/pdf.html.erb'}}
end
end
end
The key thing you asked that I picked up on.
how can I call the controller action from my mailer
In the controller simply collate a scope of Users, then check the format is a pdf, providing it is do some stuff. Then it will run the method send_report which I earlier highlighted in the user model class (Btw in your words this is the controller calling the model). Then inside the respond block for this there is a format.pdf so that you can generate the pdf. Once again note that you need a template for the core design of the pdf, which is similar to how rails generates an application.html.erb in the layouts. However here we have a pdf.html.erb defined. So that this can be called anywhere again in your application should you want to generate another pdf in your application somewhere else.
Think I've provided a substantial amount of information to set you off in the right direction.
I have a lot of data in a model that needs many forms to edit. What I've done is create a page that takes options like ?id=something&otheroption=something else and renders the correct edit form based on those inputs. Now, I am trying to create the actual edit page. The plan is for the user to select the "id" and "otheroption" from a drop down, and then an AJAX call will update a DIV with the correct form.
What I need to to is put this into a partial in someway where I can send an AJAX request to, have rails process the options, render the partial, and return the AJAX request. How do I do that with JQuery?
What I do is create a controller action with a js response that then renders a partial. As an example:
HTML
<div id="div_id"></div>
Controller
def ajax_responder
#data = query
respond_to do |format|
format.js
end
end
JS partial
jQuery("#div_id").html("<%= escape_javascript(render "html_partial") %>");
HTML Partial
whatever your html partial with data would be
This may suck mightily... I am open to feedback.
I want the the table to be displayed in pdf format .
we are using
format.html
format.json{render json: #user}
etc for generating html ,json format
Similarly
I want to render the page as pdf .
so what steps are there if it is possible in rails???
Step one:
register PDF type for use in respond_to blocks
# config/mime_types.rb
Mime::Type.register "application/pdf", :pdf
Step two:
in your controller respond to PDF format request
respond_to do |format|
format.html
format.json{render json: #user}
format.pdf do
# ...
# here your PDF generating code
# ...
send_data(your_generated_pdf, filename: 'your_filename.pdf', type: 'application/pdf')
end
end
For generating PDF you can use pdfkit with wkthmltopdf, Prawn and some other. Refer to the respective documentations on their usage.
Starting from Rails 5:
Step three:
add gem 'responders' as Rails 5 changelog says: "Remove respond_to/respond_with placeholder methods, this functionality has been extracted to the responders gem"
Another thing is Prawn.
It seems more robust and support complex situations. So you may choose this to work with something sophisticated. Get the https://prawnpdf.org/manual.pdf here.
The API docs: https://prawnpdf.org/api-docs/2.3.0/
Thanks Glenn for pointing it out.
I think this might help [ https://github.com/mileszs/wicked_pdf ]
You will always be able to use like format.pdf as long as your route supports .:format part. So just use that to capture the request for pdf. Then render the pdf using wicked_pdf.
The basic usage is showing there as below
def controller_action
... ... ...
... ... ...
format.pdf do
render :pdf => "file_name"
end
end
Here is another article might help to understand the usage.
Finally its done with prawn and prawn-rails. Here are the details.
To make my system ready
# Add this to your Gemfile
gem 'prawn'
gem 'prawn_rails'
# run
bundle install
I hit the url http://localhost:3000/regions i.e. to hit the index of RegionsController and it shows the page as pdf format.
I have a Region Model with a single attribute name. Has two entries in regions table.
[
#<Region id: 1, name: "Region 1", ... >,
#<Region id: 2, name: "Region 2", ... >
]
My Controller Method:
def index
#regions = Region.all # Should return two region objects :)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #regions }
format.pdf # <---------- This will handle the pdf response
end
end
I have created a view file in views/regions/index.pdf.prawn. Anyway the view file name format is :action.pdf.prawn and the view file is containing
prawn_document() do |pdf|
#regions.each {|r| pdf.text r.name}
end
This will just output the name of Regions.
Thats it. You have your page in pdf format. Now just play with all other options provided by Prawn and Prawn-Rails. You can find some here - http://prawn-rails-demo.heroku.com/
Just thinking to write a series of blogs guiding how to use different pdf generation tool with rails 3.
Let me know if it solves your problem.
If you need to use templates, you can always use the combine_pdf gem by itself (it has minor editing capabilities, such as tables and text boxes) or together with any of the aforementioned solutions, such as Prawn.
I'm in the process of creating a simple API for my application. I have create the controllers and did all the processing. However, the view is being returned.
How can I return a JSON document to the user instead of the view?
Also, if there's an error, should I also return a JSON document or... ?
Thanks!
Add this to your controller
respond_to :html, :json
(remove html if you only want json-api).
In your actions you can then simply use a respond_with call, like:
respond_with(#posts = Post.all)
It will render JSON-object if format is JSON, and it will render your html-view if html is requested. If your routes are created as standard resources, simply adding .json suffix to the url will give you the JSON-result, ie. if the route is specified as:
resources :posts