Prawn PDF and muliplte records - ruby-on-rails

I'm looking to extract all records to a single pdf using Prawn PDF and rails 4.2.
Currently I have them generating by id for individual pdf's and works well.
Show
def show
#agreement = Agreement.find(params[:id])
respond_to do |format|
format.html
format.pdf do
pdf = AgreementPdf.new(#agreement)
send_data pdf.render, filename: "Agreement - #{#agreement.entity}", type: "application/pdf", disposition: "inline"
end
end
end
Index in table
<% #agreements.each do |agreement| %>
<tr>
<td><%= agreement.entity %></td>
<td><%= link_to 'Download', agreement_path(agreement.id, format: 'pdf'), :target => "_blank" %></td>
</tr>
<% end %>

First, you have to add a route with the path of the new method:
get '/agreements/all_records' => 'agreements#all_records', :as => :agreement_all_records
Then call the methods with in the view:
<td><%= link_to 'Download All Records', agreement_all_records_path(), :target => "_blank" %></td>
It will look something like this in the controllers:
def all_records
#agreements = Agreement.all
pdf = AgreementsPdf.new(#agreements)
send_data pdf.render,filename:'agreements.pdf',type:'application/pdf', disposition: 'inline'
end
And the Report may look like this ( assuming that agreement model has id,name fields ):
require 'prawn/table'
class AgreementsPdf < PdfReport
TABLE_WIDTHS = [100, 100]
PAGE_MARGIN = [40, 40, 40, 40]
def initialize(agreements=[])
super(:page_size => "LEGAL", margin: PAGE_MARGIN, :page_layout => :landscape)
#agreements = agreements
display_table
end
private
def display_table
if table_data.empty?
text "None data"
else
table(table_data,column_widths: TABLE_WIDTHS, :cell_style => { size: 10 } )
end
end
def table_data
#table_data ||= #agreements.map { |e| [e.id, e.name] }
end
end
Hope this will give you an idea

Related

Rails exporting xls using link_to format

Hello everybody who likes RAILS, i have a problem i'm trying to export by "ejecutive_id" to XLS but i'm not doing the correct code,
-I created a select box where i can select all my ejecutives.
-I created another select box where i can select by status_id.
-I selected 1 ejecutive for example "Mogan" (ejecutive_id = 1)
-I selected 1 status form example "active" (status_id = 0 )
-After selecting both select boxes i click on "SEARCH"
-After doing SEARCH i'm getting my results (#list_policies this value in my code is before respond format)
Here is my controller
****PROJECT/APP/CONTROLLER/policy_managment/policy.rb********
class PolicyManagement::PolicyController < ApplicationController
def generate_print_ejecutive_comercial
#search_ejecutive = params[:search_ejecutive]
#search_status = params[:status_id]
#list_ejecutives_comision = Ejecutive.find(:all)
#list_policies_search = Policy.deleted_is(0)
if params[:search_ejecutive].to_i!=0
#list_policies_search = #list_policies_search.ejecutive_id_is(#search_ejecutive)
end
if !params[:status_id].blank?
if params[:status_id].to_i != 3
#list_policies_search = #list_policies_search.state_is(params[:status_id])
end
else
#list_policies_search = #list_policies_search.state_is(0)
end
#status_id = params[:status_id]
if !#search_dependent_dni.blank?
if #list_dependents.blank?
#list_dependents = Dependent.id_gt(0)
end
#list_dependents = #list_dependents.num_document_is(#search_dependent_dni)
list_dependencies = []
#list_dependents.each do |dependent|
list_dependency_dependents = Dependency.find(:all, :conditions => { :dependent_id => dependent.id })
list_dependency_dependents.each do |dependency|
list_dependencies << dependency
end
end
policy_ids = []
list_dependencies.each do |dependency|
policy_ids << dependency.policy_id.to_i
end
end
#list_policies_search = #list_policies_search.deleted_is(0)
#list_policies = #list_policies_search.paginate(:page => params[:page], :per_page => 10)
#results = #list_policies_search.find(:all,:conditions=> { :ejecutive_id => #search_ejecutive })
respond_to do |format|
format.html
format.xls
format.js {
render :update do |page|
page.replace_html 'table', :partial => 'table2'
end
}
end
end
end
Here maybe could be the problem,also those are my links where i can export
*********HERE IS MY VIEW***********
<% form_remote_tag :url=>{:action=>"generate_print_ejecutive_comercial"},:before=>"load_close('loading_search')",:success=>"load_off('loading_search')" do -%>
<label>EJECUTIVES:</label>
<%= select_tag 'search_ejecutive',"<option value=\"\">Select</option>"+options_for_select(#list_ejecutives_comision.collect {|t| [t.name.to_s+" "+t.lastname1.to_s,t.id]})%>
</span>
<label>STATUS :</label>
<%= select_tag "status_id","<option value=\"3\">ALL</option>"+options_for_select([["active",0],["cancel",1],["no cancel ",2]],0) %>
</span>
<input name="Buscar" value="SEARCH" type="submit" /><span id="loading_search"></span>
<% end %>
#HERE WITH THOSE LINKS I'M EXPORTING ONLY MY FIRST 10 VALUES
<%= link_to("Export Excel","http://localhost:3000/policy_management/policy/generate_print_ejecutive/generate_print_ejecutive_comercial.xls")%>
<%= link_to "Export XLS",:controller=>"policy_management/policy",:action=>"generate_print_ejecutive_comercial",:format=>"xls" %>
<%= link_to 'PRINT PDF', :controller=>"policy_management/policy",:action=>"generate_print_ejecutive_comercial", :format=>"pdf" %>
I'm exporting my partial view and it depends of this
#list_policies = #list_policies_search.paginate(:page => params[:page], :per_page => 10)
Here is my partial view and i'm using #list_policies
********************PARTIAL VIEW THAT I WANT TO EXPORT*********
<table>
<% #list_policies.each do |policy| %>
<tr>
<td><div class="nobreak"><%= policy.num_policy%></div></td>
<td><div class="nobreak">
<% if !policy.ejecutive.blank? %>
<%= policy.ejecutive.name %><%= policy.ejecutive.lastname1 %><%= policy.ejecutive.lastname2 %>
<% end %></div>
</td>
<td><div class="nobreak"><%= policy.str_state%></div></td>
</tr>
</table>
Seems that i need to add some params to my links_to....format.... i don't know what to add
Somebody can check this code?
It seems like using an options hash to dynamically build your query might be easier / cleaner. I would do it like this:
class PolicyManagement::PolicyController < ApplicationController
def generate_print_ejecutive_comercial
#list_ejecutives_comision = Ejecutive.find(:all)
policy_options = {:deleted => false}
policy_options = policy_options.merge({:ejecutive_id => params[:search_ejecutive]}) unless params[:search_ejecutive].blank?
policy_options = policy_options.merge({:state => params[:status_id]}) unless params[:status_id].blank? and (params[:status_id] != 3)
#list_policies_search = Policy.all(policy_options)
if !#search_dependent_dni.blank?
if #list_dependents.blank?
#list_dependents = Dependent.id_gt(0)
end
#list_dependents = #list_dependents.num_document_is(#search_dependent_dni)
list_dependencies = []
#list_dependents.each do |dependent|
list_dependency_dependents = Dependency.find(:all, :conditions => { :dependent_id => dependent.id })
list_dependency_dependents.each do |dependency|
list_dependencies << dependency
end
end
policy_ids = []
list_dependencies.each do |dependency|
policy_ids << dependency.policy_id.to_i
end
end
#list_policies = #list_policies_search.paginate(:page => params[:page], :per_page => 10)
respond_to do |format|
format.html
format.xls
format.js {
render :update do |page|
page.replace_html 'table', :partial => 'table2'
end
}
end
end
end

how to redirect two different url's from two different buttons from index in controller?

How to redirect the two links to two urls by using single method in controller?
Example:
def index
#location_id = Location.find(#location_id)
#epc = Enr::Rds::CurrentEpc.find_by_location_id(#location_id)
if # PDF EPC link clicked
#epc.current_epc_path[-4..-1] == '.pdf'
content = open(#epc.current_epc_path, "rb") {|io| io.read }
send_data content, :filename => 'epc.pdf', :disposition => 'inline'
end
if # LIVE EPC link clicked
#epc = Enr::Rds::XmlData.find_by_location_id(#location_id)
redirect_to #epc.report_url
end
end
in my view,
<%= link_to 'PDF', enr_location_current_epc_index_path(#location) %>
<%= link_to 'LIVE', enr_location_current_epc_index_path(#location) %>
in my routes
resources :current_epc, only: [:index, :show] do
get :download, :on => :collection
end
I would consider create 2 differente actions. One for each case. It would make your actions and your code much easier to read.
Then u would result with 3 actions. Index which would only load the initial objects, one to treat the specific id by the first logic and another link to treat the second logic.
def index
#location_id = Location.find(#location_id)
#epc = Enr::Rds::CurrentEpc.find_by_location_id(#location_id)
end
pdf_epc
#location_id = Location.find(#location_id)
#epc = Enr::Rds::CurrentEpc.find_by_location_id(#location_id)
#epc.current_epc_path[-4..-1] == '.pdf'
content = open(#epc.current_epc_path, "rb") {|io| io.read }
send_data content, :filename => 'epc.pdf', :disposition => 'inline'
end
def live_epc
#epc = Enr::Rds::XmlData.find_by_location_id(#location_id)
redirect_to #epc.report_url
end
in your routes
resources :current_epc, only: [:index, :show] do
get :download, :on => :collection
end
get "/pdf_epc/:id" => "current_epc#pdf_epc", :as => enr_location_current_epc_pdf
get "/live_epc/:id" => "current_epc#live_epc", :as => enr_location_current_live_epc
in your view
<%= link_to 'PDF', enr_location_current_epc_pdf_path(#location) %>
<%= link_to 'LIVE', enr_location_current_live_epc_path(#location) %>
def pdf_url
if (params[:url] == 1)
do something
else
do something else
end
#epc = Enr::Rds::CurrentEpc.find_by_location_id(#location_id)
if #epc != nil
#epc.current_epc_path[-4..-1] == '.pdf'
content = open(#epc.current_epc_path, "rb") {|io| io.read }
send_data content, :filename => 'epc.pdf', :disposition => 'inline'
end
end
In your routes.rb:
match "/anything/pdf_url/:url" => "anything#pdf_url"
And your two links:
<%= link_to "first", "/anything/pdf_url/1" %>
<%= link_to "second", "/anything/pdf_url/2" %>
EDIT:
member is used when it requires an :id parameter, if not it is a collection. Anyway, I would use match in that case like (which is in parenthesis is optional):
match "/anything(/download/:url)" => "anything#index"
and get the parameter in your controller like this:
def index
if params[:url] == 1 # Or whatever you put in your link_to
# redirect_to url
else
# redirect_to url
end
end
EDIT 2:
Index controller:
def index
if params[:id]
#location_id = Location.find(params[:id])
#epc = Enr::Rds::CurrentEpc.find_by_location_id(#location_id)
if params[:url] == 'pdf'
#epc.current_epc_path[-4..-1] == '.pdf'
content = open(#epc.current_epc_path, "rb") {|io| io.read }
send_data content, :filename => 'epc.pdf', :disposition => 'inline'
elsif params[:url] == 'live'
#epc = Enr::Rds::XmlData.find_by_location_id(#location_id)
redirect_to #epc.report_url
end
else
#locations = Location.all
respond_to do |format|
format.html
format.json { render :json => #locations }
end
end
end
Your routes:
match "/anything(/:id(/:url))" => "anything#index"
Your view (change links to fit your tastes, it's just a simple example):
<%= link_to "first", "/anything/1/pdf" %>
<%= link_to "second", "/anything/1/live" %>

How I can dynamically generate url ( for generating xls report )?

Hello!
I have this trouble: I'm searching reports by date and in html view everything is alright, BUT when I'm rendering xls view error appear, because it didn't receive params, so I need to pass them in URL for xls link_to generator.
My controller:
def show
#website = Website.find(params[:id])
if params[:report] && params[:report][:start_date] && params[:report][:end_date]
#search_by_created_at
#performance_reports = #website.performance_reports.where("created_at between ? and ?", params[:report][:start_date].to_date, params[:report][:end_date].to_date)
else
#performance_reports = #website.performance_reports
end
respond_to do |format|
format.html # index.html.erb
format.xls
format.xml { render :xml => #performance_reports }
end
end
and my generated url looks like:
http://127.0.0.1:3000/websites/25/performance_reports/show?utf8=%E2%9C%93&report[end_date]=07%2F09%2F2012&report[start_date]=04%2F09%2F2012&commit=Run+Report
mine xls url is generated like this:
<%= link_to url_for(:format => 'xls') do%>
<%= image_tag("excel.png", :id => "analytics",:size => '21x23')%> <b>Export</b>
<% end %>
result:
http://127.0.0.1:3000/websites/25/performance_reports/show
Any help will be appreciated.
xls in not available by default.
Add this:
gem "spreadsheet"
gem "to_xls", :git => "https://github.com/dblock/to_xls.git", :branch => "to-xls-on-models"
Register the Excel MIME type in config/initializers/mime_types.rb by adding this:
Mime::Type.register "application/vnd.ms-excel", :xls
Add an as_xls method to model that you want to export for the fields you want.
For example for a User model you might have:
def as_xls(options = {})
{
"Id" => id.to_s,
"Name" => name,
"E-Mail" => email,
"Joined" => created_at,
"Last Signed In" => last_sign_in_at,
"Sign In Count" => sign_in_count
}
end
Add code to the controller:
def index
#users = User.all
respond_to do |format|
format.html
format.xls { send_data #users.to_xls, content_type: 'application/vnd.ms-excel', filename: 'users.xls' }
end
end
Provide a link:
= link_to 'Export', users_path(request.parameters.merge({:format => :xls}))
All code should have a test. You could do something like this:
describe "GET index.xls" do
it "creates an Excel spreadsheet with all users" do
user = Fabricate :user
get :index, :format => :xls
response.headers['Content-Type'].should == "application/vnd.ms-excel"
s = Spreadsheet.open(StringIO.new(response.body))
s.worksheets.count.should == 1
w = s.worksheet(0)
w.should_not be_nil
w.row(0)[0].should == "Id"
w.row(1)[0].should == user.id.to_s
w.row(0)[1].should == "Name"
w.row(1)[1].should == user.name
end
end

Import CSV - No such file or directory

When I want to select a file via file_field, it gives me the error that my file is 'nil'. Here's the error: "No such file or directory - Book1.csv"
May I know why? Below are the codes:
controller
def import_csv
#list = List.find(params[:list_id])
#lists = List.all
respond_to do |format|
#csv_text = File.read(params[:list][:file])
#csv = CSV.parse(#csv_text, :headers => true)
#n=0
#csv.each do | row |
#user_new = User.new
#user_new.first_name = row[0]
#user_new.last_name = row[1]
#user_new.email = row[2]
#user_new.company = row[3]
#user_new.address = row[4]
#user_new.city = row[5]
#user_new.state = row[6]
#user_new.zipcode = row[7]
#user_new.country = row[8]
#user_new.notes = row[9]
#user_new.birthday = row[10]
#user_new.home_number = row[11]
#user_new.mobile_number = row[12]
#user_new.list_id = #list.id
#user_new.save
#list.subscribers += 1
#list.save
#n=#n+1
GC.start if #n%50==0
flash[:notice] = "CSV Imported Successfully, with #{#n} records"
end
format.html { redirect_to lists_url }
format.json { head :no_content }
end
end
view
<%= form_for(:list, :url => list_import_csv_path(#list), :method => :get, :html => {:multipart => true}) do |f| %>
<table>
<tr>
<td><label for="dump_file">Select a CSV File :</label></td>
<td><%= f.file_field :file %></td>
</tr>
<tr>
<td colspan='2'><%= submit_tag 'Import from CSV file' %></td>
</tr>
</table>
<% end %>
This is because you try to pass the ActionDispatch::Http::UploadedFile Object as a path instead of the real path. You do:
#csv_text = File.read(params[:list][:file])
you should do:
#csv_text = File.read(params[:list][:file].tempfile.to_path.to_s)
Also it might be a problem that you use :method => :get when you upload not so tiny files. Genereally GET and File Upload arent such a great combination.^^
6/27/2017 - Hopefully someone will benefit from this if they are in the same situation I was.
It turns out, whereas I had:
= form_tag action: :bulk_upload_submit, multipart: true do
...
= file_field_tag :file, accept: 'text/csv'
and it was sending the file params as:
"file"=>"subscribers.csv"
I needed to change the form_tag to use a path instead of an action:
= form_tag upload_subscribers_path, multipart: true do
which changed the params to:
"file"=>
#<ActionDispatch::Http::UploadedFile:0x007ffda857b5e0
#content_type="text/csv",
#headers="Content-Disposition: form-data; name=\"file\"; filename=\"subscribers.csv\"\r\nContent-Type: text/csv\r\n",
#original_filename="subscribers.csv",
#tempfile=#<File:/var/folders/_4/50fjk9z57x544klj30k0g1780000gn/T/RackMultipart20170627-33947-12xwfow.csv>>

Parameter in AJAX request

I have a view which contain multiple links:
<% a.each do |q| %>
<%= link_to "stock it",
{ :action => "stock",
:qid => q.question_id,
:qur => q.question_answers_url,
:qti => q.title } ,
:remote => true %>
<div id="<%= "stock" + q.question_id.to_s %>"></div>
<% end %>
Each link generate AJAX-request. Here is a controller:
def stock
if(!Later.where(:question_id => params[:qid]).exists?)
later = Later.new(:question_id => params[:qid], :name => params[:qti], :url => params[:qur])
later.save
end
respond_to do |format|
format.js { render :layout=>false }
end
end
Now return to the view. Each link has a 'div' with unique id='stock'. When user press the link I need to add text to specific div with corresponding id.
I have a stock.js.erb file:
$("#stock<number>").html("some text");
How can I pass div-id to stock.js.erb and how can I use it ?
Common use is to add object.id to your DOM id. That what you exactly did:
<div id="<%= "stock_#{q.question_id}" %>"></div>
Then in your controller you shoud define your question_id or your exact question:
def stock
if(!Later.where(:question_id => params[:qid]).exists?)
later = Later.new(:question_id => params[:qid], :name => params[:qti], :url => params[:qur])
later.save
end
#question_id = params[:qid]
end
Now it will be shared with your stock.js.erb file:
$("#stock_<%= #question_id %>").html("some text");

Resources