I want to make PDF and Excel report code using same method and want to pass parameters only one time ,but it is showing an error
NoMethodError (undefined method `[]' for nil:NilClass) .
Controller Code -
def print_application_report
#from = params[:salary][:from_date]
#to = params[:salary][:to_date]
#company = params[:employee][:company_id]
#company_location = params[:employee][:company_location_id]
#department = params[:employee][:department_id]
#employees = Employee.where(company_id: #company.to_i,company_location_id: #company_location.to_i,department_id: #department).pluck(:id)
#travel_requests = TravelRequest.where(application_date: #from.to_date..#to.to_date,employee_id: #employees)
respond_to do |format|
format.js
format.xls {render template: 'travel_requests/application_datewise_report_xls.xls.erb'}
format.html
format.pdf do
render pdf: 'application_datewise_report_pdf',
layout: 'pdf.html',
orientation: 'Landscape',
template: 'travel_requests/application_datewise_report_pdf.pdf.erb',
# show_as_html: params[:debug].present?,
:page_height => 1000,
:dpi => '300',
:margin => {:top => 10, # default 10 (mm)
:bottom => 10,
:left => 20,
:right => 20},
:show_as_html => params[:debug].present?
end
end
end
you can check the condition in your controller with the terniary operator and check for the presence of params[:salary] and params[:employee],
Controller:
def print_application_report
#from = params[:salary] ? params[:salary][:from_date] : params[:from_date]
#to = params[:salary] ? params[:salary][:to_date] : params[:to_date]
#company = params[:employee] ? params[:employee][:company_id] : params[:company_id]
#company_location = params[:employee] ? params[:employee][:company_location_id] : params[:company_location_id]
#department = params[:employee] ? params[:employee][:department_id] : params[:department_id]
#employees = Employee.where(company_id: #company.to_i,company_location_id: #company_location.to_i,department_id: #department).pluck(:id)
#travel_requests = TravelRequest.where(application_date: #from.to_date..#to.to_date,employee_id: #employees)
respond_to do |format|
format.js
format.xls {render template: 'travel_requests/application_datewise_report_xls.xls.erb'}
format.html
format.pdf do
render pdf: 'application_datewise_report_pdf',
layout: 'pdf.html',
orientation: 'Landscape',
template: 'travel_requests/application_datewise_report_pdf.pdf.erb',
# show_as_html: params[:debug].present?,
:page_height => 1000,
:dpi => '300',
:margin => {:top => 10, # default 10 (mm)
:bottom => 10,
:left => 20,
:right => 20},
:show_as_html => params[:debug].present?
end
end
end
Explanation:
The change I made is,
#from = params[:salary]
to,
#from = params[:salary] ? params[:salary][:from_date] : params[:from_date]
the meaning of params[:salary] ? params[:salary][:from_date] : params[:from_date] is,
if there is params[:salary], then take params[:salary][:from_date], if params[:salary] is not there, then take params[:from_date]
This line can also be written as,
if params[:salary]
#from = params[:salary][:from_date]
else
#from = params[:from_date]
end
Without the actual line of error, I am making a guess here.
you are sending params as:
print_application_report_travel_requests_path(from_date: params[:salary][:from_date],to_date: params[:salary][:to_date], company_id: params[:employee][:company_id]....
Here value of param from_date is params[:salary][:from_date] but you are sending the param directly, not enclosed in salary key. so all of your params will be available directly inside params hash.
you can try changing like this.
#from = params[:from_date]
#to = params[:to_date]
#company = params[:company_id]
#company_location = params[:company_location_id]
#department = params[:department_id]
Related
I want to generate a Excel and PDF report using ruby on rails , but I have 24,278 entries to display in both reports so it is showing an error . How to solve this error .
Controller Code - (for excel)
def from_date_wise_xls
#start = params[:day]
#end = params[:to_date]
#present = params[:present]
#employee_attendances = EmployeeAttendance.where(present: #present,day: #start..#end)
respond_to do |format|
format.xls {render template: 'employee_attendances/from_date_wise_xls.xls.erb'}
end
end
(For PDF) -
def from_date_wise_pdf
#start = params[:day]
#end = params[:to_date]
#present = params[:present]
#employee_attendances = EmployeeAttendance.where(present: #present,day: #start..#end)
respond_to do |format|
format.html
format.pdf do
render :pdf => 'from_date_wise_pdf',
layout: '/layouts/pdf.html.erb',
:template => 'employee_attendances/from_date_wise_pdf.pdf.erb',
:orientation => 'Landscape', # default , Landscape
:page_height => 1000,
:dpi => '300',
:margin => {:top => 10, # default 10 (mm)
:bottom => 10,
:left => 20,
:right => 20},
:show_as_html => params[:debug].present?
end
end
end
My code is
class pdfController < ApplicationController
def index
#posts = Post.all
respond_to do |format|
format.html
format.pdf do
pdf = Prawn::Document.new
send_data pdf.render, :filename => "report.pdf", :type => "application/pdf", :disposition => "inline"
end
end
end
end
Now the problem is, pdf file downloaded. But I am getting an empty file, there is no report in that downloaded file.
And the code#posts = Post.all Post is a table, I can get the data from Post to downloaded pdf file.
As suggested in this post: http://adamalbrecht.com/2014/01/14/generate-clean-testable-pdf-reports-in-rails-with-prawn/
You can inherit Prawn::Document class for an easy configuration of your table border color and font size.
class PdfReport < Prawn::Document
# Often-Used Constants
TABLE_ROW_COLORS = ["FFFFFF","DDDDDD"]
TABLE_FONT_SIZE = 9
TABLE_BORDER_STYLE = :grid
def initialize(default_prawn_options={})
super(default_prawn_options)
font_size 10
end
def header(title=nil)
text "My Awesome Invoice!!", size: 18, style: :bold, align: :center
if title
text title, size: 14, style: :bold_italic, align: :center
end
end
def footer
# ...
end
# ... More helpers
end
Now, the above class is handful to use at other places by inheriting to some other classes, for example: posts reports, comments reports, etc. For your posts reports, We could do something like this:
class PostSummaryReportPdf < PdfReport
TABLE_WIDTHS = [20, 100, 30, 60]
TABLE_HEADERS = ["ID", "Name", "Date", "User"]
def initialize(posts=[])
super()
#posts = posts
header "Posts' Invoice Summary Report"
display_event_table
footer
end
private
def display_event_table
if table_data.empty?
text "No Events Found"
else
table table_data,
headers: TABLE_HEADERS,
column_widths: TABLE_WIDTHS,
row_colors: TABLE_ROW_COLORS,
font_size: TABLE_FONT_SIZE
end
end
def table_data
#table_data ||= #posts.map { |p| [p.id, p.name, p.created_at.strftime("%m/%d/%y"), p.created_by.try(:full_name)] }
end
end
Everything is now up and ready to be used in DRY-way within your controllers.
class pdfController < ApplicationController
def index
#posts = Post.all
respond_to do |format|
format.html
format.pdf do
pdf = PostSummaryReportPdf.new(#posts)
send_data pdf.render, :filename => "report.pdf", :type => "application/pdf", :disposition => "inline"
end
end
end
end
I hope that helps.
My code is this
def footstamp
if current_user
#user = User.find(params[:id])
#tracking = Tracking.where(:user_id => current_user.id, :target_user_id => #user.id)
if #tracking
#tracking.accessed_at = Time.now
#tracking.save
else
#tracking = Tracking.new
#tracking.user_id = current_user.id
#tracking.target_user_id = #user.id
#tracking.accessed_at = Time.now
#tracking.save
end
end
end
Then I get this error
NoMethodError (undefined method `save' for []:ActiveRecord::Relation):
Use:
#tracking = Tracking.where(:user_id => current_user.id, :target_user_id => #user.id).first
You are getting this error because the result of your method do not return a Tracking, but an array of Trackings.
Either you introduce more conditions to match only one Tracking, or use the first method or iterate over the results,
To use first:
#tracking = Tracking.where(:user_id => current_user.id, :target_user_id => #user.id).first
Iterate:
Tracking.where(:user_id => current_user.id, :target_user_id => #user.id).each do |tracking|
if tracking
tracking.accessed_at = Time.now
tracking.save
else
tracking = Tracking.new
tracking.user_id = current_user.id
tracking.target_user_id = #user.id
tracking.accessed_at = Time.now
tracking.save
end
end
Optimised answer,
def footstamp
if current_user
#user = User.find(params[:id])
#tracking = Tracking.where(:user_id => current_user.id, :target_user_id => #user.id).first_or_create
#tracking.accessed_at = Time.now
#tracking.save
end
end
More usefull methods here
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
I have this controller:
class SchedulesController "post", :except => :index
def index
#Schedules.create(:id => -1, :deviceId => "2002", :subject => "Test 2", :scheduleTime => Time.new, :repeatEveryYear => "FALSE")
##schedules = Schedules.all
respond_to do |format|
format.html # list.html.erb
format.json { render :json => #schedules.to_json }
end
end
def create
#schedule = Schedules.new.from_json(params[:schedule])
#schedule.save
render :json => "success"
end
end
The Schedule has a dateTime field, how can I get the controller to return this time formatted as "yyyy-MM-dd HH:mm:zzzz" (zzzz = Specific GMT timezone)?
Thank you
Søren
You can specify the date and time formats in the initializers. For instance, create the file config/initializers/time.rb and put the following code:
Time::DATE_FORMATS[:schedule] = "%Y-%m-%d %H:%M:%z"
Then in your Schedule.rb:
def formatted_schedule_time
scheduleTime.to_s(:schedule)
end
And every time you call the to_json method on a Schedule object, you need to do:
#schedule.to_json(:methods => [:formatted_schedule_time])