Unwelcome string at start and end of XML output - ruby-on-rails

I'm exporting XML directly to file, to avoid the time it takes to render to view, and it's working nicely:
controller:
def onixout
s = render_to_string(:template=>"isbns/onix.xml.builder")
send_data(s, :type=>"text/xml",:filename => "onix2.1.xml")
end
The Builder file is pretty standard:
xml.instruct!(:xml, :version => "1.0", :encoding => "utf-8")
xml.declare! :DOCTYPE, :ONIXMessage, :SYSTEM, "http://www.editeur.org/onix/2.1/03/reference/onix-international.dtd"
xml.ONIXMessage do
xml.Header do
if Company.where(:client_id => current_user.client_id).first.nil?
else
xml.FromCompany Company.where(:client_id => current_user.client_id).first.sendername
end
end
Isbn.where(:client_id => current_user.client_id).search(params[:q]).result.all.each do |isbn|
xml.Product do
xml.NotificationType isbn.notificationtype unless isbn.notificationtype.blank?
isbn.productcodes.each do |productcode|
xml.ProductIdentifier do
#more
In the resultant file, though, I'm getting an undesirable string at the start (e047d in this case):
e047d
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ONIXMessage SYSTEM "http://www.editeur.org/onix/2.1/03/reference/onix-international.dtd">
<ONIXMessage>
<Header>
#more
And there's a '0' at the end of the doc too.
Any idea what they are? And, obviously, how to get rid?

Related

Builder GEM XML formatting

I'm using the Ruby Gem Builder, and I need this output..
<?xml version="1.0" encoding="utf-8"?>
<fileAttachment> "name of file here.xls"
<Data>zip</Data>
<Size>7434</Size>
</fileAttachment>
My code is below, but the file name next to "fileAttachment" just isn't working.. This is something simple I'm just not seeing it?? The error says I can't mix text with a block.. makes sense I just don't know the correct syntax.
xml = Builder::XmlMarkup.new(:indent => 2 )
xml.instruct! :xml,:version=>"1.0", :encoding => "utf-8"
xml.fileAttachment("name of file here.xls") do
xml.Data "zip"
xml.Size "7434"
end
I think you want to use the text! method:
xml.fileAttachment do
xml.text! "name of file here.xls"
xml.Data "zip"
xml.Size "7434"
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.

Is there a way for acts_as_flying_saucer to save a file without calling render_pdf?

As the title says I use the Rails gem that works good but I want to separately save pdf's to a folder. Is there a way to do this without calling render_pdf?
This is what does not work:
render_pdf :template => 'caseprinttemplates/create_pdf_to_print.erb', :pdf_file => "/home/mattias/www/Inkasso/public/uploadedfiles/" + results[:title]
redirect_to new_interventionreminder_path(:case_id => #interventionreminder.case_id, :saved => "1")
return
This does work on another page:
render_pdf :template => 'caseprinttemplates/create_pdf_to_print.erb', :layout => nil, :send_file => { :filename => "samladutskrift.pdf"}
The acts_as_flying_saucer plugin is just a wrapper around the Flying Saucer java library. In the source, you can see that only a single wrapper method is defined: render_pdf().
https://github.com/dagi3d/acts_as_flying_saucer/blob/master/lib/acts_as_flying_saucer_controller.rb
You can, however, use render_pdf() to render to a file, like the examples found here:
# Renders the template located at '/foo/bar/pdf.html.erb' and stores the pdf
# in the temp path with a filename based on its md5 digest
render_pdf :file => '/foo/bar/pdf.html.erb'
# renders the template located at 'app/views/foo.html.erb' and saves the pdf
# in '/www/docs/foo.pdf'
render_pdf :template => 'foo', :pdf_file => '/www/docs/foo.pdf'
# renders the 'app/views/foo.html.erb' template, saves the pdf in the temp path
# and sends it to the browser with the name 'bar.pdf'
render_pdf :template => 'foo', :send_file => { :filename => 'bar.pdf' }

Integrate Jasper in Rails 3

I'm trying to integrate a rails 3 app with jasper following this wiki:
http://wiki.rubyonrails.org/rails/pages/HowtoIntegrateJasperReports
But it seems that a lot of information isn't updated so it's been very hard to make it work by myself. I've also read a topic at ruby-forum: http://www.ruby-forum.com/topic/139453
with some details explained but still couldn't make it work.
My first problem is related with the render_to_string method:
When the controller method runs I receive a "Template is missing" error:
this is the method:
def report
#customers = Customer.all
send_doc(render_to_string(:template => report_customers_path, :layout => false), '/pdfs', 'report.jasper', "customers", 'pdf')
end
Although this seems simple I'm not understanding why is this happening. Doesn't render_to_string with layout => false suposed to get me the string result of that action?
I also tried :action instead of :template, but it does the same.
If anybody with some expertise with this integration could help...
Thanks in advance,
André
We actually use jasperreports to create reports, and recently upgraded to Rails 3.0. To create the xml, we use xml.erb templates. Jasper reports runs in a separate glassfish server Here's the general idea:
url = URI.parse(my_url_string)
dataxml = render_to_string(:template => my_template_name).gsub(/\n/, '')
params = {'type' => 'pdf', 'compiledTemplateURI' => my_jasper_file, 'data' => dataxml }
request = Net::HTTP::POST.new(url.request_uri)
request.set_form_data(params)
obj = Net::HTTP.new(url.host, url.port)
obj.read_timeout = my_timeout_setting
response = obj.start { |http| http.request(request) }
case response
when Net::HTTPOK
send_data(response.body, :filename => my_chosen_filename, :type => "application/pdf", :disposition => "inline")
else
raise "failed to generate report"
end
I don't know anything about jasper, but it sounds like you want to do two things: render a PDF template and then send the raw output back w/ a PDF mime type:
pdf_contents = render_to_string(:template => 'users/report')
send_data(pdf_contents, :file_name => 'report.pdf', :type => 'application/pdf')
You're passing in the external URL as the template path, but that's probably wrong if you're getting errors about the template path. Fix the template path first.
Use savon to interact with jaserserver in rails3.
Here is an example:
require 'logger'
require 'savon'
logger = Logger.new(STDOUT)
logger.info "Test jasper via Savon-SOAP"
#client = Savon::Client.new {
wsdl.document = "http://localhost:8080/jasperserver/services/repository?wsdl"
http.auth.basic "jasperadmin", "jasperadmin"
}
logger.info "runReport method"
begin
result = #client.request :run_report do
soap.body = "<requestXmlString>
<![CDATA[
<request operationName='runReport' >
<argument name='RUN_OUTPUT_FORMAT'>PDF</argument>
<resourceDescriptor name='' wsType='' uriString='/reports/samples/AllAccounts' isNew='false'>
<label></label>
</resourceDescriptor>
</request>
]]>
</requestXmlString>"
end
send_data result.http.raw_body, :type => 'application/pdf', :filename => 'report.pdf', :disposition => 'attachment'
rescue Exception => e
logger.error "SOAP Error: #{e}"
end
Try to change the render_to_string() code to this:
#customers.to_xml

