Using Prawn with Sinatra - html

How can I use Prawn to generate PDF of form data in Sinatra?
My form is at the index action of the site but Prawn doesn't recognize the variables passed in. I've found this code in the documentation at http://prawnpdf.org/docs/0.11.1/Prawn/Document.html.
get '/download' do
content = "Hello World"
Prawn::Document.generate "example.pdf" do |pdf|
pdf.font "Times-Roman"
pdf.draw_text content, :at => [200,720], :size => 32
end
end
Now this is great, but when I try to pass in my variables from the parameters like this:
post '/resume' do
#name = params.fetch 'name'
...
end
And then if I add that into the /download route like this:
get '/download' do
Prawn::Document.generate "example.pdf" do |pdf|
pdf.font "Times-Roman"
pdf.draw_text #name, :at => [200,720], :size => 32
end
end
It it will draw nothing. Also, weirdly, it generates a pdf file but doesn't redirect to it and I have to manually load it.
Really stuck on this one - advice?

Every request creates a new instance of your Sinatra app to serve it. Therefore, instance variables won't be the same across 2 different requests. You either need to persist the data using one of the many ways to do this (cookies, local storage, database, cache etc) or you need to put the Prawn logic in the POST route.

Related

How to pass back html and logic information after an ajax call with CI

I have a CI and jQuery based project. I've got a site searching my db. It consists of a jQueryUI accordion. One section contains input fields for an advanced search and the other section is used to display a html table with results.
The search parameters from the first section are sent to the server using ajax post. This is crunched by the server and either a html styled error message or a html table with results (and later some other stuff such as how many results found, how much time consumed etc.) is returned.
Back on the client jQuery must be able to distinguish between the two. Best would be to be able to transmit another variable 'search_success'. If 'search_success' is false, the error is prepended to section one above the input fields. Otherwise the html block is displayed in section two and jQuery opens section 2.
Right now I'm returning plain html with a 0 or 1 prepended. This first char is chopped off by jQuery and used to distinguish between the two possible results. This is kind of ugly.
After reading this post about sending array using json I thought about addressing this problem in json.
I intended to build something like
echo json_encode(array('search_success' => $search_success, 'html' => $html));
This would alow for nice structuring of the data. Problem now is, my 'html' is not a simple php variable but a view:
<?php
$template = array('table_open' => '<table id="table" data-url="'.base_url().'">');
$this->table->set_template($template);
$this->table->set_heading($table_header);
echo $this->table->generate($table);
?>
This view could also get a lot more complicated. Of course I could abandon the CI MVC and store the whole html in a php string which I could transform to json with the above code. However, this would defeat the purpose of storing the whole html part in a view.
Is there a way to wrap my whole view in json without relinquishing my view architecture?
Or what approach would be more suitable to the problem?
Thanks, singultus
To bring this topic to an end, the answer is simple:
$json['html'] = $this->load->view('myfile', '', true); // 3. param 'true'!
$json['other_stuff'] = $other stuff;
echo json_encode($json);
See here at the very end. This approach allows for a nicely structured response to the server.
All credit to #koala_dev!

return array in rails and storage it

I know that it could sound an "easy-question" but I am new in rails and I don't know if I am structuring correctly my app.
My app is "easy" it has to connect a webpage and collect all JPG links and store the links in a database.
In my "model folder" I have defined my functions:
class JPG < ActiveRecord::Base
acts_as_paranoid
validates :title, :link, presence: true
validates :link, uniqueness: true
attr_accessible :tag_list, :id, :title
#acts_as_taggable
def main_web
require 'rubygems'
require 'scrapi'
require 'uri'
Scraper::Base.parser :html_parser
scraper = Scraper.define do
array :items
process "div.mozaique>div", :items => Scraper.define {
process "div.thumb>a", :link => "#href"
}
result :items
end
uri = URI.parse(URI.encode(web))
return scraper.scrape(uri)
end
end
As you can see the function main_web returns an array.
Well my question is "easy". If I want to call the function and to storage the information in the database, how do I have to do it?
I don't want to show the information in the screen I only want to storage the data in the database but from where do I have to do the call? view? or controller?
I suggest you read more about the controller-view model. You need to call and store in the database from the controller.
If main_web returns an array then wouldn't #jpg = #jpg.main_web mean that #jpg is now an array instead of the Active Record model? That would seem to be why it wouldn't save. You might want to add a field to your database that holds the array you generate from main_web. Then instead of returning it you could just call save on your #jpg model.
Also a nice tip would be if you are having issues with models or other things really try typing 'rails console' on command line. You could run your 3 lines of code there to see if they worked. This wouldn't solve your issue but might allow you to play around with some things.
#jpg = JPG.new
#jpg = #jpg.main_web
#jpg.save
Replacing my initial answer after giving it more consideration...
You are doing this:
return scraper.scrape(uri)
which you assign to the #jpg instance. Thus, #jpg is no longer an instance of JPG and cannot be saved as such.
Also, it is not necessary to call and store from the controller. The controller is more a decision maker than anything. It determines state and routes control and information to the desired view or model. The model is where data should be managed. Though, that may be a matter of debate and is my opinion.
Recommended reading:
http://sirupsen.com/what-I-wish-a-ruby-programmer-had-told-me-one-year-ago/

