Coder Social home page Coder Social logo

articles's People

Stargazers

 avatar

Watchers

 avatar

articles's Issues

Easy DOM parsing with Mojo::DOM

created_at=2011-02-23T22:48:00

Long ago, I used regex's to parse HTML.

They told me it was evil. They told me it was not maintainable. They were right.

But the alternatives were painful. They were clunky. They required me to change the way I approached HTML. They required me to abandon the hipness of css selectors I had embraced with javascript libraries, and ignore the many years spent perfecting my css-foo.

HTML::Parser, HTML::TreeBuilder, I'm sure you're brilliant in your own way. I'm sure you have conquered many lands, and for those who wanted to adapt to your mindset, you brought much happiness.

I wanted a simpler way. jQuery taught us that css selectors are that better way.

Fortunately, Mojo::DOM sprouted up out of the land of Mojolicious and cookies and rainbows and unicorns.

<script src="https://gist.github.com/813613.js?file=gistfile1.pl"></script>

Seriously, have you ever seen HTML retrieved, parsed, and processed so nicely in Perl?

Since most of you have used jQuery and/or similiar Javascript libraries, you already know how to use Mojo::UserAgent/DOM. You simply apply your existing Perl & Javascript knowledge, and you're done.

You're not relegated to parsing only web-requested data; you can use Mojo::DOM directly:

<script src="https://gist.github.com/813614.js?file=gistfile1.pl"></script>

Installing is one-step easy:

curl -L get.mojolicio.us | sh

So now you know: you can leave the cruftiness behind, and hang with the hippest of the hip - there's no need to hide your head in shame when talking with hipsters about the latest Ruby shine. Shine is external; your Mojo runs deep.

Mojo::DOM docs

Request Desktop Site

It's been years since I've given my website anything more than a cursory look. After moving on from web development to native apps, my site has been relegated to the most basic of questions:

Is it up?

Yes.

Ok.

But it's time. Time to support all the hip things: Responsive design, larger fonts, and clean layout.

2 days later, I've learned the necessities of responsive design, implemented bootstrap 4, and increased the line height and font size of my site.

There is one thing, however, that has always bothered me.

The option in every mobile browser, "Request Desktop Site", that so many sites do not support, either to stay true to the religion of forced responsive design, or out of laziness.

Fortunately, it's really easy to support this option, giving all your mobile users the option to ignore the mobile site you've tirelessly exerted yourself over, only to support a subset of the desktop version's features.

Not that I'm being passive aggressive.

At all.

Your responsive site likely has a meta viewport tag like this:

<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

You can easily check the request user agent and look for the word "mobile". If it exists, then drop the device-width and use a specific width instead:

<meta name="viewport" content="width=1024">

What's that, you say? Functionality dependent on the user agent is bad form?

Maybe.

And that would be likely true, if you were checking for a specific OS or browser, Most browsers these days include a bunch of things in the user agent string, so it would be pointless anyway.

In fact, did you know that the Android Pie browser specifies that it's AppleWebKit, in addition to "KHTML, Like Gecko.

The one string that is consistent with mobile browsers, however, is the existence of Mobile.

So that's what I'm using.

Because that's what works.

Mojocast #1 - Fun with clouds!

created_at=2011-07-05T17:56:00

I've just recently released my first Perl-related screencast, Fun with clouds.

It details how to install and build your first Mojolicious web application. I'd like to create more, just let me know what Mojolicious-related topics you would like to hear about on http://mojocasts.com. The more feedback I get, the more I'll release.

<iframe src="http://player.vimeo.com/video/25921577?title=0&byline=0&portrait=0" width="500" height="375" frameborder="0"></iframe>

Mojocast #1 Fun with clouds! from glen hinkle on Vimeo.

Enjoy!

More Mojolicious ConsoleLogger

created_at=2012-12-28T00:00:00

Mojolicious::Plugin::ConsoleLogger has been updated to provide an even easier Mojolicious debugging experience.

Previously, all log information displayed in the browser console, and you've been able to see every bridge, route, and template processed by the request:

debug-info-consolelogger-log

This is great; you don't have to tab back to the terminal - you can see what's going on right in the browser as you're looking at the content.

Let's take it a step further, though. As an application grows, it becomes increasingly difficult to remember what's available in the session, the stash, and the config. A number of questions arise in the midst of development:

What exactly was the format of that stash object? What about the value? Is it empty? What about the user id in the session? Am I even logged in? Halp!

We can halp. Mojolicious::Plugin::ConsoleLogger now displays the Config, the Session, and the Stash, in addition to the logging goodness of before.

The entire state of your Mojolicious app is available right from the browser window, and all it takes is just one CPAN module, and just one line of Perl.

Installation

cpanm Mojolicious::Plugin::ConsoleLogger

Usage

<script src="https://gist.github.com/4401646.js"></script>

o/

Hey! You can follow me on Twitter.

AZT Day 2, Night 2

<title>Cedrick</title> Arizona Trail southbound October 17, 2018

image

I camped on a weaving trail with a cloudy sky overhead; I awoke to a haunted forest fog. Hail fell intermittently, spattering the tent with a pleasant sound.

During the night, I decided my mountain lion friend is named Cedrick. My first thought when I heard the hail was that Cedrick was urinating on the tent to taunt me.

No. That’s not reasonable. It has to be something else.

Hail. Yes, it’s hail.

After packing up, I headed out of Buckskin passage; the terrain immediately changed to fields of bushes. I was now on the Kaibab Plateau, and the skies cleared up for an hour or two. This, of course, was a good time to lay my tent out to dry.

Or so you would think. It immediately started to hail again.

Fine.

The hail turned to light rain, which continued for several hours, until the terrain changed. Quite dramatically, in fact. Instead of fields of bushes, it was now a slalom of tall trees, reminiscent of North Carolina. As I came into Marble Canyon, the temperature dropped to a brisk 40 degrees, just as the terrain changed again to rolling hills with a light canopy of trees.

Sunset was coming. I looked around, and remembered the night before.

I checked the map. I was several miles from a trailhead, where others of my species sometimes congregate. The thought of making camp in a place with a fire appealed to that side of me that desires safety.

I am still scared of the dark in the forest. It’s marginally ridiculous, but I feel it. I feel Cedrick lying in wait. Waiting for me to make a mistake.

If I couldn’t make it the trailhead, then now was the time to start setting up camp.

So I ran.

