I have an application where a user can upload a PDF document, when the pdf document is uploaded (with a front-end Stimulus controller using ActiveStorage DirectUpload), I then process the PDF to strip content out to place into an Excel Spreadsheet. Everything is uploaded to an s3 bucket.
My model looks like this:
class Export < ApplicationRecord
has_one_attached :pdf
has_one_attached :spreadsheet
validates :pdf, attached: true, content_type: 'application/pdf'
def process_pdf!
self.pdf.open(tmpdir: "#{Rails.root}/tmp") do |file|
tmpfile = File.open(file.path)
file_name = File.basename(file.path).sub(".pdf", "")
op = PdfScraper.call(pdf_file: tmpfile, output_name: file_name)
attach_spreadsheet(file_name: file_name)
end
end
private
def attach_spreadsheet(file_name:)
self.spreadsheet.attach(
io: File.open("#{Rails.root}/tmp/#{file_name}.xlsx"),
filename: "#{file_name}.xlsx",
identify: false,
content_type: "application/vnd.ms-excel"
)
end
end
The controller looks like this:
class ExportsController < ApplicationController
def create
#export = Export.new(export_params)
#export.uuid = cookies[:visitor_uuid]
respond_to do |format|
if #export.save
#export.process_pdf!
flash[:notice] = "Success!"
format.html { redirect_to download_path }
else
flash[:error] = #export.errors
format.html { redirect_to root_path }
end
end
end
private
def export_params
params.require(:export).permit(:pdf)
end
end
When the redirect happens back to the download_path, I am finding the Export based on the cookie ID but when I attempt to inspect (or view) the download URL for the attached spreadsheet, I am getting the following error:
undefined method `persisted?' for nil:NilClass
The View looks like:
<p>
<%= polymorphic_url(#export.spreadsheet) %>
</p>
I even tried the rails_blob_url(#export.spreadsheet) and it doesn't work. If I look up the URL via the rails console, it seems to work.
Related
I can hit the importers#import_vendor_ledger action but I can't seem to hit the importers#import_chart_of_accounts action via the redirect_based_on(arg) method inuploaders#upload_file. Please help!
NOTE: I left out some code that I didn't think was necessary to see
My code:
routes.rb
resources :uploaders do
collection { post :upload_file }
end
resources :importers do
collection { post :import_vendor_ledger, :import_chart_of_accounts }
end
index.html.haml
#chart_of_accounts
= form_tag upload_file_uploaders_path, multipart: true do
= hidden_field_tag :account, "chart_of_accounts"
= file_field_tag :file
= submit_tag 'Upload Chart of Accounts'
#vendor_ledger
= form_tag upload_file_uploaders_path, multipart: true do
= hidden_field_tag :account, "vendor_ledger"
= file_field_tag :file
= submit_tag 'Upload'
uploaders_controller.rb
class UploadersController < ApplicationController
include Excel
def upload_file
uploaded_io = params[:file]
if uploaded_io.path.downcase.end_with?(xlsx_extension)
save_to_storage(uploaded_io)
flash[:success] = 'File uploaded successfully!'
redirect_based_on_(params) # this is where it should call the action
else
flash[:warning] = 'ERROR: The file you upload MUST be an ".xlsx" excel file!'
redirect_to root_url
end
end
private
def redirect_based_on_(_params)
case _params[:account]
when "vender_ledger"
redirect_to import_vendor_ledger_importers_path and return
when "chart_of_accounts"
redirect_to import_chart_of_accounts_importers_path and return
end
end
end
importers_controller.rb
class ImportersController < ApplicationController
include Excel
def index
end
def show
end
def import_vendor_ledger # I can hit this action
puts "hits vendor ledger import"
end
def import_chart_of_accounts # but I can't hit this action
puts "hits chart of accounts import"
end
EDIT #1: even if I explicitly call redirect_to import_chart_of_accounts_importers_path in uploaders#upload_file it still doesn't hit the importers#import_chart_of_accounts action
EDIT #2: after inspecting more, it seems that importers#import_chart_of_accounts action IS being hit, but none of the functions in the action is being called
Change your route to something like this:
resources :importers do
collection do
get :import_vendor_ledger
get :import_chart_of_accounts
end
end
EDIT: Since you are redirecting to those two paths, I believe, you need those to be GET routes. Since redirect_to issues a 301 request which will be GET request.
My objective is generate every month a PDF.
I am using Prawn Gem.
Likes this:
../Generatepdf/July2015.pdf
../Generatepdf/August2015.pdf
../Generatepdf/Setember2015.pdf
etc...
So my problem is how to define the urls?
I got a controller "Generatepdf" with a view "index.html"
I only can access of my PDF via:
../generatepdf/index.pdf
Controller:
class GeneratepdfController < ApplicationController
def index
respond_to do |format|
format.html
format.pdf do
pdf = ConsumptionsPdf.new
send_data pdf.render, filename: "lol2.pdf",
type: "application/pdf",
disposition: "inline"
end
end
end
end
Class:
class ConsumptionsPdf < Prawn::Document
def initialize
super
text "example"
end
end
I've a Clients controller:
class ClientsController < ApplicationController
def index
#clients = Client.all
respond_to do |format|
format.text do
file_name = "clients_emails.txt"
send_data #clients.pluck(:email).join('; '), file_name: file_name
end
end
end
end
There is a link in the application that points to this controller index action :
link_to "Extract Email List", clients_path(format: "text")
When I press the link the file is automatically downloaded but the name of the file is clients.text
It looks like :file_name option is being ignored.
Is there a way with send_data to force the browser to create a file with a given name?
Try it with filename:
send_data #clients.pluck(:email).join('; '), filename: file_name
So I setup my app to upload documents to S3 (following Ryan Bates' railscast). Currently, there's a form to upload a file is on the index page for the document resource. On successful upload to S3, that form renders the new actions where the user can rename the file (as it's named locally).
But I'd like to refactor this to eliminate redirecting the user to the '/new' page. I don't want to offer the user a chance to rename the file.
There's got to be a way to upload the file to S3 and then have it post to the create action.
This is what my controller looks like now.
class DocumentsController < ApplicationController
before_filter :authenticate_user!
def index
#page_title = "Docs"
#documents = household.documents.all
#uploader = Document.new.file_upload
#uploader.success_action_redirect = new_document_url
end
def new
#page_title = "New Doc"
#document = Document.new(household_id: household.id, key: params[:key])
end
def create
#doc = Document.new(params[:document])
if #doc.save
flash[:notice] = "Consider it done!"
redirect_to documents_path
else
flash[:notice] = "Oops. Please try again."
render 'new'
end
end
end
How do I simplify this situation and avoid rendering the /new page? Instead of rendering the /new, I want to just post to the create action. I need modify this line:
#uploader.success_action_redirect = new_document_url
but I don't know what it should be.
Perhaps you can create a method in DocumentsController that serves as a REST endpoint. You post from the client via Ajax and then upload to S3 in the endpoint method. This way the client's experience remains unchanged with the upload.
Something like this:
def upload
uploader = Document.new(params_from_ajax_post).file_upload
respond_to do |format|
format.html { render :json => {:message => 'Upload successful.'} }
end
end
In routes.rb:
match 'documents/upload' => 'documents#upload', :via => :post, :as => 'upload'
I have a controller that responds_to html and png ( I load the image dynamically and render it as text ). That makes the controller code messy and today I found respond_with, which looks very cool, but I can't found out how to make it work with formats, different than html, json and xml ( like the png )
I expected that this would work, but it stills tries to find a template file and ignores my method :(
models/user.rb
class User < ActiveRecord::Base
def to_png
File.read("some_file.png")
end
end
controllers/users_controller.rb
class UsersController < ApplicationController
respond_to :html, :png
# GET /users/1
def show
#user = User.find(params[:id])
respond_with(#user)
end
end
Try to add in file [YOUR_APP]/config/initializers/mime_types.rb:
Mime::Type.register "image/png", :png
and restart your application
if you need to use a MIME type which isn’t supported by default, you
can register your own handlers in environment.rb as follows.
Mime::Type.register "image/jpg", :jpg
http://apidock.com/rails/ActionController/MimeResponds/InstanceMethods/respond_to
in environment.rb
Mime::Type.register "image/png", :png
then
respond_to do |format|
format.png do
#do stuff here
end
end
or
respond_with #user do |format|
format.png do
#do stuff here
end
end