Ruby on rails -prawn & prawnto error - ruby-on-rails

In a ruby on rails application prawn ,prawnto is used to generate pdf raises some error..
def generate_report
generate_report = params[:report_type]
# puts(generate_report)
if generate_report == "1"
# get count of all successful downloads
#total_downloads=StatisticDownload.where("DownloadSuccess=?","1").count
#puts(#total_downloads)
# get all downloads grouped by date
#downloads = StatisticDownload.select("date(Date) as downloaded_date, count(id) as count").where("DownloadSuccess=?","1").group("date(Date)")
respond_to do |format|
format.pdf { render :layout => false }
end
end
Code in generate_report.pdf.prawn
pdf.move_down(30)
book = #downloads.map do |item|
[
item.downloaded_date,
item.count
]
end
pdf.table book, :border_style => :grid,
:row_colors => ["FFFFFF", "DDDDDD"],
:headers => ["downloaded_date", "count"],
:align => { 0 => :left, 1 => :right, 2 => :right, 3 => :right }
/admin/generate_report gives a blank page as output
/admin/generate_report.pdf gives an error
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.map
Extracted source (around line #2):
1: pdf.move_down(30)
2: book = #downloads.map do |item|
3: [
4: item.downloaded_date,
5: item.count
how can i rectify this error

May be worth going to http://railscasts.com/episodes/153-pdfs-with-prawn-revised and following the tutorial, you will have to subscribe to watch if you haven't got a pro subscription though.

Related

Rails 4, How to add an s3 image to wicked pdf

In rails 4, I am using wicked_pdf gem for .pdf file download. I have to add an image inside this pdf, right now image is rendering through wicked_pdf_image_tag in development but in test environment image(s3) is not rendering.
Used Gems are,
gem 'wicked_pdf', '1.0.3'
gem 'wkhtmltopdf-binary', '0.9.9.3'
In initializers,
class WickedPdf
wkhtmltopdf_path = Rails.env.production? ? "#{Rails.root}/bin/wkhtmltopdf-amd64" : "#{Rails.root}/bin/wkhtmltopdf-amd64"
WICKED_PDF = {
:exe_path => wkhtmltopdf_path,
:wkhtmltopdf => wkhtmltopdf_path
}
end
In controller,
respond_to do |format|
format.html {
render :pdf => "sample",
:margin => {:top => 10, :bottom => 10, :left => 10, :right => 10},
:orientation => 'Portrait', # default , Landscape,
:no_background => true
}
end
In views, I have tried to load through
<%= Rails.env.development? ? wicked_pdf_image_tag("img/logo.png") : wicked_pdf_image_tag("#{Rails.root}/public/assets/img/logo.png") %>
<%= Rails.env.development? ? wicked_pdf_image_tag("img/logo.png") : wicked_pdf_image_tag("#{Rails.root}/assets/img/logo.png") %>
<%= image_tag(ActionController::Base.helpers.asset_path('img/logo.png')) %>
How can I load s3 image in pdf file?
You can put the image in a s3 bucket and make it public. After that try it like below. If you use the below code no need to use separate syntax for different environments, it will works for all .Hope it works.
<%= wicked_pdf_image_tag('//s3.amazonaws.com/bucket_name/image.png') %>
I have worked on the similar functionality but using PDFKit gem. But I think rendering logic will be almost similar.
Below is the code where I rendered my partial in controller
def print_batch
batch = Batch.find(params[:id])
respond_to do |format|
format.pdf {
html = render_to_string("_batch",:formats => [:html], layout: false , locals: { batch: batch })
Rails.logger.debug(html.inspect)
kit = PDFKit.new(html)
send_data(kit.to_pdf, :filename => "file_name_#{batch.id}.pdf", :type => 'application/pdf') and return
}
format.html
format.json { render json: {id: batch.id, processed: batch.processed?} }
end
end
In _batch.html.haml. You can see I have used person.s3_logo for rendering the pdf image.
- logo_image_pdf = person.logo.present? ? person.s3_logo : default_credit_logo
- logo_image_html = person.logo.present? ? image_path(Person.logo.thumb('100x100').url) : image_path('default_credit_logo.png')
- logo_image = params[:format] == 'pdf' ? logo_image_pdf : logo_image_html
.bucks
%img.logo{src: logo_image }
In Person.rb model. Anyway we cannot directly render image in PDF file directly from s3. So any gem will first download it in /tmp folder and render it. This is how I have done it in my model file.
def s3_logo
file = open(self.logo.remote_url)
file.path if file
end

Relationships created by a rake task are not persisted though the rails server

I'm working my first project using Neo4j. I'm parsing wikipedia's page and pagelinks dumps to create a graph where the nodes are pages and the edges are links.
I've defined some rake tasks that download the dumps, parse the data, and save it in a Neo4j database. At the end of the rake task I print the number of pages and links created, and some of the pages with the most links. Here is the output of the raks task for the zawiki.
$ rake wiki[zawiki]
[ omitted ]
...
:: Done parsing zawiki
:: 1984 pages
:: 2144 links
:: The pages with the most links are:
9625.0 - Emijrp/List_of_Wikipedians_by_number_of_edits_(bots_included): 40
1363.0 - Gvangjsih_Bouxcuengh_Swcigih: 30
9112.0 - Fuzsuih: 27
1367.0 - Cungzcoj: 26
9279.0 - Vangz_Yenfanh: 19
It looks like pages and links are being created, but when I start a rails console, or the server the links aren't found.
$ rails c
jruby-1.7.5 :013 > Pages.all.count
=> 1984
jruby-1.7.5 :003 > Pages.all.reduce(0) { |count, page| count + page.links.count}
=> 0
jruby-1.7.5 :012 > Pages.all.sort_by { |p| p.links.count }.reverse[0...5].map { |p| p.links.count }
=> [0, 0, 0, 0, 0]
Here is the rake task, and this is the projects github page. Can anyone tell me why the links aren't saved?
DUMP_DIR = Rails.root.join('lib','assets')
desc "Download wiki dumps and parse them"
task :wiki, [:wiki] => 'wiki:all'
namespace :wiki do
task :all, [:wiki] => [:get, :parse] do |t, args|
# Print info about the newly created pages and links.
link_count = 0
Pages.all.each do |page|
link_count += page.links.count
end
indent "Done parsing #{args[:wiki]}"
indent "#{Pages.count} pages"
indent "#{link_count} links"
indent "The pages with the most links are:"
Pages.all.sort_by { |a| a.links.count }.reverse[0...5].each do |page|
puts "#{page.page_id} - #{page.title}: #{page.links.count}"
end
end
desc "Download wiki page and page links database dumps to /lib/assets"
task :get, :wiki do |t, args|
indent "Downloading dumps"
sh "#{Rails.root.join('lib', "get_wiki").to_s} #{args[:wiki]}"
indent "Done"
end
desc "Parse all dumps"
task :parse, [:wiki] => 'parse:all'
namespace :parse do
task :all, [:wiki] => [:pages, :pagelinks]
desc "Read wiki page dumps from lib/assests into the database"
task :pages, [:wiki] => :environment do |t, args|
parse_dumps('page', args[:wiki]) do |obj|
page = Pages.create_from_dump(obj)
end
indent = "Created #{Pages.count} pages"
end
desc "Read wiki pagelink dumps from lib/assests into the database"
task :pagelinks, [:wiki] => :environment do |t, args|
errors = 0
parse_dumps('pagelinks', args[:wiki]) do |from_id, namespace, to_title|
from = Pages.find(:page_id => from_id)
to = Pages.find(:title => to_title)
if to.nil? || from.nil?
errors = errors.succ
else
from.links << to
from.save
end
end
end
end
end
def indent *args
print ":: "
puts args
end
def parse_dumps(dump, wiki_match, &block)
wiki_match ||= /\w+/
DUMP_DIR.entries.each do |file|
file, wiki = *(file.to_s.match(Regexp.new "(#{wiki_match})-#{dump}.sql"))
if file
indent "Parsing #{wiki} #{dump.pluralize} from #{file}"
each_value(DUMP_DIR.join(file), &block)
end
end
end
def each_value(filename)
f = File.open(filename)
num_read = 0
begin # read file until line starting with INSERT INTO
line = f.gets
end until line.match /^INSERT INTO/
begin
line = line.match(/\(.*\)[,;]/)[0] # ignore begining of line until (...) object
begin
yield line[1..-3].split(',').map { |e| e.match(/^['"].*['"]$/) ? e[1..-2] : e.to_f }
num_read = num_read.succ
line = f.gets.chomp
end while(line[0] == '(') # until next insert block, or end of file
end while line.match /^INSERT INTO/ # Until line doesn't start with (...
f.close
end
app/models/pages.rb
class Pages < Neo4j::Rails::Model
include Neo4j::NodeMixin
has_n(:links).to(Pages)
property :page_id
property :namespace, :type => Fixnum
property :title, :type => String
property :restrictions, :type => String
property :counter, :type => Fixnum
property :is_redirect, :type => Fixnum
property :is_new, :type => Fixnum
property :random, :type => Float
property :touched, :type => String
property :latest, :type => Fixnum
property :length, :type => Fixnum
property :no_title_convert, :type => Fixnum
def self.create_from_dump(obj)
# TODO: I wonder if there is a way to compine these calls
page = {}
# order of this array is important, it corresponds to the data in obj
attrs = [:page_id, :namespace, :title, :restrictions, :counter, :is_redirect,
:is_new, :random, :touched, :latest, :length, :no_title_convert]
attrs.each_index { |i| page[attrs[i]] = obj[i] }
page = Pages.create(page)
return page
end
end
I must admit that I have no idea of how Neo4j works.
Transferring from other databases though, I too assume that either some validation is wrong, or maybe even something is misconfigured in your use of the database. The latter I can't give any advice on where to look, but if it's about validation, you can look at Page#errors or try calling Page#save! and see what it raises.
One crazy idea that just came to mind looking at this example is that maybe for that relation to be configured properly, you need a back reference, too.
Maybe has_n(:links).to(Page, :links) will help you. Or, if that doesn't work:
has_n(:links_left).to(Page, :links_right)
has_n(:links_right).from(Page, :links_left)
The more I look at this, the more I think the back reference to the same table is not configured properly and thus won't validate.

Ruby-Rails Spreadsheet "corrupted" under Microsoft Excel 2010

I am using Spreadsheet gem to allow users to export data with .xls format. The code I am showing is allowing users to open the file in Open Office and MS Excel for MAC, but not for Windows, which I get a "file is corrupted" error.
I have a method that do the XLS export like this:
book = Spreadsheet::Workbook.new
sheet1 = book.create_worksheet(:name => "Expired Activity")
# Title
title_format = Spreadsheet::Format.new(:size => 12, :pattern => 1, :pattern_fg_color => :blue, :align => :merge)
for i in 0..5
sheet1.row(0).set_format(i, title_format)
end
sheet1.row(0).push "Activity"
# Header row
header_format = Spreadsheet::Format.new(:size => 11, :pattern => 1, :pattern_fg_color => :yellow, :align => :merge)
index_row = sheet1.row(1)
index_row.push("Date")
index_row.push("First Name")
index_row.push("Last Name")
for i in 0..2
index_row.set_format(i, header_format)
end
# Row values
row_iterator = 2
#expired.each do |expired|
sheet1.row(row_iterator).push(expired.earnedOn, expired.firstName, expired.lastName)
row_iterator = row_iterator + 1
end
file_io = StringIO.new
book.write file_io
file_io.string
And this method is being called like this:
format.xls {#expired = current_user.recent_activity(unlimited_size,params[:start],nil);
send_data(build_excel_expired_activity, :filename => "#{Time.now.strftime('%Y-%m-%d')}_Expired_Activity.xls", :type => "application/xls", :disposition => 'attachment')
}
Any thoughts, or ideas?
You might want to have a look at the axlsx gem and its rails counterpart acts_as_xlsx. It supports full schema validation so you don't have to fight with this kind of thing.
https://www.ruby-toolbox.com/projects/axlsx

Error while testing assets : can't dup NilClass

I'm using rails 3.0.9 with ruby 1.9.2. I am doing a system that allow users to put items into different closets. One of the user's possibility is to copy an item of an other user into his own closet (please tell me if you don't understand, I'm not good in explaining things..).
To handle images, I'm using paperclip 2.3.16. I'm testing my app with Rspec-rails 2.6.1, Cucumber-rails 1.0.2. When I run my tests with guard & spork on the asset's copy part, i'm having a "TypeError: can't dup NilClass". I've search on the net for an answer but didn't find anything specific and working :(.
Have you an idea about this issue ?
My code for closet_spec.rb (if you need something else, just tell me) :
describe '#tidy_up' do
let!(:other_user) { Factory.create(:confirmed_user, :user_name => 'Plop', :email => 'coin#plop.fr') }
let!(:closet) { other_user.closets.first }
let!(:item) { Item.create! :type_id => 42, :closet_id => dream_dressing.id }
let!(:dressing_item) { Item.create! :type_id => 42, :closet_id => dressing.id }
before do
path = File.join(Rails.root, "spec", "support", 'image.jpg')
f = File.open(path)
2.times.map do |n|
i = Item.new :type_id => 2#, :asset => Asset.new(picture)
i.save!
puts ">>>>>>>>>>>>>>>>>>>>> #{i.id}"
i.build_asset(:picture => f)
closet.items << i
end
#count = 0
end
it 'copies given items and assets to closet' do
expect { dream_dressing.tidy_up closet.items }.to change { dream_dressing.items.count }.by 2
expect { dream_dressing.tidy_up closet.items }.to change { dream_dressing.items.map{|i| i.asset; puts ">>>>>>>>>>>>>>>>> asset : #{i.asset} " }.length }.by 2
end

How to make Rails add line numbers / time stamps to log messages?

I use tail -f to display the log file when developing my Rails app.
It shows the log messages (in color! :), which is great.
But with so much information in the 80-width console, it becomes difficult to track where a certain "set" of log messages started when, say, I clicked on a button to GET a resource.
It would be easier if there was a line number or even a time stamp at the start of each log message/line. This way I could remember that I need to start looking at the log "after line number 2365" or "after 2010/10/10 23:33:23:45".
Is this possible to do? Is there some Rails internal option for this ?
why don't you just edit your desired environment's log tags
development.rb
config.log_tags [ lambda {|r| DateTime.now } ]
If you wanted to get a time stamp:
class ApplicationController < ActionController::Base
# ...
before_filter :log_tracker
def log_tracker
Rails.logger.add(1, "Log Date: #{DateTime.now}")
end
end
And format the date however you see fit....
That would work for Rails 2.1 +, prior you could access the ActiveSupport::Buffered log object with the constant: RAILS_DEFAULT_LOGGER
Get access to the actual log file with Rails.logger.instance_values["log"]
Getting the number of lines is difficult because the logger only opens the file for writing, probably for economy. I get an IOError: not opened for reading when I try.
`
Thanks #scaney.
I found a solution here.
I modified that code to add my own coloring highlights (for development only of course!) and now I can see things like 'parameters' in yellow in the console and I'm very pleased now!
In case someone is interested, here is the code I put at the end of environment.rb.
Here is my current (dirty) implementation. Will probably fix this up later (maybe make a gem, but for now this serves me fine)
WARNING
DIRTY CODE FOLLOWS! Use at your own risk!
module ActiveSupport
class BufferedLogger
#define the ANSI escape codes for normal and bright colors
$my_my_ansi_colors = {
:normal => "\x1B[0m",
:black => "\x1B[30m",
:red => "\x1B[31m", #red
:green => "\x1B[32m",
:yellow => "\x1B[33m",
:blue => "\x1B[34m",
:magenta => "\x1B[35m",
:cyan => "\x1B[36m",
:white => "\x1B[37m",
:bred => "\x1B[1m\x1B[31m", #bright red
:bgreen => "\x1B[1m\x1B[32m",
:byellow => "\x1B[1m\x1B[33m",
:bblue => "\x1B[1m\x1B[34m",
:bmagenta => "\x1B[1m\x1B[35m",
:bcyan => "\x1B[1m\x1B[36m",
:bwhite => "\x1B[1m\x1B[37m",
}
#take a string and using the keys in the hash, replace the keys in the
#string but surround the keys with ANSI color codes
#No idea how to retain the case of the key!(TODO someday)
def my_highlight msgx,hash
return msgx if msgx.blank?
return msgx if hash.empty?
hash.each_pair do |k,v|
if not k.nil?
msgx.gsub! Regexp.new(k, Regexp::IGNORECASE), $my_my_ansi_colors[:normal]+$my_my_ansi_colors[v]+k.upcase+$my_my_ansi_colors[:normal]
end
end
msgx
end
def add(severity, message = nil, progname = nil, &block)
return if #level > severity
message = (message || (block && block.call) || progname).to_s
#INSERT BEGINS
if not $myownglobalnumbercounter.nil?
$myownglobalnumbercounter += 1
else
$myownglobalnumbercounter = 1
end
level = {
0 => "DEBUG",
1 => "INFO",
2 => "WARN",
3 => "ERROR",
4 => "FATAL"
}[severity] || "U"
message = "\x1B[0m[%d %s] : %s" % [$myownglobalnumbercounter,level,message]
message = my_highlight message, {
"debug" => :white,
"error" => :bred,
"info" => :bwhite,
"warning" => :byellow,
"warn" => :byellow ,
"parameters" => :byellow,
"#" => :bgreen,
"ms " => :bmagenta,
"GET " => :bmagenta,
"PUT " => :bmagenta,
"POST " => :bmagenta,
"DELETE " => :bmagenta
}
#INSERT ENDS
message = "#{message}\n" unless message[-1] == ?\n
buffer << message
auto_flush
message
end
end
end

Resources