For 10 minutes. I was tired. I kept running. The trail changed from flat to rocky, and I stopped to consider. The sun wasn’t set, but it was too late to stop now. I had committed.

So I ran.

Holding the pack straps to my shoulders, I decided it didn’t matter if I was tired. I was going to make it to the trailhead. I unclipped the hip belt so that I could run with my arms supporting the weight of the pack.

The trail when down over rocks, and then up. I probably shouldn’t run this, I thought. But if I keep my eyes on the trail, I’ll be fine.

I stopped to rest for a moment. And then started again. I kept running.

And then I saw it - a stop sign. And I heard a car driving by on the highway.

It was beautiful. The sun wasn’t set yet, and all I had to do was cross the street. A man was walking along and asked whether I was just starting out.

Yeah, I’m only about 38 miles in to the Arizona Trail.

“How long you been at it?”

This is day 2.

“That’s almost 20 miles a day! That’s pretty good!”

Aw.

We talked for a while. He graciously offered to give me his gloves since I had lost one earlier in the day. He went back to his RV and I set up my tent.

I’ve never been one to put a high value on community, but it felt good to interact with this man.
It was dark by the time I got my tent set up, and I was still watching for Cedrick. Less intently, though. There was a van parked with people on it, presumably resting for the night. I realized they were probably concerned about this man fumbling around in the dark.

“Look honey, he has a shaved head. That probably means he’s dangerous.”

The woman went to the bathroom facilities, and shortly thereafter the man got out of the car to make his presence known and watch after her.

I took a strange comfort in these human social meanderings.

Mojocasts forthcoming

created_at=2011-07-20T22:08:00

It's been several weeks since the first mojocast, and the response has been quite positive.

What started out as an excuse to use iMovie has turned into something useful and galvanizing. Especially encouraging are the comments from folks currently learning Perl; presenting n00b information in an easily consumable and pleasant manner solidifies new users' decisions that Perl is an excellent choice.

The second mojocast is forthcoming, delayed only by the process of moving; sleeping on couches en route has a negative effect on finding quiet locations with decent acoustics.

Never fear, though, the second mojocast is nearly complete.

Anyone who wants to contribute to its launch and the marketing of Perl through mojocasts, please contact me directly - via comments, email, or in the #mojo irc channel. The comments for the first episode indicate that even the Ruby folk are surprised and impressed with a taste of Modern Perl, so the more people that are onboard, the better; there's every reason to work together to make an impact on Perl's impression in the open source community as a whole.

Viva la revolución!

Logginz ur console with Mojolicious

created_at=2011-02-23T22:48:00

Update Plugin has been updated with more functionality. See latest blog post.

A new Mojolicious plugin has been released, Mojolicious::Plugin::ConsoleLogger.

By default, Mojolicious will send debug messages to a log/[mode].log file; if the log directory does not exist, messages will default to the terminal console.

<script src="https://gist.github.com/841380.js?file=gistfile1.eclass"></script>

You can use any of the four logging groups for customized messages:

<script src="https://gist.github.com/841386.js?file=gistfile1.pl"></script>

With Mojolicious::Plugin::ConsoleLogger, you can log these same messages directly to your browser console.

Declare the plugin:

<script src="https://gist.github.com/841389.js?file=gistfile1.pl"></script>

And view all your log messages directly from your browser:

console logger devtools screenshot.png

That's all well and good, but let's take it a step further. You can even see error messages when the template is missing:

template not found browser console error.png

Or when there's a template error:

syntax error template mojo console logger.png

Even when there's a Perl compilation error:

perl error mojo console logger.png

As always, Mojolicious installs in about a minute:

curl -L cpanmin.us | perl - Mojolicious::Plugin::ConsoleLogger

Disclaimer:
Implementation stolen from Plack::Middleware::ConsoleLogger

YAPC::NA 2012: Mojolicious, swag, and pizzazz

created_at=2012-06-20T00:14:00

The Intro to Mojolicious talk at YAPC::NA 2012 was a success!

One person came up afterwards and told me it was one of the most cogent talks at the conference. Awesome! I was definitely shooting for cogent. Someone else even mentioned that it was their favorite talk of the event, and that is indeed high praise for which I am truly grateful.

I put a lot of work into the flow of the presentation, intending for it to come across as much like a mojocast as possible. In watching the video content all over the web, I've noticed a distinct lack of cohesion in the presentation of information, and I wanted to make sure I've done everything possible to ease the transition of data into others' brains.

It's fantastic that a subset of the videos have been posted to youtube; that many more search results for modern Perl information. The more creative lightning talks were my favorite.

Sometimes, the the video of the speaker covers up necessary information in the slides:

speaker covers slides

I've put together a higher quality video of the Mojolicious presentation, complete with some post-editing pizzazz that gives it that extra edge. My edited rendition fades out the speaker video when necessary:

speaker fades out

It also displays summarized questions as they are being asked, so as to include the online viewer in the fun:

question example screenshot

The edited video also displays well at resolutions of 1024x768.

The pizzazzed presentation, as well as the set of resources and links mentioned in the talk is available at Mojolicious @ YAPCNA 2012.

I was much more interested in speaking with the general populace of the event than certain "known" names. I would often sit down in a new group of people and begin talking.

Easily, my favorite person of the entire event was @dswallis. She gave a lightning talk about how the word "Monger" has no relevance, and that the M of PM needs a better meaning.

Agreed.

I also enjoyed the job fair. I'm rarely looking for a job, but I'm always open to being convinced. It was interesting to see how each company chose to present themselves. I would have expected ActiveState to have more of a presence, but when I went by their booth, no one was there. Maybe that's why they were hiring.

That brings us to the swag.

My favorite was definitely LiquidWeb's hero:

liquidweb hero

Followed by OmniIT's throwable brain.

omniweb brain

Booking had a strong presence, mostly due to the pleasant presence of Ingrid. I stole many of their globes for no reason in particular.

globes.jpg

Shutterstock had a little paper thing, which @belden told me was face decoration. He's a liar. It's clearly beard decoration:

beard cover

Linode had some pretty neat stickers. I ganked more than my fair share, and stand by my actions.

linode

I'm happy to have attended the event. Given that this was my first tech conference, Perl, as it most often does, sets the standard that everything else is to be compared by.


Hey! Follow me on twitter!

Deploy a web app in one step

created_at=2012-07-19T05:16:15

It's easy to run a web app.

As chromatic posted, you can do it in 8 easy steps. Only 8 hurdles to jump!