Difficulty with send_data in Ruby on Rails in conjunction with Spreadsheet plug-in

I have a function in a controller that takes in some specifications and generates a report on them. This function user_report is called in a view:
< %= submit_to_remote 'submit-button', "Export Report to Excel", :url => { :controller => :reports, :action => :user_report, :print_state => 'print'} % >
In reports_controller I use the Spreadsheet plugin to generate an Excel file within the user_report function. I want to use send_data to stream the file to the user without creating it on the server first. The research I've done shows that using StringIO is the way to go, as shown below. Frustratingly, nothing happens when I call send_data. The plugin seems to work well creating a file and saving it on the server, but does nothing when I use send_file, suggesting that the problem doesn't lie in the plugin. But then what am I doing wrong with send_file/send_data?
The function itself looks like this:
def user_report
if request.post?
unless params[:reports][:userid].blank?
#userid=params[:reports][:userid]
end
if params[:print_state]=='print'
report = Spreadsheet::Workbook.new
info = report.create_worksheet :name => 'User Information'
info.row(1).push 'User ID', #userid
#outfile = "Report_for_#{#userid}.xls"
require 'stringio'
data = StringIO.new ''
report.write data
send_data data.string, :type=>"application/excel", :disposition=>'attachment', :filename => #outfile
end
respond_to do |format|
format.js { }
end
end
end
The log file reads
2010-10-18 14:13:59 INFO -- Sending data Report_for_jjohnson.xls
but no download begins in-browser. I've succeed in using send_data on this app before, which is confusing.
I'm using Rails v2.3, Ruby v1.8.7, and Spreadsheet v6.4.1 at spreadsheet.rubyforge.org.
Just change the line:
send_data data.string, :type=>"application/excel", :disposition=>'attachment', :filename => #outfile
to:
send_data data.string.bytes.to_a.pack("C*"), :type=>"application/excel", :disposition=>'attachment', :filename => #outfile
Even though I dont like to write and delete , but with spreadsheet seems like the only solution.
# write the file
book.write "Employee_History_#{ params[:id]}.xls"
# send the file
send_file "Employee_History_#{ params[:id]}.xls", :type => "application/vnd.ms-excel", :filename => "data.xls", :stream => false
# and then delete the file
File.delete("Employee_History_#{ params[:id]}.xls")
For someone looking at this in (or after) 2022, a possible solution to this would be to use Axlsx Gem. The interface provides a method for converting it to a StringIO object. (From Axlsx Documentation)
#serialize to a file
p = Axlsx::Package.new
# ......add cool stuff to your workbook......
# Serialize to a stream
s = p.to_stream()
send_data(
s.read,
:type => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
:disposition => 'attachment',
:filename => #filename
)

Resources