[Catalyst] template design issue: varibales stand-alone components
This question may be slightly off-topic, as it stems from my use of Mason in templates. Maybe I wouldn't have had this problem if I used something else. But I intend to re-organize my existing app with Catalyst, in a way that would allow me to continue using Mason, and I would like to know proficient Catalyst users' opinion on what seems to be fairly general design problem. I looked at TT once; it scared me: I didn't like the way it looked and found it more difficult to type than Mason. Let me assume for a moment that the question is generic, and I will attempt to present it in abstract terms. Mason templates usually consist of two parts: the template itself and the code providing values for its variables. Mason calls that code %init, and the variables defined there can be interpolated into the template. %init is not the only source of values for template variables, and it is entirely optional. Variables can also be defined as template arguments; in that case, their values will be supplied by the caller. But I am not concerned with arguments. I am concerned with the variables whose values are created through hard work, requiring possibly a lot of code and interactions with various agents. In a complicated Mason template, that usually happens in the %init section, which contains regular perl code. Additionally, perl can be used across the template in a manner similar to c preprocessing directives, providing means for conditional rendering and for generation of repetitive patterns (tables, lists, c.). Even further, instead of inserting a value of a variable into the text, a chunk of perl code can be called in-line and replaced with its return value. Alternatively, instead of calling perl code embedded into the template, the template can insert another template. I am conflicted about the best way to use templates even in the non-catalyzed Mason, and I would like to resolve this conflict before I move it to Catalyst. Here's an example. I can generate the same output with these two template variants: - variant 1 -- Dear Dr. % $surname %, ... %init my $surname = get_ldap_surname($uid); /%init ~~ - variant 2 -- Dear Dr. lib/ldap_surname.mason, uid = $User ... ~ The first variant does all the work within the same template, while the second variant delegates that same work to another template, which can be reused in other templates. I can't afford more than a trivial example, but please imagine that a typical template can have dozens of variables and/or sub-templates (known as components in Mason). If I consistently follow the first variant, I end up with fairly efficient, but extremely messy and unreadable code that provides everything the template needs in one place. The template itself tends to be complicated and incomprehensible. However, if I delegate bits of work (as well as rendering) to various sub-templates, I can achieve highly readable object-oriented structure, with simple and easy-to-understand components -- in terms of appearance as well as behavior -- at the cost of elevated redundancy and poor performance. Many components end up going to the same place for copies of the data, not knowing that their siblings have already been there and queried the same table row, for example. I wonder what is considered good design, vis-a-vis this dilemma, and what is the Catalyst way of doing this. I understand, roughly, that my first variant is more easily adaptable to Catalyst: take all that code in %init, put it in one controller action and make it fill places in a single template -- right? What should I do if I want to implement the second variant, based on sub-templates, and what can I do to avoid redundancy in controller actions, if I go that way? Is there a third way I am not aware about? Thanks, --Gene ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] template design issue: varibales stand-alone components
On Wed, 4 Feb 2009, J. Shirley wrote: The Catalyst method is quite simple, since it tries to adhere to the MVC design patterns. You would not set the variable in your templates, instead in the controller. sub action_name : Local { my ( $self, $c ) = @_; $c-stash-{surname} = $c-model('LDAP')-get_ldap_surname($id); } Then your template gets 'surname' and you can just do: Hello % $surname %! I understood as much. The problem I am grappling with is the complexity of the web pages I have to present, with many different states and transitions. There is no way I can code for that with a single template. I am used to the idea that I can have a parent template (autohandler in Mason), which provides basic navigation and status display for the site; autohandler then invokes another template (a master template for that particual page's content) which itself uses various odd templates for recurrent elements in the page, and the change of state sometimes consists of replacing one little component of a sub-component with a component of a totally different nature (say, a name is replace with a list of names, or a blank display component is replaced with a message resulting from a prior action). Mason seems to be perfect for that; I have built a fairly complicated site, and succeeded in making it look simple for the user, but it is an ugly mess within. It's enough for me to spend a month without doing something with it that I forget how it works. Even worse, I have to pass the project on to someone, and before that happens, I want to achieve some transparent architecture that a stranger can navigate and understand. Having done some minor work in Catalyst on other projects, I have high expectations. But I don't have a clear vision of how such recursive templating will play out in Catalyst. If I understood the Catalyst model correctly, I will need some sort of nested views. Or am I complicating the problem beyond necessity? How else can I achieve mutable views with a hierachy of sub-views? Thanks, --Gene ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Newbie Question about Database
connect_info = [ 'dbi:mysql:model', This is a mysql question. DBI passes the connection line is mysql. See here for an example of what you can write in it, but I cannot confirm, not being a mysl user: http://www.apachefriends.org/f/viewtopic.php?f=16t=27481 Look for any examples of mysql connection in DBI manuals. --Gene ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Newbie help
On Wed, 14 Jan 2009, Diego M. Vadell wrote: The process may run for about 15 minutes, so I have to handle , somehow, the browser timing out because of lack of output. I thought about making the script output to a tmp file and using ajax to query that file. What is the best way to do that? Is there a nice, magical CPAN module out there? :) Not sure about the best way, but to send in you in the right direction, a customary method for doing this is to have your server send chunks of data at regular intervals (shorter than the minimal browser time-out) until the request is complete. Each chunk will have its own http header, and the first chunk will idicate that this is a multipart stream by sending a special multipart/x-mixed-replace header, in which it will specify a string to use as a chunk boundary. You will probably have to form that yourself in your catalyst action. Read more about this and other options here: http://en.wikipedia.org/wiki/Push_technology Not having done that in Catalyst, I am not even sure whether its architecture supports this directly or not. You need to make sure that parts of your response are printed and flushed to stdout as soon as the data are available, and certainly before the action method completes. Here's the sequence that should take place: 1. The first response indicating that the process has been launched will have something along these lines: Content-type: multipart/x-mixed-replace;boundary=NEXT --NEXT Content-type: text/html html head title.../title /head body ... a message saying we're working to fulfill the request and advising the user against pushing browser buttons ... /body /html 2. If you have any connection to your worker process and it tells you about its progress, stream that to the browser, perhaps converting something that can be used to drive a progress bar, c. --NEXT Content-type: text/html html xx% done so far /html 3. When done, send the results in the same way : --NEXT Content-type: text/html ... results ... --NEXT -blank line Note the additional empty chunk sent after the results chunk -- it indicates that the response is complete. I can show you a very rough and ready library I use as a shell to run things on the server, pipitf their output verbatim to the browser. This method is not bullet-proof, but it lets you achieve what you want very quickly. It doesn't even send intermediate chunks to keep the browser alive; it pipes raw stdout to the browser to let the user know that the job is in progress. You run it like this (this example shows multiple things done done to a set of files in a directory: use CGI; use Cwd; use Util; my $cgi = new CGI; Util::open_cgi_shel(job title); print bgt; cd data/$dir/b\n; chdir data/$dir or die Couldn't call 'chdir data/$dir', reason: $!; foreach my $file ( grep /pattern/, `ls .` ) { chomp $file; my $command = tool -params $file $file.output; Util::run_task(*STDOUT, $command); } Util::close_cgi_shell(); ~~~ The Util library has these routines: sub open_cgi_shell { my ($title) = @_; my $this_loc = http://cci.uchicago.edu/~selkovjr/trflp;; print END Content-type: multipart/x-mixed-replace;boundary=NEXT --NEXT Content-type: text/html html head title$title/title /head body onLoad=top.opener.location.href='$this_loc' h2$title/h2 table cellpadding=5 tr td valign=centerh1font color=brown!/font/h1/td td valign=top Pushing your browser's stop button will cancel this job, possibly leaving debris in your project directory on the server. Avoid stopping the browser while the job is running, even if the browser indicates the transaction as stalled. Some tasks may take a long time to complete. It may also be a good idea to check the timeout value in your browser settings. It must not be smaller than the expected job completion time. /td /tr /table p emStarting .../em /p pre style=color: #edb; background-color: #333 END ; Util::run_task(*STDOUT, date); print \n; } sub close_cgi_shell { Util::run_task(*STDOUT, date); print q(/pre p emFinished. Give the parent window a few seconds to update.../em /p /body /html --NEXT-- ); } # this is a poor man's shell sub run_task { my ($FH, $cmd, $silent) = @_; my $pid = open PIPE, -|; if ( $pid ) { # I'm the parent select(STDERR); $| = 1; # make unbuffered select(STDOUT); $| = 1; # make unbuffered my($stat, $data); while ($stat = sysread PIPE, $data, 1024) { print $FH $data; } die sysread error: $! unless defined $stat; close PIPE; } else { # I'm the child if ( $silent ) { exec qq(echo ; $cmd 2\1); } else { exec qq(echo ; echo \b\gt; $cmd\/b\; $cmd 2\1); }
Re: [Catalyst] PostgreSQL Conference: West
On Tue, 19 Aug 2008, Joshua Drake wrote: However, one of the problems you may find from the Catalyst side of things is that we tend to forget the particulars of various databases because DBIx::Class, SQL::Abstract and SQL::Translator take a lot of the pain from being cross-database compatible out of the mix. Right, that is the constant issue with all the toolkits. My mind is something that provides an introduction to Catalyst (which is good for Catalyst) but also, Why use Catalyst with PostgreSQL?. What kind of cool features can Catalyst (and is associated libs) expose that developers might be missing. The coolest feature in postgres is its extensibility. Tsearch2, which someone mentioned in an earlier post is based on a user-defined data type. I have done some work on the postgres GIST a decade ago, which enabled applications like Tseach2, among other things. There is no full-text search capability in the postgres engine, but it doesn't have to be implemented in the engine. Two Russian astronomers came along and figured out how to index arbitrary vectors with a GIST-based data type, then they used those vectors to index documents for full-text search That's not a very straightforward method, but it works better than the built-in search methods in other databases. This goes to say that there is almost nothing one cannot do with postgres; however, it is mostly used to mimic what everyone else does with databases, with the only conspicuous advantages being its zero price, high performance and convenience. So if you really want to highlight postgres's advantages, focus on its extended behaviors. But linking that to Catalyst will appear contrived, unless we can think of a nice and complete application that uses these things as independent components. Think of something that would be difficult to do without one or the other. I am currently working on porting one of my database applications to Catalyst. It has nothing postgres-specific in it, besides the fact that if I were to use anything else (mysql, etc.) I would spend more time being annoyed than making progress. However, it has a fairly sophisticated data backend running in postgres; it has a fairly sophisticated user interface done with yui, and there's Catalyst in between. Here's one component that may be worth showcasing (after some adaptation). Take a look: http://cci.uchicago.edu:8000/plot/tree/roach (if it bitches about communication errors, wait a bit and reload the page. The server is so weak I am really afraid to publish this link) The idea is that there's a large tree structure in the database (about 7000 nodes), and there is a mass of data linked to the nodes directly or indirectly. Think of the tree as a fancy container for things. The user has two basic needs: (1) navigate the tree and (2) look into things hanging on it. Looking into things, in most cases, is easier said than done, as it may require expensive processing. Another interesting notion that may be of general interest is branch aggregates, the simplest examples of which are the count of things hung on a branch and the mean value of the common attribute, but it can be much more complicated than that. I will not go into detail explaining the meaning of this application (it's for surgical education -- highly specific), but it should suffice to say that there's a tree, there's data linked to the tree, and there can be multiple views of the tree itself and the data it contains. The data is in postgres, served with Catalyst, rendered in the browser with YUI, and because the backend portion of the rendering process is expensive, the view loads itself dynamically on user's request. This is not a good example of easy and painless development, but I have solved so many typical problems while building it that it could be used to represent a sophisticated web technology, if properly generalized. Here's a list of fairly difficult things that it can illustrate: 1. Storing a tree (nested-segment representation is used) 2. Tree traversal (I have developed (and borrowed) a couple dozen utility queries for doing things with the trees). 3. Some very involved DBIx::Class queries 4. A combination of DBIx::Class subqueries with pass-through queries used where the task is beyond DBIC's ability. 5. Tree rendering with YUI 6. Thomas Pietrzykowski's AJAX controller is used to call the applications controller actions from the browser http://thomas.pietrzykowski.de/blog/?p=1 7. External processes are called by the backend to process the data (R, gnuplot, etc.) This would be the kind of example I would like to use, but instead I had to spend months figuring things out by trial and error. If there is any interest in this kind of thing, I can spend some more time to generalize it and make it publishable. Alternatively, I could collaborate with someone to demonstrate the use of extended data types in
RE: [Catalyst] Chart::Graph::Gnuplot trouble.
On Mon, 17 Mar 2008, Peter Edwards wrote: In Chart::Graph::Gnuplot latest it looks like line 768 is in _exec_gnuplot() which calls system() to run gnuplot. There are known problems getting the exit status back from a spawned process under Catalyst. I hit this a while ago. I didn't manage to track it down quickly so I found a workaround using IPC::Run. That might work for you if you use the pseudo-ttys option. Cat-devs, any pointers as to what in Catalyst is interfering with process spawning and I/O redirection? This has more to do with the kind of server you are running under than with the Catalyst itself. More specifically, it has to do with how the servers use the I/O, and yes, they do interfere. Most of them do. The only combination I can use successfully is Apache/mod_perl. I run gnuplot and r with IPC::Run3. Fastcgi and the Catalyst dev server screw up STDIN (I believe they reopen and select() on it, but I am not sure). I have studied all available server implementations in detail, but I can't recall the details -- please forgive my vagueness. I was convinced that there is nothing a person with my level of competence could do to fix that. So, I ended up running all my stuff under mod_perl (which I don't need otherwise), and I have to restart the server every time I change my code, which it quite a PITA, but I am grateful that there is at least one way to make things work. But I would also like a competent answer to this question: what can be done to make the normal Catalyst code interact with unix processes on all 3 channels? I mean, all 3: if a process spews something on stderr, I'd like to capture that, consider how severe the message is (unless it tells me in the status code) and possibly throw an exception and ultimately forward the message to the browser. I know I will be rebuked by the people thinking along the lines of cross-platform compatibility. Spare me. I will still want to run gnuplot and a thousand other things, and talk to them through the unix I/O, because that's all they afford me to do. Thanks, --Gene ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] List spanish
On Wed, 13 Feb 2008, Matt S Trout wrote: On Wed, Feb 13, 2008 at 12:20:52PM -0400, Esteban Saavedra L. wrote: Hello, I created a list of Catalyst for Spanish-speaking people The direcion is: http://groups.google.com.bo/group/catalyst-es/ We already host the main and -de lists - if you mail me off-list I can get you a list set up on the same platform. Always easier if people can find stuff in the same place ... Especially if by finding you mean running the same search query across multiple lists, rather than poking around in the menus, or relying on the web robots to index them all, which they don't really do too well. The Spanish-speaking community is somewhat isolated, but it is very large, and that's where I often find solutions to my problems, after having exhausted the more familiar English search space. This is not to diminish the role of smaller spaces, such as suomi or Hungarian, which I will never understand, but someone else might. It will be nice to have them all under the same roof. --Gene ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
RE: [Catalyst] javascript libraries in your application
Serving your javascript as a static resource is OK if your view really has a static behavior -- that is, it does not mutate as you change parameters in your request, or it is shared among multiple requests. If it is not static, you may want to serve it as templates, in the same way you serve the screen templates. For example, I have a set of somewhat similar views into a tree-shaped database. All these views share the same YUI tree component and the same AJAX dispatcher. But the way each view uses this component is not the same; the content of the nodes, and therefore the code for their construction is somewhat different, and the associated callbacks are entirely different; also, different sets of YUI modules are loaded to minimize load times, and the module dependencies are such that various modules must be included at a number of different locations inside the page. The behavior remains conceptually the same, but the details of its implementation differ so much that I have to separate and parameterize the variations. If I didn't do that, I would end up with a huge replication of my javascript code. So I think the correct answer is, it depends. If your client-side behavior is simple and does not vary, put it into static. Otherwise, there may not be a good place for it. It may have to be designed and architected in the same way you do it with you server-side code. --Gene On Tue, 5 Feb 2008, Mesdaq, Ali wrote: I put mine under root/static/js during testing and development but on live servers I put it under /js and use mod rewrite rules to allow that and the images directory to be served up statically. For some reason having /static/js on a live URL is ghetto to me. Thanks, -- Ali Mesdaq (CISSP, GIAC-GREM) Security Researcher II Websense Security Labs http://www.WebsenseSecurityLabs.com -- From: Dennis Daupert [mailto:[EMAIL PROTECTED] Sent: Tuesday, February 05, 2008 11:43 AM To: The elegant MVC web framework Subject: Re: [Catalyst] javascript libraries in your application On Feb 5, 2008 2:04 PM, Jennifer Ahn [EMAIL PROTECTED] wrote: hello!! i just started building my web application on catalyst and i'm wondering where to put my javscript library in the framework. Usually you want your javascript library to just download to the client as is, so under root/static is a good place. I like to set dedicated directories for static files: root/static/js root/static/css /dennis Click here https://www.mailcontrol.com/sr/wQw0zmjPoHdJTZGyOCrrhg== JgBaACSDeMXQWRz9bcREXBI5WqhMaOjSoV05X3tupocxOU+hzbZ!McXk8aO1IcCWTJm2e1JR kak83gA7i1ZX0Rh0pjvjOVVc6jcNlB8Ds4+JocbhkZWBW7!0F73cQW1dwOla+spYSJAy!Vv4 KBKU6lr3gM0bZYMcdwivWgSmGe9NjQAjWNIXit9O to report this email as spam. Protected by Websense Messaging Security -- www.websense.com ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/ ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] [newbie]How to call stored procedure?
On Fri, 28 Dec 2007, Jason Kohles wrote: On Dec 28, 2007, at 8:19 AM, Tony Winslow wrote: I've stored procedures defined in my database schema, and I need to call them in my code. The arbitrary-sql approach won't help since it writes sql statements in source code to act as stored procedures. So could I do that in DBIx? You were probably looking in the Catalyst docs rather than the DBIx::Class (I'm assuming because you asked the Catalyst mailing list, rather than the DBIx::Class mailing list, which would have been more appropriate. Had you checked the DBIx::Class documentation, you probably would have found this in the cookbook... The DBIx::Class documentation wasn't very helpful to me when I was looking for the same solution. I suspect that most new users, such as myself, would want their model schemas generated for them, and so will fall for the DBIC::Schema approach as I did. If, having done that, you try to follow the recipes in the DBIx cookbook without complete understanding of what they intend to do, you will be breaking the invisible under-the-hood stuff created by the schema generator. I think it will be well for the Catalyst docs to mention that, perhaps in the form of a recipe -- something that you can follow right through. To answer the original question: you can do everything you want with arbitrary SQL in Catalyst: stored procedures, views, or whatever -- and that's not a bad way of doing things, as long as you are aware of the portability issues introduced by SQL (if that matters to you at all). Please see my posting at perlmonks explaining this: http://www.perlmonks.org/?node_id=658193 To elaborate a little bit on what I've written there, I think you will walk away with a complete understanding of what's going on with arbitrary SQL if you consider that most SQL dialects allow you to put any query (in parentheses) wherever a table name is allowed. That's why all the arbitrary SQL recipes for DBIx::Class will advise you about the parentheses (without mentioning why, because it's obvious), and they will show you how to stash your SQL query into the name attribute, perhaps leaving you wondering why something you think of as a code is strangely referred to as name. That's because it's hack -- the one exploiting SQL's recursiveness. It will work if your backend supports subselects and will fail otherwise. --Gene ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/