That's way too many for me. It's definitely way too many for a Perl developer to advocate; it's not like we have the hipsters on our side, so we have to do better in order to win mindshare. Much better.

mojolicious: web in a box

And that's where Mojolicious comes in.

Install the toolchain in under 10 seconds with a fresh Perl installation:

curl -L tempi.re/bundles/mojo-deploy-heroku | sh

Generate an app:

mojo generate lite_app hellomojo

And that's where my new hipster tool comes in.

mojo deploy heroku logo


hellomojo deploy heroku -n hellomojo

BAM.

Deployed in just one step

In less than a minute

You don't have to know how to use git. Or the Heroku tools. You don't have to know how Heroku works. Hell, you don't even need to know what Heroku is, because the command will tell you where to sign up when you're prompted for your credentials.

There are many details involved in running a successful web app, but the name of the game here is accessibility. Reducing the hurdles, or barriers of entry, allows developers to learn what they need when they need it, and avoid complication until it becomes necessary.

Easy. Simple. Accessible.

Speaking of accessibility, we need more than a blog entry and some pod on search.cpan.org; we need a dedicated landing page with docs, workflow, and a screencast demonstrating usage:


Forget shopping. Let's go programming.

Hey! Follow me on twitter!

Mojo News: Mango

For those of you who haven’t been paying attention, the Mojolicious sister project, Mango (Non-blocking Mojo-based driver for MongoDB) has been deprecated. Frustrations with the direction of the MongoDB project have led to this difficult decision, but ultimately, time is better spent elsewhere.

Official Announcement

But what about non-blocking database access?

It’s ok!

Now we have Mojo::Pg, returning us to our relational database roots with Postgres. There’s even been an attempt at Mojo::mysql, though the outcome of that project is up in the air; that is, until you (yes, you!) decide to contribute.

JSON Document storage in Postgres

If you’re wondering how to handle JSON document storage in the future, keep an eye out for Postgres 9.4, which introduces a fancy new JSON binary type, and a fancy new query syntax to boot:

SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb;

Most importantly, we have a confirmation from the #mojo irc channel on the following piece of information:
franzkafka Wait, are you a fan of Hello Kitty?
sri Who isn’t?

You can follow tempire on the Twitter

Mojocast #5: Mojo::UserAgent

created_at=2011-12-26T08:55:00

Mojocast Monday brings you a high-level overview of Mojo::UserAgent, the client side of Mojolicious. DOM Walking, CSS selectors, and watching live requests are just a couple of the things you'll see.

Mojocast #5: Mojo::UserAgent

If this is your first exposure to mojocasts, you might want to start with the first episode.

Merry Christmas and Happy Unicorns!

APNS with Perl and Mojolicious

When I first started looking at push messages in iOS, I was under the impression that a service provider was required. Certainly, if Parse and Urban Airship had entire service plans specifically for sending push messages, I couldn’t simply do it myself.

A bit of time and research later, however, revealed to me that <a href="https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html”>APNS is not all that complicated, and you can send your own messages without the aid or clutter of an external provider.

The question becomes, then, how does one do it in Perl, and more specifically, can you use Mojolicious?

<em style=“font-size: 1.2em;”>Of course!

Fortunately for us, we don’t have to concern ourselves with the details of the APNS protocol, as <a href="https://github.com/jhthorsen”>
batman has already done it for us with <a href="http://search.cpan.org/dist/Mojo-APNS/“>Mojo::APNS.

Apple Developer Member Center

Certificates

Certificates

Development