accessing a variable outside a Requesthandler

i'm using CSS3 accordion effect, and i want to detect if a hacker will
make a script to make a parallel request; ie:
i've a login form and a registration form in the same page, but only
one is visible because there is a CSS3: to access the page, the user
agent must be HTML5 compatible.
the tip i use is:
class Register(tornado.web.RequestHandler):
def post(self):
tt = self.get_argument("_xsrf") + str(time.time())
rtime = float(tt.replace(self.get_argument("_xsrf"), ""))
print rtime
class LoginHandler(BaseHandler):
def post(self):
tt = self.get_argument("_xsrf") + str(time.time())
ltime = float(tt.replace(self.get_argument("_xsrf"), ""))
print ltime
i've used the xsrf variable because it's unique for every user, to
avoid making the server think that the request is coming from the same
machine.
now what i want: how to make the difference between time values:
abs(ltime - rtime) ; mean, how do i access to rtime outside the class,
i just know how to access the value outside the method, i want to make
this operation to detect if the value is small, then the user is using
a script to make a parallel request to kill the server!
in other words (for general python users)
if i have:
class Product:
def info(self):
self.price = 1000
def show(self):
print self.price
>>> car = Product()
>>> car.info()
>>> car.show()
1000
but what if i've another
class User:
pass
then how do make a method that prints me the self.price, i've tried
inheritance, but got error: AttributeError: User instance has no
attribute 'price', so only methods are passed, not attributs?
It sounds like you need to understand Model objects and patterns that use persistant storage of data. tornado.web.RequestHandler and any object that you subclass from it only exists for the duration of your request. From when the URL is received on the server to when data is sent back to the browser via a self.write() or self.finish().
I would recommend you look at some of the Django or Flask tutorials for some basic ideas of how to build a MVC application in Python (There is no Tornado Tutorials that cover this that I know of).

using Perl and WWW::Mechanize to get HTML with filled-in forms and save it to file

I am trying to get a session recording of everything I do using WWW::Mechanize. It is really important to have the HTML with the input fields filled and saved to a file.
My code:
$m->save_content($file); # Saves the page without any forms filled
$m->field('user_name', $user); #fills the form
# I need to save the html with the filled form
# $m->save_content($file_2); won't do it
# $m->dump_forms; shows that mechanize knows about the filled forms
$m->click('SUBMIT.x');
$m->save_content($file); # Too late, already in a different page
Any ideas? I have seen it working with LWP::UserAgent but I don't have access to the code.
I have tried everything I can come up with but nothing will update content with the values of $m->forms().
EDIT: basically what I want is to have a function of the type:
$updated_content = merge($m->content, $m->dump_forms);
So when I save it I can see what the input that was given to the forms into a html slideshow.
I don't need to save the current state of the object or restore the session after it is closed.
The solution depends on what you are trying to achieve. The save_content method saves only the content of the last HTTP response and not the entire WWW::Mechanize state.
If you want to store a WWW::Mechanize object so that browsing can proceed at any time from a given point, then you need to investigate serializing a blessed object.
My choice would be to use Data::Dump. If you write
use Data::Dump 'dump';
use WWW::Mechanize;
my $mech = WWW::Mechanize->new;
$mech->get('http://www.mysite.com/path/resource.html');
$mech->form_with_fields(qw/ username password /);
$mech->set_fields( username => 'me', password => 'secret');
open my $dump, '>', 'mechanize_freeze.pl' or die $!;
print { $dump } dump $mech;
close $dump or die $!;
… then you should have a file that you can restore in a separate program using
my $oldmech = do 'mechanize_freeze.pl';

Evaluate code once the view is rendered in rails

In rails I've built a sort of cronjob, but once the view is rendered there some code I would like to run like a 'signoff' on the task processed.
Where would I put code so that it is run at the absolute end of processing (once the view is rendered)
How does rails process html does it buffer? (Would it flush HTML to the user as its rendered or once its rendered?)
You can render the view to a string, catch any Timeouts that could happen while rendering, log the results of the action, and return the string:
begin
#elements = Element.find(:all)
html = render_to_string
# Store the result
Result.create(:element_count => #elements.count)
rescue Timeout::Error
# Store the result of the call as failed?
Result.create(:element_count => 0)
end
send_data html, :disposition => 'inline', :type => 'text/html'
Some other things that you can do to achieve your goal could be:
You can use a rake task instead of a controller action, if the code that you need to execute is only triggered by your cron job.
Instead of directly making a request using wget in your cron job, you can call a script that will make a request to your controller, inspect the output of the request, and then log the result (maybe by calling a new action in the controller).
To pick an element from the rendered HTML, you could read the value using javascript/JQuery:
$(document).ready(function() {
var completion = $('#items_processed').val();
});