RoR HTML template to .docx - ruby-on-rails

I need to create a .docx file from a HTML template, so I used htmltoword gem.
Usage:
I added the gem (Gemfile):
gem 'htmltoword', '~> 0.5.1' #last version of the gem
I put a route (route.rb):
get 'preview' => 'foo#preview'
And in my bar.html.erb I have a link which target's that url:
<%= link_to '.docx', preview_path %>
Template (preview.docx.erb):
<h1>foobar</h1>
And in the controller (foos_controller.rb):
class FoosController < ApplicationController
respond_to :docx
#other code
def preview
respond_to do |format|
format.docx do
render docx: 'foobar', filename: 'preview.docx'
end
end
end
end
However, I'm getting an error:
ActionController::UnknownFormat
How to fix this error?
My config:
RoR v4.2.4
Ruby v2.2.3p173
Also, there is an open github issue for this/similar topic.
Update: as #kajalojha mentioned, respond_with / Class-Level respond_to has been removed to an individual gem, so I installed the responders gem, however, I get the same error.

Since respond_to has been removed from rails 4.2 to a individual gem i will recommend you to use formatter gem..
For further details you can look to the link given below.
Why is respond_with being removed from rails 4.2 into it's own gem?

Have you tried caracal-rails? You can find it here

I had to build this same functionality in an app earlier this year and also used the htmltoword gem.
# At the top of the controller:
respond_to :html, :js, :docx
def download
format.docx {
filename: "#{dynamically_generated_filename}",
word_template: 'name_of_my_word_template.docx')
}
end
I then have two "view" files that come into play. The first, is my method view file download.docx.haml. This file contains the following code:
%html
%head
%title Title
%body
%h1 A Cool Heading
%h2 A Cooler Heading
= render partial: 'name_of_my_word_template', locals: { local_var: #local_var }
From there, I have another file name_of_my_word_template.docx.haml that contains the meat of my Word file.
%h4 Header
%h5 Subheader
%div= local_var.method
%div Some other content
%div More content
%div Some footer content
When someone hits my_app.com/controller_name/download.docx, a Word file is generated and downloaded for them.
In order to ensure this happens, I have a route for the download method in my routes.rb file:
resources :model_name do
member do
get :download
end
end
Apologies for the long reply ... this has worked well for me and I hope helps you through this issue!

So, I figured it out. I added format: 'docx' to the route and it works now.
Note: as #kajalojha mentioned, respond_with / Class-Level respond_to has been removed to an individual gem, so I installed the responders gem.
Let's create a download logic.
Gemfile
gem 'responders'
gem 'htmltoword', '~> 0.5.1'
routes.rb
get 'download' => 'foos#download', format: 'docx' #added format
foos_controller.rb
class FoosController < ApplicationController
respond_to :docx
def download
#bar = "Lorem Ipsum"
respond_to do |format|
format.docx do
# docx - the docx template that you'll use
# filename - the name of the created docx file
render docx: 'download', filename: 'bar.docx'
end
end
end
end
download.docx.erb
<p><%= #bar %></p>
And I've added some link to trigger the download logic:
<%= link_to 'Download bar.docx', foo_download_path %>
Which will download the bar.docx file with "Lorem Ipsum" in it.

Related

How can I show a new file/webpage using ActiveJob in Rails 5?

I used to generate PDFs for my users by using the wicked_pdf gem and writing
something like the example code below:
class ThingsController < ApplicationController
def show
respond_to do |format|
format.html
format.pdf do
render pdf: "file_name" # Excluding ".pdf" extension.
end
end
end
end
I would then have a link on a page like <%= link_to report_pdf_path(#report), "Download PDF", target: "_blank" %> that would cause the PDF to show up in the user's browser as a new tab. This is the preferred behavior I would like, but it halts all requests until the PDF is completed for the user and some of these take quite some time to generate.
So I've since offloaded the generating of the PDF to ActiveJob which works nice, but I can't figure out how to have ActiveJob open the file in a new window yet. Currently, I have it writing to the server and then updating a partial that shows the files the user has requested. Below is an example of it.
class GeneratePdfJob < ApplicationJob
queue_as :default
def perform(*args)
params = args.first
generate_pdf_document(params)
end
def generate_pdf_document(params)
html = ApplicationController.new.render_to_string(
template: 'players/board_labels.pdf.erb',
locals: { player_ids: params[:player_ids] }
)
save_to_pdf(html, params[:pdf_title], params[:user_code])
end
def save_to_pdf(html, pdf_title, user_code)
pdf = WickedPdf.new.pdf_from_string(
html,
pdf: "#{pdf_title}",
layout: 'print',
encoding: 'utf-8'
)
pdf_name = "#{pdf_title}.pdf"
pdf_dir = Rails.root.join('public','uploads','reports',"#{user_code}")
pdf_path = Rails.root.join(pdf_dir,pdf_name)
# create the folder if it doesn't exist
FileUtils.mkdir_p(pdf_dir) unless File.directory?(pdf_dir)
# create a new file
File.open(pdf_path,'wb') do |file|
file.binmode
file << pdf.force_encoding("UTF-8")
end
end
end
So how can I make a method that would replace the save_to_pdf method and instead open the file in a new tab for the user? If this isn't possible could I open a tab when I initiate the ActiveJob that is a placeholder tab and then incorporate ActionCable to display the file some how after it's been generated for the user?

Rails respond with paperclip image.url multiple URLs

I'm building a simple rails application where users can upload some images. Now I need a simple controller that returns the image's URLs of related record which have the same id_attivita. To do so I create a function in the controller and enable it in the routes.rb file.
My question is about how to respond to the http request with the attribute value of image.url provided from paperclip?
def getattached
#photo_attivitum = PhotoAttivitum.where(id_attivita: params[:id_attivita])
respond_to do |format|
#photo_attivitum.each do |p|
format.html { render :json => p.image.url}
end
end
end
it works but it returns only the URLs of the first record not the other four record's URLs...
How can I do this?
Add the following gem to your Gemfile
gem 'active_model_serializers'
Then install it using bundle
bundle install
You can generate a serializer as follows
rails g serializer photo_attivitum
it will create Serializer class file in
# app/serializers/photo_attivitum_serializer.rb
class PhotoAttivitumSerializer < ActiveModel::Serializer
attributes :id, :image_url
def image_url
object.image.url
end
end
And in controller
def getattached
#photo_attivitum = PhotoAttivitum.where(id_attivita:
params[:id_attivita])
render json: #photo_attivitum
end
Not sure what u want to do? Show all image urls in json?
urls = #photo_attivitum.pluck('image_url')
format.html { render :json => urls}

XLS Format in Ruby on Rails Resources

In an RoR application, I would like the index resource to download an xls file.
Currently, I can get the file to download but it requires a link to a path I created like so
link_to subscribers_path(:format => :xls)
Ideally like the subscribers_path on it's own to add the format xls, and I don't want a view in html format with index.
My file structure
/subscribers
index.html.erb
index.xls.erb
and my controller code
def index
#subscribers = Subscriber.all
respond_to do |format|
format.html
format.xls #{send_data #subscribers.to_csv(col_sep: "/t")}
end
end
I tried to remove html to see if it would just default to another path but it says unknownformat error. I also tried to remove the index.html.erb file to see if would fallback to another format of the same name, but that didn't work.
Hopefully my objective is clear: How do I use the resource index path to link with xls instead of html format?
First, to clarify things: Yes, Rails does fully support XLS.
To use it just put the following line under config/initializers/mime_types.rb:
Mime::Type.register "application/xls", :xls
Then, as the author did it, change the format to xls and create an index.xls.erb
Now, to answer your question, there is a number of ways:
The first thing I thought of, was to just change the request format. In your controller:
class SubscriberController < ActionController::Base
before_filter :change_format
def index
#subscribers = Subscriber.all
respond_to do |format|
format.xls #{send_data #subscribers.to_csv(col_sep: "/t")}
end
end
private
def change_format
request.format = "xls"
end
end
There should also be a dozen other ways to do this, but I would prefer this one.

How do I add different types of GET routes that require parameters in Ruby on Rails

I have a list of users being displayed, you can click on "Show user" or "PDF" to see details of that user in HTML or as a PDF document. The show was automatically created with scaffolding, now I'm trying to add the option to view it as a PDF. The problem is adding a second GET option, if I pass the user along as a parameter, it is assumed to be a POST and I get an error that the POST route does not exist. I am not trying to update the user, just to show it in a different way, basically to add a second "show user" option.
How do I tell it that I want a GET, not a POST? Is there an easier way to do what I am trying to do? Thanks.
Please, create a controller like this:
class ClientsController < ApplicationController
# The user can request to receive this resource as HTML or PDF.
def show
#client = Client.find(params[:id])
respond_to do |format|
format.html
format.pdf { render pdf: generate_pdf(#client) }
end
end
end
Please, update route.rb file, action name with post and get, like below :
match 'action_name', to: 'controller#action', via: 'post'
match 'action_name', to: 'controller#action', via: 'get'
More info please read this link : "http://guides.rubyonrails.org/routing.html"
you haven't posted any code or details, so I am guessing you want something like this:
routes
resources :users
controller
class UsersController < ActionController::Base
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.pdf # handle the pdf response
end
end
end
view file in views/users/show.pdf.prawn
prawn_document() do |pdf|
#user.each {|r| pdf.text r.id} # will print user id of the user
end
The way above example will work is, if something visits the following URLs, they will get html file:
localhost:3000/users/1 #html is the default format in rails
localhost:3000/users/1.html
but if they visit .pdf, they will be served a pdf format.
localhost:3000/users/1.pdf
If the above assumptions are correct, then check prawn or wicked_pdf pdf gem. the above example uses prawn
Checkout this link http://apidock.com/rails/ActionController/MimeResponds/InstanceMethods/respond_to. You can add a new MIME type and pass on the :format as pdf in all your rails routes.
Hope this will help.
And for the POST-request check your
config/routes.rb
There shoud be a few routes already, so you can infer the route you need.
In your link you can pass an additional parameter called format for pdf. For e.g.
<%= link_to 'Display in PDF', "/user/pdf", :format => "pdf" %>

Rails can't see .rjs file

I'm trying to learn how to use AJAX in my rails apps so i've decided to start with something simple. I have a blog app on which user can vote on any blog post. Here is my code for posts#vote:
posts_controller.rb
class PostsController < ApplicationController
(...)
def vote
post = Post.find(params[:id])
if current_user.voted_on?(post)
current_user.unvote_for(post)
else
current_user.vote_for(post)
end
respond_to do |format|
format.html { redirect_to post_path(post) }
format.js
end
end
end
and here is a link code for my posts#view:
view.html.erb
<%= link_to "Vote", vote_post_path(post.id), :remote => true %>
And now, if i'll click my Vote link, posts#vote action works and vote is casted, however i'm getting an error:
ActionView::MissingTemplate (Missing template posts/vote,
application/vote with {:handlers=>[:haml, :coffee, :erb, :builder],
:locale=>[:en], :formats=>[:js, :html]}.
I have (empty) vote.rjs file in my views/posts folder but for some reason rails can't see it. According to error, the only file extensions that rails is searchng for are .haml, .coffee, .erb and .builder. Shouldn't there be also a .rjs extension on that list? Thanks in advance.
Your file should be called vote.js.erb. Rails doesn't use a .rjs extension.
The .rjs extension was originally used for Rails and Prototype JS library.
With Rails 3.1 the default library was switched to JQuery.
If you want to use .rjs in your Rails project it would mean using Prototype instead of JQuery. The gem for that is prototype-rails.

Resources