<img src=(https://cloud.githubusercontent.com/assets/63439/4868438/dcf52914-613f-11e4-9634-6b052ac54137.png)

Add

Push selection

Choose app

Select both

Export

Save as Certificates.p12

CSS selector goodness in Mojo::DOM

created_at=2011-02-17T03:29:00

Now that we've seen how easy Mojolicious' Mojo::DOM makes parsing html, let's take a closer look at the css selector goodness it provides.

Here's a fairly verbose html sample for us to work with:

<script src="https://gist.github.com/828913.js?file=gistfile1.html"></script>

First, we initialize and parse the file:

use File::Slurp 'slurp';
use Mojo::DOM;
my $dom = Mojo::DOM->new->parse(scalar slurp 'some.html');

Getting all the articles' contents, of course, is easy:

$dom->find('li a');

But we can do better than that. Let's say we want only the article titles that have page anchors:

$dom->find('a[href^=#]');

Nah, let's get the article titles that link to external urls:

$dom->find('a[href^=http]');

How about only article titles that link to .net domains?

$dom->find('a[href*=.net/]');

We can also get the page anchors themselves:

$dom->find('div.article a[name]');

It could be that some articles have no text content; let's single those out:

$dom->find('div.article p:empty');

Or, if we want only the articles with text content:

$dom->find('div.article p:not(:empty)');

Let's get the articles that are only snippets (class name ends with 'snippet'):

$dom->find('div.article p[class$=snippet]');

There's an advertisement in the markup, let's look at the article immediately following it:

$dom->find('a.advertisement + div.article');

If you're looking to be particularly awesome, with Mojolicious 1.1, you can use all of these selectors from the command line.

Mojo::DOM currently implements all the selectors from jQuery that make contextual sense; if you run into a use case for something that's not implemented, pop into #mojo or the mailing list and make your case. Join the revolution!

As always, it's one-step easy to install:

curl -L get.mojolicio.us | sh

Mojo::DOM docs

Mojocast #3: Authentication, Helpers, and Plugins

created_at=2011-09-12T16:21:00

The response for Mojocast #2 was even more overwhelming than the first episode.

How overwhelming?

mojocast e2 #1 on hackernews.png

That's right, your upvotes matter. Within 6 minutes of posting, it was secured on the front page. Within 20 minutes, it was #1.

Consider the reality here: the most watched site on the internet by hackers/developers had a Perl-related post in the top spot. It remained on the front page for 6 hours, which is pretty good for a screencast with no article attached. That's a solid group of folks with a lot of potential aha moments in Perl's favor.

Bottom line: If you care about the marketing of Perl and its exposure among the masses, consider upvoting the Mojocast, leave a comment, and spread the word!

Hooray Perl!

Speaking of which,

Mojocast #3: Authentication, Helpers, and Plugins

Hackernews post

Manage your web app with commands

created_at=2012-07-23T04:17:57

A less known, but very important feature of Mojolicious is the ability to add your own commands to your web application. These commands can ship with your app, so that your management utilities have direct knowledge of your application.

These are some examples of commands that ship with the framework:

routes
Prints out the routes of your web app
generate makefile
Generates a makefile specifically for your web app
inflate
Moves embedded templates into separate template files

There are also commands not tied to a specific app:

generate app
Generates scaffolding for a new web app
plugin
Generate scaffolding for a Mojolicious plugin
cpanify
Upload a plugin to CPAN

Here is the thing to remember:

It's super easy to write your own command

How many times have you wasted time manually adding your preferred toolkits to your web app? How about saving yourself some time by throwing this command together?

$ mojo generate app boilerplate -w bootstrap -w backbone -w font-awesome

Or maybe you have little scripts that manage your database, scripts with hard-coded database connection info? Or maybe you programatically pull config info from a separate file? Why not make your life easier and get the database connection directly from the app?

With Mojolicious commands, you get direct access to your entire web app for free; you can even run a web request against it to get the results of a route, and use that information in your command.

There's no difference between the built-in commands and the commands you write yourself.

And it gets even better. What is the deployment process for your app? Multiple steps? Why not simplify it to one step, and distribute it with your web app?

$ myapp deploy

So much more is possible. For example, the recently released deploy heroku eliminates the need to know anything about the deploy platform, instead handling all the details with sensible defaults.

Mojolicious commands are extremely powerful, and CPAN is waiting - what commands have you hoped for in the past? What can you throw together to make your development that much easier?

Your customized command is only one subroutine away!

screenshot of adding commnds section of mojolicious cookbook

Hey! Follow me on twitter!

Perlr

created_at=2013-04-28T11:03:29

Ever since Google Reader shut down, I've found myself perusing ironman.enlightenedperl.org directly for Perl blogs. While the desire for Ironman status is no longer a priority, the effort had its intended effect in creating a steady stream of consumable Perl articles.

I appreciate the existence of the site, as it's provided a valuable role in the community, though I must admit, my desire for aesthetics are not quite fulfilled by its presentation.

Yesterday, I clicked on "Older posts" for the last time, as I've made a new site for blog aggregation, Perlr.com, complete with a fancy color scheme, a new article with recommendations for Perl community newcomers, and a logo based on Sebastian's Perl5 logo. No more paging, Perlr will display the list of all articles on the initial load, forever available with the flick of a mouse.

And of course, the Perl raptor.

For some extra flair, each article displays the author's cpan-related gravatar, if they've included their PAUSE id in the feed metadata. If you've never been a contributor to the ironman feed, now is the perfect time for you to get on that boat. Submit your blog feed today.


One Step

created_at=2013-01-02T00:40:57

If my career has taught me anything, it's the importance of having repetitive tasks be completable in one step.

Every action should take one step.

Consequently,

Every piece of information should be one step away.

How can this apply to daily development?

Let's talk about databases. What is involved when you deploy your schema? If you can't answer in under 5 seconds, the process is too long. You're wasting time. Your brainpower is not being used effectively.

When working with a Mojolicious web app, here's my process:

myapp deploy_schema

After I write the deploy_schema command, I tend not to remember the details of how it works. Sometimes it's a wrapper around DBIx::Class->deploy, sometimes it's a fixture dump with MongoDB::Collection->insert. I don't care, because I'm busy making the application do something nifty.

It's actually enjoyable to make schema changes, because I marvel at how easy it is, every time. Internally, I'm overjoyed like a little girl. Sometimes I giggle.

This giggle affects my opinion of the project. It affects how much I want to work on the project. It affects how I feel about the other people involved in the project. It positively correlates to how well the project works, how maintainable it is, and how well designed it is.

Changing a schema requires other supporting tasks, like changing tests, changing fixtures, and running those tests; those are related, but separate processes. Each one of those are one step as well, which can be subsequently combined to create higher order one-step tasks.

Keep combining, and after a while, you've got one-step deployment of the entire product...kind of like this blog. A Perl app deployed in one click.

It's a natural progression.

Make everything one step.

I'm on Twitter!

Mojolicious Full and Lite apps - understanding the difference

created_at=2012-02-08T02:18:00

The mojocasts have thus far used lite apps exclusively to demonstrate basic Mojolicious functionality. This has led some to believe that Mojolicious is a one-file micro-framework; however, that is not the case.

Mojolicious a full-featured framework, supporting what some would call Catalyst-level deployments, in addition to one-file simple applications.

Mojolicious::Lite is a thin layer on top of the full framework - literally a 68-line module that provides Sinatra-like syntax, including the ability to embed base64-encoded binary files.

Full apps are a good choice for teams, and for sanely separating concerns for large web apps.

I've uploaded a sample application to demonstrate the differences, and allow folks to see first hand how to translate from Full to Lite, and vice-versa.

The example application demonstrates DBIx::Class integration, how to test your web app with Test::Mojo, as well as how to use EP templates with and without tag helpers. For those unfamiliar with testing in general, there are even examples of DBIC schema tests.

Both apps are identical in functionality:
Full app
Lite app

They are runnable using the morbo development server, as well as hypnotoad, the "full featured UNIX optimized preforking non-blocking I/O HTTP 1.1 and WebSocket server built around the very well tested and reliable Mojo::Server::Daemon with IPv6, TLS, Bonjour, libev and hot deployment support that just works".

Shnikies that's a lot of buzzwords for a Perl framework!

And as always, Mojolicious downloads and installs in about a minute:

curl -L cpanmin.us | perl - Mojolicious

Even better, enable parallel tests and you can install in about 15 seconds!

HARNESS_OPTIONS=j9 cpanm Mojolicious

Or skip tests entirely for a 4-second installation:

curl -L get.mojolicio.us | sh

\o/

Mojoconf - A New World

I've attended YAPC. It's great for talking about the shared experience of Perl by people who use and enjoy it.

What I found with Mojoconf, however, is that it's attended by people who are excited about Mojolicious. Not just people who are content, or prefer it, but who are excited about it. They're excited about the possibilities of not just the web framework aspect of it, but the true power of the core toolkit to construct amazing applications.

One of the talks described how an enterprise moved from a Java-based system to Mojolicious; their developers can iterate faster, be more responsive, and be more flexible.

A Java-turned-Mojolicious shop because it's better for the business.

The first commercial workshop for non-blocking services with Mojolicious was a dramatic success. It was sold out, and the results were remarkable. "Difficult" concepts were understood, and the attendees were passionate about becoming not only familiar, but competent in non-blocking programming.

When a group of people finally get it - when they understand the ramifications of having thousands of simultaneously non-blocking operations - when they realize they can create those next-generation applications they've been dreaming about...everything changes. It's not about Perl anymore. It's about creating groundbreaking products.

Next year, I'll certainly be at Mojoconf. Not only because I'm involved with the project, but because the new features that have yet to appear in Mojolicious are going to open up even more possibilities. Because there is a guarantee that whatever is in store for Mojolicious over this next year is going to change the face of the community yet again.

 

It's always fresh. It's always fun.

This is the new world.

Welcome to Mojolicious.

Welcome to Mojoconf.

Mojolicious Plugins

created_at=2011-01-11T01:47:00

I've recently released a couple more Mojolicious Plugins:

They're quite simple, and match the Mojolicious::Plugin::BasicAuth implementation.

SslAuth uses the recently added TLS certificate authentication support in Mojolicious 1.01.

<script src="https://gist.github.com/773870.js?file=gistfile1.pl"></script>

The first argument passed to the callback sub is the IO handle, giving you access to whatever IO::Socket::SSL provides. (get_cipher, for example).

ParamsAuth is very basic, its purpose being to keep your params-based authentication uniform with other auth-types.

<script src="https://gist.github.com/773872.js?file=gistfile1.pl"></script>

The arguments passed to the callback are the values from the named form or query parameters.

BasicAuth has been around for a while, and uses a similar interface:

<script src="https://gist.github.com/773873.js?file=gistfile1.pl"></script>

If you're looking to be hip with the latest oauth goodness, Marcus Ramberg recently released Mojolicious::Plugin::OAuth2.

...

On a side note, Вячеслав Тихановский (vti) updated MojoX::Validator only days ago. It is, to date, the only form validation helper that doesn't make me think Amway would have been a better career choice. It can be integrated into Mojolicious or used separately. And, like Mojolicious, the code is easy to understand and contribute to. Join up!

Eponymous Hash

created_at=2013-05-08T00:00:00

You've been there.

Coding along, minding your own business, creating clear and concise lines of Perl code with maps, greps, and slices; manipulating lists with the best of them.

Suddenly, you find yourself doing this:

method_name(
  ponycorn => $ponycorn,
  sparkles => $sparkles
);

Immediately, you're offended. The sheer arrogance of this method hurts your soul. All that retyping of the same thing.

You stare at it, convinced you can fix it with some sort of list manipulation. You work through several permutations in your head, until you realize that you either have to make the code unreadable, or you have to settle for duplicating the names - once in the key, once in the value.

Years go by. You run into the same issue again and again.

We've all been there.

But no more. Now, there is Eponymous::Hash.*

Eponymous::Hash will examine your list of scalars, array refs, and hash refs, and return a hash with keys matching your variable names.

Given these declarations:

my $ponycorn  = 'jello';
my $sparkles  = 'pudding';

This statement:

eponymous_hash($ponycorn, $sparkles)

Returns this hash:

(ponycorn => 'jello', sparkles => 'pudding')

Now, you might be thinking,

1) What does eponymous mean, and 2) why do I have to type so long a name?

Excellent questions.

  1. Don't worry about it.
  2. You don't.

You can define your own method name, as short or long as you want:

use Eponymous::Hash 'epy';

method_name(epy $ponycorn, $sparkles);

Should something like this be built-in to Perl? Yes. But until then, there's Eponymous::Hash.

* There might already be solutions to this. If there are, I bet none of them mention ponycorns in their POD. Huzzah!

Learn the Platform

I used to be a web application developer.

I can certainly still develop for the web. I can create a web application using a framework, wire up the Javascript framework, and pipe the necessary data from the backend using a myriad of languages and tools.

But I don't consider myself a web application developer anymore. It's certainly a valuable skillset, even a necessary skillset, but I've moved on.

There was a time when I was really excited about web development, design, and all things that pertain to the area. It was fascinating, at the time, but I always felt limited in my capabilities, due to the fact that given the choice between a native app or a web application, I preferred a native app every time.

Screen Shot 2019-04-30 at 4 51 04 PM

Of course, being a web developer, I looked into many options wherein I could leverage my skillset to create native applications. There were many options, and I was hopeful about all of them.

I had a hammer. So I tried to use the hammer.

And then.

And then I actually used them.

They were all awful.

This was years ago, when PhoneGap was new. Before React Native. Before Electron. When Sencha Touch was seemed like it might be a great product. (It's not. Dear goodness, it's not)

But I learned my lesson.

If you want to create an application on a platform, LEARN THE PLATFORM.

It's that simple.

Now, you could create a native application using Javascript. Theoretically.

However, if you want to create a nice product, you're still going to have to learn the underlying aspects of the platform, in spite of whatever niceties the framework adds to abstract away the details.

Not to mention, the other lesson that is important for every developer to learn:

Where there is software, there are bugs.

The amount of bugs may be below the threshold where you care, but there are still issues to be addressed. Perfection that is not achieved.

So, the platform you're targeting will have bugs. And your intermediate javascript-based layer will have bugs.

Have fun with those intermediate bugs, the ones that are getting in the way of creating an actual product. Those issues that will eat away at your time, and leave you thinking, "Is this really worth it? How much more time, or less, would it take to learn the tools and language that I'm trying to bypass?"

These days, I just spend the time to learn the platform.

Sure, it takes time up front, but you either pay the price right now, or pay the cost forever, every time you want to do anything.

In software, there are no shortcuts.

Pay the cost now.

Learn the platform.

Perl numbrenclature support

created_at=2011-06-30T16:01:00

Erez Schatz has proposed that each released version of Perl be referred to as a code name.

Besides the fact that "Erez Schatz" is a cool name by itself, I think he's on to something.

Since it's clear that the Perl6 moniker is going to remain, and most folks are too curmudgeonly to change the name of Perl5, this seems like a good compromise. It allows for a clear marketing difference for each release - one that obviously works elsewhere in the tech industry.

  • Perl 5.8 Zombie (because it never dies, haunting us until the end of days)
  • Perl 5.10 Onion
  • Perl 5.12 Camel
  • Perl 5.14 Llama
  • Perl 5.16 Butterfly

(You know Sebastian's going to jump at the chance to design a nifty logo for each one)

Peter Shangov's idea is also worth pursuing - a Perl distribution with all the modern toolkits included. Given the recent logo activity, it should be called Raptor. It would be easy enough to start referring to "Raptor", just as "Rails" is a rallying cry for the Ruby folk. It could be downloadable from http://raptor.perl.org, of course - possibly even installable via perlbrew:

$ perlbrew install raptor

The Making of Mojocasts

created_at=2011-08-09T18:48:00Z

szabgab, who has quite a few screencasts, asked me to explain how I made the mojocasts.

Creating them has been quite the learning curve. My initial inspiration was Vimcasts, and although I don't have the hip accent, I figured I could put something interesting together for...something. It didn't take to long to settle on Perl and my preferred source of Perl unicorns, Mojolicious.

A Vimcast has a very cool, down-to-earth presentation; the music, the tone of voice, and the presentation as a whole tell the viewer, "Yeah, Vim is just that cool, and if you learn this, you'll be that cool as well". Presentation is vital: the Apple logo on most of my devices state as much.

Given Perl's less than stellar rep among the masses, I wanted something to counteract the stale feeling that Perl's critics likely feel - something that screamed "Fresh". Remember, we're talking about feeling here, not facts. I figured the composer of Vimcast's jingle would give me place to start, and luckily, the same composer had a royalty-free tune that broadcasted exactly the feeling I was looking for. Go ahead, listen to the mojocast intro music...close your eyes and picture a world with that theme music.

Mojolicious is Happy and Fresh

It's happy. It's fresh. It's a whole new adventure. Everything is going to be different now.

If that's not perfect for a Modern Perl presentation, I don't know what is. Tie that in with the Mojolicious theme of light and fluffy clouds, rainbows, and unicorns...hey, we've got something here.

The content was easy enough - show people how easy it is to get started. Quickly. From scratch, with no clutter. Show them exactly what they need to see, and nothing more. Walk them through the process, and throw in a couple "Huh, that's neat" moments.

I used Screenflow [update] to capture the screen. After toying with several resolutions, I changed a secondary display to 800x600 and recorded all the actions in sequence, leaving the audio for later. Screenflow allows you to fade opacity levels over time for images and video clips, which is how the intro shows the clouds and logo text in succession. I found that timing isn't important at this stage - you can always modify the speed of clips later on as necessary.

Technically, you could do the entire project from within Screenflow, but the interface is somewhat cumbersome when dealing with the entire timeline. My goal from the beginning was to use iMovie, so I decided to export it.

I'm going to save you a lot of trouble and give you a screenshot of the optimal settings you want to use when transferring a video for use in another program.

export for imovie.png

There. You have 4 more hours of your life to do something useful with.

iMovie is wonderful. Transitions, text overlays, and image importing are nearly everything you need for a decent screencast. With iMovie '11, you can add voiceovers and change the audio levels with sub-second precision, and see whether the voice levels between clips are equivalent at a glance.

I imported the full movie, and then copied each section of the imported movie into the main timeline according to topic. I learned over time that it's important to mark each section with chapter markers, since the visual representation in the timeline is at best an estimate, and it's easy to get half-empty terminal windows mixed up.

Audio Technica AT202 USB Cardioid condensrr microphone

Initially, I used the built-in Macbook mic, and happened to choose a perfect spot at my desk that detected no background noise. I ended up having to re-record all the voiceovers, and learned that the magical spot at my desk was not so easily reproducible. The second episode made use of a Audio Technica AT2020 USB Cardioid condenser microphone, recorded at 50% input volume with -40dB Noise Reduction and voice enhancement enabled. Alias pointed out that professional voiceovers are recorded while standing, so I adjusted my workstation as such; I think you'll agree that Mojocast #2 is a marked improvement in audio quality.

After all the recording is done, it's time to make video edits. There's no shortcut here. It simply takes time.

In summary:

  1. Watch the whole video.
  2. Make sure there's enough time between statements so that viewers can take in the visual and auditory information without feeling rushed.
  3. Make sure the video matches exactly what the voiceover is talking about. If you're talking about reloading a page, show the action as the word is said.
  4. Repeat until you can't stand it anymore

That's pretty much it.

I hope this is helpful to some folk. Thankful readers should buy me some cookies.

Go forth, and make some [your cool subject]casts.

*Update 2012-05-27
Quicktime now supports screen capture with more accurate color reproduction than Screenflow. It is recommended.

AZT Day 3, Night 3

<title>Jacob Stalling</title> Arizona Trail southbound October 18, 2018

UNADJUSTEDNONRAW_thumb_6493

There’s full LTE coverage at this campsite, and for most of the surrounding area. I am tickled pink when there’s data coverage on the trail. It feels so remote, but I could still make a video call were it necessary.

I probably should have woken up early and started out on the trail.

But I was craving meat. My normal diet is meat and vegetables, whereas my trail diet is light on protein and high in carbohydrates and fat. I believe my digestive system is rebelling, just a bit.

I decided to head into the nearest town.

It’s common for thru-hikers to hitchhike; I started out on the highway and let the first couple of cars pass - it felt awkward to be imposing.

On the fourth car, I held out my thumb while walking. I did that for a while.

After maybe 20 cars, I changed to the other side of the highway, and turned around as I was walking so they could see my face.

I removed my rain jacket so they could see my trail-fashionable attire.

Nothing. Fine. I can make this walk.

I walked into the restaurant, and immediately saw a counter and glass case full of fancy cookies. I had made the right decision.

At the restaurant, I ordered a bison burger, a large salad, and a chicken sandwich. Surely this would be enough protein for today. I’m not sure it was, but it would have to do.

I visited the bathroom, and washed my face, brushed my teeth, and did all the things with actual running water.

It’s only been two days, but emotionally, it feels longer. I was so grateful for human technology.

I sat in the restaurant leather chairs for a while. I reorganized my pack. Three times. I was stalling, but also waiting for my food to digest to see if I wanted more.

After a sufficient amount of time, I started back out towards the trail. I tried to cut across the forest, but there were several fences in the way. Back to the highway, I suppose.

This time, I tried a different tactic.

I walked, but as cars approached, I turned and gave them full view of my fashionable attire. I looked them in the eyes as they drove by.

Nothing.

Ok, attempt 2.

I stopped, faced the car, and pulled out my phone. This, my hope, was to show them that I was not just any vagabond. I was a vagabond with a fancy phone.

The second car picked me up. Nick was headed to Flagstaff.

Me too! Just, much slower than you.

Picking up a hitch hiker was on his bucket list, and I had filled that notch on the bucket.

Getting back on the trail after using a sink, eating meat, and getting a hitch was invigorating. I had wasted most of the day, but I still had several hours before dark. I’ve gone faster, though, as I left town with 3.5 liters of water in my pack. Water is heavy.

As the time for sunset neared, I opted to not make the same mistake as previous nights.

Set up camp during the day. Eat during the day.

Of course, as it came time, the terrain, elevation, and temperature changed. I was now walking through snow.

I found the perfect spot!

Right next to a wildlife water tank.

No.

There’s another one!

And...another wildlife water tank.

Finally, I found a mediocre spot. I was hoping to find one that had a clear shot of the rising sun so that the tent condensation would clear up quickly, but that was not for tonight.

The tent was set up. Still daylight. Good job, Glen! Now to eat.

Hmm. I finished eating in the dark. Cedrick was close, but I’m getting better. I finished up, put my food bag in a different location, and climbed in the tent.

Tomorrow, I’ll do even better.

AZT Day 1, Night 1

<title>Apex Predator</title> Arizona Trail southbound October 16, 2018

IMG_3841

I started at the northern terminus at noon, and started the first uphill climb. I didn’t know what to expect, but thus far, the Arizona Trail has easy and well marked terrain. I found the 1900 ft elevation to be relatively easy.

About 5 miles in, I rolled my left ankle and caught myself from falling by abruptly locking my knee. My ankles are strong, so rolling one isn’t a big deal, but the abrupt knee lock left me with strange and confusing feelings. After hurting my knee last year, the process of healing left me with a healthier joint, but one in which the newfound flexibility presented me with all the feels, whereas previously there was just tightness.

So now I feel things. All the time. And I don’t know what they mean. I’m told it’s normal.

I’ve heard stories of people injuring themselves from over use during the first couple days on a trail, so I stopped to let it rest.

Necessary? I have no idea. But a bad knee is not something I ever want to deal with, so I defer to these unidentifiable feelings in new situations.

I walked 12 miles today, including a rather long stop at a wildlife tank. Since it was late in the day, I took the opportunity to cook some food. Upon doing so, however, I realized I had forgotten to bring any utensils. So I used my fancy new trowel as a spoon.

That sounds awful. But it’s not. Trowels are only used for dirt. It is shiny fluorescent lime green, though. Don’t be jealous.

The sun was starting to set, so I found a place to camp, just short of the end of the Buckskin passage (40).

After much searching, I found a spot low on rocks and heavy with fallen pine for cushion. I cleared out potential sharp sticks, and set up the stakes. By this point, it was mostly dark because of the overcast sky.

After the tent was mostly staked in, I heard what sounds like an animal vomiting about 30 feet away. 30 feet is too far for my headlamp, and going to search out the source while alone didn’t seem like the wisest idea.

Now, given my previous experience with mountain lions, every unidentified sound in the wilderness now comes from a mountain lion. Every twitch, every smell, every potential step - is from a lion.

My heart starts pumping and my emotions begin jumping to conclusions as my mind races with what the next step should be.

I immediately yelled out and informed this would be lion:

BACK UP!

YOU ARE NOT AN APEX PREDATOR.

I AM AN APEX PREDATOR.

I AM AN AMERICAN OF BRITISH DESCENT.

HISTORICALLY, YOU HAVE NO CHANCE HERE. I WILL DESTROY YOU UNDER THE AUSPICE OF EXPLORATION THROUGH MEANS OF FORCE AND ECONOMY.

WHAT ECONOMIC POWER DO YOU HAVE?

NONE!

YOU DON’T EVEN HAVE A CREDIT RATING. COME BACK WHEN YOU’RE ABOVE 780.

I didn’t hear anything after that. I’m pretty sure he was convinced. As I was finishing the tent setup, I needed more sound to confound any animals around.
What could drive fear into their hearts? What could viscerally drive them away?

Zouk.

Damn. I don’t have any Zouk music for the same reason.

A west coast playlist will have to do. The sounds of Phlake and Tay-Tay will keep the wild in check as I complete the tent setup.

Now, I didn’t need to get in the tent immediately, but I will tell you that I opted to skip my normal nightly preparations and retreated to the tent, just in case this would-be lion wasn’t convinced that his credit score was relevant.

I yelled again.

780!

So now I lie here. Face unwashed. Teeth unbrushed, but secure in my apex economic power.

I’m pretty sure at least one animal defecated near enough to my tent that the wind carried the scent. It only lasted about 2 minutes.

It may have been the mountain lion being passive aggressive.

The wind tonight is fascinating. I hear slaloms of wind, intersecting in all directions, sounding like freeways above and all around me. The tent shudders, but remains taught. I keep quiet. And listen.

It’s now midnight, and one of the door stakes came out of the ground. Comfortable ground is often porous, and in my haste I did not put the door stakes in deep enough.

I have to fix it, or a strong gust could bring the tent down. It’s not freezing, but it is close. So I put on the head lamp, and get out of the tent.

I would be lying if I told you I wasn’t concerned.

A Mojolicious non-blocking web service: why?

created_at=2014-01-07T00:00:00

Let’s take a trip to the land of Slow APIs. The land of Slow APIs is a horrid land, filled with web services that are almost RESTish, in all ways except those that make development easy. Sometimes those APIs don’t respond, and other times, the APIs respond, but then time out before the information is given.

As I said, it’s a horrible land.

Your job, on this wonderful day, is to write an API that uses a Slow API as a backend data store, and make it capable of supporting thousands of users at a time. The catch? Each Slow API call takes 5 seconds to respond with data.


Ok, you say.

I’ll use Mojolicious, because I like rainbows and unicorns.

Good choice, for reasons we shall soon see.


Let's make a file named coolapi:

use Mojolicious::Lite;
use Mojo::UserAgent;

my $ua = Mojo::UserAgent->new;

get ‘/‘ => sub {
    my $self = shift;

    $self->render(text => $ua->get(‘http://slowapi.com/')->res->body);
};

app->start;

I’m done, you say!

Nay, you are not.

We have a problem that you have not considered. You need to support thousands of users at once, so you first need to consider how you’ll be serving these requests.

Your first thought is to run the built-in daemon:

$ perl coolapi daemon

Wow! It’s running. But wait. Make a request. Now make two, within 5 seconds.

Hmm.

The second request cannot begin until the first request has completed. Each request blocks all other requests. Why? Because daemon only runs one thread, and it can only do one thing at a time. Thousands of users at a time?

I think not.

Fine, you say. We’ll run hypnotoad, which has multiple listeners.

 $ hypnotoad coolapi

Hypnotoad runs 5 listeners by default. Now you can serve up to 5 users at a time. Whoa, 5.

Ok, so add some more workers. We’ll add a configuration file called coolapi.conf with the following configuration.

    {hypnotoad => {workers => 2000}}

And we'll tell Mojolicious to use the configuration by specifying the Config plugin:

use Mojolicious::Lite;
use Mojo::UserAgent;

plugin 'Config';

my $ua = Mojo::UserAgent->new;

get '/' => sub {
...

There! You can run up to 2000 listeners at a time! Except, you now have 2000 processes running as well. Waiting. Sometimes, doing nothing. And what if you need 2001? 5000? Are you really prepared to run 10000 processes? I can tell you right now, you’re not. You don’t want to go down that road. It’s dark, much darker than even the citizens in the land of Slow APIs could fathom.

Your shoulders slump, crestfallen. Hope is dimming.

Never fear, my friend. You chose Mojolicious. And Mojolicious has thus saved you with its forethought and shininess.

Behold, we are about to enter the realm of non-blocking web services. It’s a magic realm, filled with mystery and wonder. But there will be no more mystery. Today, as you enter, you will understand, as clear as day, and never write a blocking web service again.

Behold. The strong, colorful, right arm of Mojolicious will save you on this day. And you will fall down in deference in awe of Mojolicious, the non-blocking next generation framework. A double, nay, a triple rainbow will shine grace upon you.

Let’s take a step back, and consider the problem: each process can only do one thing at a time. But it doesn’t have to be this way. We can defer each request, and let Mojolicious handle the processing of it while it remains ready to answer other requests.

Even better, it isn’t difficult. It’s not difficult at all.

Let’s use Mojo::UserAgent in a slightly different way.

$ua->get(‘http://slowapi.com/' => sub {
    my ($ua, $tx) = @_;  
    $self->render(body => $tx->res->body);
});

Passing a callback into the get method will let Mojolicious know that you're intending to make a non-blocking call. When the request returns, whether 5 seconds, or 5 minutes, the render will be called. And because Mojolicious is handling this in the background, the process can still listen for new requests.

Oh snap, you say.

Yes. Oh snap.

How many requests can this support? More. A lot more. As fast as Mojolicious can respond, that’s how many concurrent requests that can be handled.

This is what you want. This is how you want to write your web services. Though the land of Slow API is dark, you can still achieve a long-standing peace.

From now on. No more blocking. Ever.

use Mojolicious::Lite;
use Mojo::UserAgent;

my $ua = Mojo::UserAgent->new;

get ‘/‘ => sub {
    my $self = shift;

    $ua->get(‘http://slowapi.com/' => sub {
        my ($ua, $tx) = @_;  
        $self->render(text => $tx->res->body);
    });
}

app->start;

This post is listed on the Perl Ironman RSS and Atom feeds

Tempire is on Twitter

Testing your Mojo with Test::Mojo

created_at=2011-02-09T05:54:00

Update Mojo::Client has been replaced with Mojo::UserAgent.

They say programmers don't like to test.

It seems to me that the folks who say that aren't programmers. If they are, they've never been the sole responsible party for any application. When there's no one to pass the blame to, TDD is no longer just an idea, it's time & money.

Once you get the hang of it, the peace of knowing that your code works has a value beyond measurement.

It's for this reason Mojolicious makes it easy to test your web apps in a clean, simple manner.

<script src="https://gist.github.com/817976.js?file=gistfile1.pl"></script>

Now that's easy. But there's more.

Test::Mojo tests are chainable, so you can keep your tests in a clean group:

<script src="https://gist.github.com/817981.js?file=gistfile1.pl"></script>

Now that's pretty. But wait, there's more.

Using Mojolicious' built in JSON parser, you can test JSON output using an equivalent decoded Perl structure:

<script src="https://gist.github.com/817985.js?file=gistfile1.pl"></script>

On a side note, Mojo::JSON is the fastest pure-perl JSON parser available. Thanks to chansen, it recently became even faster, outperforming JSON::PP by 3x.

But wait, there's more.

Test::Mojo methods have exactly the same syntax as their corresponding Mojo::Client methods, sharing much of the same code.

For example, with Mojo::Client, you would write:

<script src="https://gist.github.com/817988.js?file=gistfile1.pl"></script>

Testing the route would be nearly the same thing - Just add the _ok suffix, and you're good to go:

<script src="https://gist.github.com/817998.js?file=gistfile1.pl"></script>

As a matter of fact, testing with all the HTTP methods have the same naming scheme:

<script src="https://gist.github.com/818019.js?file=gistfile1.pl"></script>

But wait, there's more.

Much like Mojo::Client, Test::Mojo automatically stores cookies for you, so you can test cookie-based web apps without any extra code.

When you need to drop existing cookies, you can reset the session:

<script src="https://gist.github.com/818000.js?file=gistfile1.pl"></script>

Sometimes, it's necessary to break free and do your own thing. You can access the most recent transaction using the ->tx accessor:

<script src="https://gist.github.com/818001.js?file=gistfile1.pl"></script>

Installing is one-step easy, and takes about a minute:

curl -L cpanmin.us | perl - Mojolicious

One more thing...

Since Test::Mojo is based Mojo::Client, you can debug your tests by printing the HTTP request/response to stderr using an environment variable:

MOJO_CLIENT_DEBUG=1 prove t/webapp.t

You've got the idea. Now go test your web apps!

Test::Mojo docs

Mojocast #4: Stash, Flash, and Sessions

created_at=2011-11-14T15:15:00

It's Mojocast Monday, kids, which means a brand new Mojocast for your perusing pleasure.

Continuing to demonstrate Mojolicious::Lite, the Mojocasts are moving through Mojolicious basics, so newcomers can get up and running more quickly than ever (And dare I say it, have fun at the same time. gasp).

As the screencasts continue, you can bet your sweet ponycorn we'll be covering some of the more cutting-edge features, such as web-sockets and event-driven web apps.

For now, however, we have another installment to make sure those old and new can get started quickly with Perl web development, without a lot of fuss.

Mojocast #4: Stash, Flash, and Sessions

Keep in mind - the shortcuts link to specific times in the screencast, so you can share/bookmark specific topics.

Thank you to @kure_ji_neko and elb0w for agreeing to host the Mojocast video files. We can all feel that much more hip by using HTML5 video instead of flash.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.