Django template philosophyOct 15 2012 | 09:56:03 | 1 Comment

Django template philosophy shares quite a bit with Chunk.  I just came across this nugget on the Django website where they describe the design decisions that went into their templating framework:

Separate logic from presentation

We see a template system as a tool that controls presentation and presentation-related logic – and that’s it. The template system shouldn’t support functionality that goes beyond this basic goal.

If we wanted to put everything in templates, we’d be using PHP. Been there, done that, wised up.

Couldn’t agree more.

Discourage redundancy

The majority of dynamic Web sites use some sort of common sitewide design – a common header, footer, navigation bar, etc. The Django template system should make it easy to store those elements in a single place, eliminating duplicate code.

This is the philosophy behind template inheritance.

Agreed.  Chunk gets this done with “exec” and “include” but, same idea.

Be decoupled from HTML

The template system shouldn’t be designed so that it only outputs HTML. It should be equally good at generating other text-based formats, or just plain text.

Absolutely.  I use Chunk all the time for templating plain-text e-mail, JSON, CSV, config files, XML etc.

XML should not be used for template languages

Using an XML engine to parse templates introduces a whole new world of human error in editing templates – and incurs an unacceptable level of overhead in template processing.

I think this is a dig at XSLT and funny XML-based templating solutions like Thymeleaf.  I never understood the appeal of these either.

Assume designer competence

The template system shouldn’t be designed so that templates necessarily are displayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe of a limitation and wouldn’t allow the syntax to be as nice as it is. Django expects template authors are comfortable editing HTML directly.

Hear hear.  Chunk keeps both options open, however.  A file full of snippets probably won’t open in DreamWeaver but if you stay away from snippets and define one template per file, you should be able to use just about any HTML Editor out there.

Treat whitespace obviously

The template system shouldn’t do magic things with whitespace. If a template includes whitespace, the system should treat the whitespace as it treats text – just display it. Any whitespace that’s not in a template tag should be displayed.

Okay, so here I disagree.  If you don’t do some “smart” handling of whitespace, your template gets contorted and unreadable when you actually do care about the whitespace in the final output.

Don’t invent a programming language

The template system intentionally doesn’t allow the following:

  • Assignment to variables
  • Advanced logic

The goal is not to invent a programming language. The goal is to offer just enough programming-esque functionality, such as branching and looping, that is essential for making presentation-related decisions.

The Django template system recognizes that templates are most often written by designers, not programmers, and therefore should not assume Python knowledge.

Wow.  Couldn’t have put it better myself.  This is what Chunk is all about.  If you want to write code in your templates, go use PHP or JSP.  Knock yourself out.  But man, your templates are ugly and your whole team is going to suffer headaches from looking cross-eyed at your mishmosh code.

Safety and security

The template system, out of the box, should forbid the inclusion of malicious code – such as commands that delete database records.

This is another reason the template system doesn’t allow arbitrary Python code.

Bingo.

Extensibility

The template system should recognize that advanced template authors may want to extend its technology.

This is the philosophy behind custom template tags and filters.

Chunk is similarly extensible: write your own filters, make your own tag-command protocols.

Sugar in the morningMar 29 2012 | 12:48:46 | No Comments

I’m a concerned parent. I care about what my kids eat. I don’t want my kids to develop an unhealthy relationship with food.  I don’t want my kids to become part of the childhood obesity epidemic (unlikely given both their parents have super-high metabolism but still).  We have gotten used to half juice half water (news flash: drinking lots of “healthy” juice — while slightly better than soda — is not too different from mainlining pixy stix!). Undiluted juice now seems unbearably sweet – how did we ever drink it straight?

But kids are kids.  They gravitate toward the sweetest option available every morning.  When the choices are Kix (3g sugar), Chex (2g sugar) and Cheerios (1g sugar), they eat the Kix.  When the choices expand to include Maple & Brown Sugar Quaker Oatmeal (12g sugar), they pick the oatmeal almost every time.

So I’ve taken to removing a heaping spoonful of sugar from the packet every morning.  It’s kind of a pain, so when Quaker changed the recipe and reduced the sugar by 25% I was pretty stoked.  I tried it, it tasted fine.  My kids noticed it was different but did not care one iota.  If anything, I think they liked it better.  I stopped buying the store brand since it still has the old super-sugary formula.

Then came the backlash.  Someone actually made a facebook page pleading with Quaker to change it back.  Stories upon stories poured forth, stories of people disgusted with the new formula, forced to throw out these vile, not-as-sweet packets. Quaker was accused of elitist socialism. And Quaker is forced to acknowledge that it has made a mistake of “new coke” proportions (ironic since new coke actually had more sugar), and they restore their “classic recipe.”

So, I’m back to spooning out chunks of sugar from the packets.  And wondering why they can’t use the shelf space currently filled with “Dinosaur Egg” oatmeal (the eggs are little nuggets of solid sugar) to stock the reduced sugar boxes alongside the classic recipe.

No, let’s ruin our health and bankrupt the country treating early onset diabetes. Let’s drag everyone else in America down into this pit with us.

Yay!

What a difference a day makesDec 07 2011 | 12:25:19 | No Comments

Monday morning:

Mo wakes up crying because he has (again) peed the bed.  Mom showers him, finds him some new clothes, lets him go back to sleep in guest bed.  Mom off to work.

A minute later, Oscar wakes up crying with a bloody nose, even though we ran the humidifier in their room all night.  For some reason the heat vent in their bedroom blasts 3x harder than any other room in the house, even with the vent closed.

Collect pee sheets from Mo’s bed.  Leave Oscar’s blood-stained sheets in place (hey, it kind of matches the stain on the other side now).  Realize Mo (kindergarten) needs white T-shirts for class project.  Thinking, there’s still time to hit Target on the way to school.  Try to get Mo out of bed. Already past his normal alarm time, but, won’t get up. Mo pulls sheet over head and starts kicking and screaming.  Oscar announces he doesn’t want to go to school today.

Carry Mo downstairs (still kicking and fussing) to eat breakfast.  While waiting for Moses to simmer down, I pack their lunches.  Oscar announces he doesn’t want his leftover mac and cheese for lunch today.  He wants me to make him a sandwich instead.  I tell him there’s no time and he’s going to love the mac and cheese.  He punches his lunchbox in anger and earns a time out.

Moses is still doing a pretty good impression of a zombie having a seizure.  Lots of moaning and body twisting.  Won’t tell me what’s bothering him, much less what he wants for breakfast.  Oscar announces he doesn’t want the jacket I picked out for him.  He wants his blue “Target” jacket with the number ’37’ on the front which is, of course, nowhere to be found. I tell him I don’t know where it is, he has to wear this one or pick something else.  He gets angry, I WANT MY BLUE TARGET JACKET!

So I get angry right back, I DON’T HAVE THAT JACKET, STOP SAYING NO TO EVERYTHING AND STOP ASKING ME FOR THINGS YOU KNOW I DON’T HAVE! And I immediately want to rewind and do that over without the yelling but it’s too late.  He tries to hold back the tears for a couple seconds and then slumps to the floor with a betrayed look and a pair of very leaky eyes.

Fast forward to Target parking lot.  Oscar insists on standing inside the cart, Mo (almost 2 years older than Oscar) wants to be in the child seat.  Fine, everyone’s situated. I whip the cart around (yes, way too fast) to head into the store and Oscar promptly loses his balance and splits his lip open as his face mashes into the side of the cart.  So we zoom into the Target bathroom, me and my bleeding, screaming child, and I’m realizing the parent-of-the-year award has just slipped out of reach.  But, white T-shirts in hand, we make it to school just as the bell rings.

Tuesday morning:

Everyone wakes up happy and ready to face the day.  No tantrums.  No impossible demands.  Breakfast is tackled early and with gusto.  Plenty of time to finish Mo’s homework together, read some books, get in the car early and walk the kids into daycare (Oscar) and up to the schoolyard (Mo).

Praying for less Mondays and more Tuesdays.

Chunk: yet another Java Template EngineJan 01 2011 | 14:24:17 | 5 Comments

Simple, powerful templates for Java

Simple, powerful templates for Java

Q: Does the Java community really need yet another templating engine?

A: Not really, but back when I started Chunk, there wasn’t anything else out there like it. Now that it has matured, I am releasing it into the wild, and if somebody finds it useful, great!

Click below for an introduction to better code/layout separation:

http://www.x5software.com/chunk/

Features:

  • Macros, Includes and Conditional Includes.
  • Flexible null-handling; template designer may specify default tag values.
  • Library of powerful predefined in-tag filters, including regex (regular expressions), sprintf.
  • Expose a subset of obj methods to template with a single line of code.
  • Define multiple snippets per template file.
  • Support for theme layers with inheritance.
  • Highly optimized codebase.
  • Hooks for extending.
  • Localization framework.
  • Eclipse Template Editor plugin available with syntax highlighting & more.

Visit the Chunk project home on Google Code to download the Chunk Templates jar and get started.

I don’t know if Chunk is better than Velocity, I don’t know if Chunk is better than FreeMarker, but I’ve been using it for years and it’s gotten pretty cool.

Hackers are encouraged to contribute enhancements back to the community.  Google is hosting the code on its SVN server so it’s easy to check out a copy of the source and make whatever improvements you need.

Fix or extend core Magento in an upgrade-safe wayNov 20 2010 | 09:22:03 | No Comments

Ah, open source.  The Magento core codebase, layouts and templates are right there, warts and all, just daring you to give in to temptation and ignore the “do not edit this file!” warning at the top of each distributed file.  We all know the guilty pleasure of instant gratification that comes with tweaking a word, or a layout, or a core class directly in the source and seeing our fix immediately on the site.  It seems especially rewarding after the hour or two it took just to hunt down the right cog in The Machine.  And really, who has time to learn entire frameworks and build a module, just to tweak the way a breadcrumb gets output?

But then it’s 500 (or 5,000!) lines of “little tweaks” later and you need to upgrade.  And you’re screwed.  And a couple extra xml files and a separate tree of folders and files doesn’t seem like such a bad idea anymore.

Well, okay, time to roll up your sleeves and learn this durn extension framework that the brainiacs at Varien/Magento have so lovingly constructed.

Layouts and Templates and Blocks, Oh My

classyllama.com has a great article on how to modify one or two things in a core layout without (1) modifying it directly in core or (2) having to make a copy of the whole layout file into your theme just to tweak one line:

http://classyllama.com/development/magento-development/the-better-way-to-modify-magento-layout/

Now that I understand this layout stuff, I’m doing a lot less messing around directly in theme templates.  By the way, if you are editing the factory-supplied Magento templates and layouts directly, for shame!  Set up a theme and make all your changes in the theme.

Update: another great article on navigating the Magento layout framework:
http://alanstorm.com/layouts_blocks_and_templates

OO PHP?  Isn’t that like oil and water?

The article linked below offers a lucid explanation of how to roll your own modules that extend the core Model, Controller, Resource, and Block classes (it’s a little different for each case) to override the core behavior in Magento. Not for beginners, you really need to have a handle on OO programming. Again, this is cool because you don’t have to edit a core file directly (where changes will get blown away in an upgrade) and you don’t have to copy the whole file just to tweak one function. The latter strategy prevents you from reaping the benefits of any bugfixes or new features in that file in the next upgrade, and could even cause serious problems/bugs as your copy gets out of sync with the core codebase.

http://prattski.com/2010/06/24/magento-overriding-core-files-blocks-models-resources-controllers/

For some reason that comprehensive article does not include instructions for overriding a function in a helper class (yet another special case). This article has an example for that:

http://blog.chapagain.com.np/magento-block-controller-model-helper-override/

Happy coding!

CSS Sucks (or, center this, microsoft)Aug 30 2010 | 09:20:01 | No Comments

CSS SucksCSS officially needs to be replaced. Centering a dropdown menu should NOT be this hard:

http://matthewjamestaylor.com/blog/centered-dropdown-menus

Thank goodness I found that article or I would still be pulling my hair out.

In my day, used to be you could stick this in one or two tables and you were done. We didn’t have no stinkin’ separation of content and layout and we liked it.

Calling Magento SOAP API from Perl with SOAP::LiteAug 02 2010 | 13:11:40 | 3 Comments

We had a legacy order fulfillment library written in Perl, so although accessing the API is extremely easy in PHP, when we migrated to Magento I had to figure out how to connect to the SOAP API from Perl.

Turns out the most popular CPAN module for doing SOAP in Perl (SOAP::Lite) is not particularly fun to use (see “State of the SOAP” at http://www.soaplite.com/ for a three-year-old call for volunteers to refactor).

Nevertheless, I did eventually emerge victorious. There may be a much easier way but after a lot of head-scratching and trial and error, this worked for me, YMMV.

The soapify routine was stolen from this page:
http://www.soaplite.com/2004/01/building_an_arr.html
Many thanks to soapify author Sandeep Satavlekar.

For passing the filter args to sales_order.list, I had to make the call in PHP first and then reverse-engineer the encoding of the nested array that actually got passed. There may be a way to get SOAP::Lite to encode nested arrays like this by default (or encode nested arrays in some other standard SOAPy way that Magento would also accept) but I chose not to waste any more time on this than I already had.

Enjoy!

UPDATE: Was getting sporadic “Access Denied” errors. Turns out you can fix this just by turning on cookies. Apparently this only affects you if Magento is using DB sessions. See new get_soap_session below for how to turn on cookies.

UPDATE TO THE UPDATE: Nah, that didn’t fix it. Still searching for a fix… runs fine in a session, fails about 80% of the time from cron.

The complete working example script is after the jump...


#!/usr/bin/perl

# replace these values with the soap account you set up in the admin
my $user = 'username';
my $pass = 'password';

# replace with your domain and path (we installed magento at /shop/)
my $soap_url = 'http://YOURDOMAIN/MAGENTO_PATH/index.php/api/index/index/';

my ($soap,$session_id) = &get_soap_session($user,$pass,$soap_url);

# simple example (one arg of type string)
my $oid = '1000001';
my $order = &get_order($soap,$session_id,$oid);

# gnarly example (argument is nested arrays)
my $orders = &get_recent_invoiced_orders($soap,$session_id);

foreach my $ord (@$orders) {
    my $due = $ord->{grand_total};
    my $paid_or_authorized = $ord->{total_invoiced};
    my $owed = $due - $paid_or_authorized;
    # ignore if not yet paid
    next if ($owed > .02);
    &fulfill_order($ord);
}

exit 0;
Continue reading »

Customizing MagentoJul 08 2010 | 15:07:35 | No Comments

Quick start – here are some pages that helped me get going quickly:


Defining your own attributes is easy.  Getting them to display in a template is not.  Cheat sheet:

http://www.sharpdotinc.com/mdost/2009/04/06/magento-getting-product-attributes-values-and-labels/


Don’t hack the Magento tree directly!  You’ll be sad when you upgrade and your customizations are gone. Do this instead:

http://www.exploremagento.com/magento/override-a-magento-core-block-class.php


Grab all the simple child products for a configurable product (and then display one of their other custom attributes):

http://snippi.net/taxonomy/term/10


Updating stock through the SOAP API is unbelievably slow.  The API doesn’t appear to accept more than one SKU per call! Use a script like this instead:

http://www.sonassi.com/knowledge-base/magento-knowledge-base/mass-update-stock-levels-in-magento-fast/


Some hints on how to get Magento to generate plain-text email:

http://www.magentocommerce.com/boards/viewthread/43928/


Kicking off an index process from the command line (using a custom script):

http://www.sonassi.com/knowledge-base/magento-knowledge-base/catalog-search-index-refresh-running-slow-or-haltingfreezing/


Finding Y-Wing (aka XY-Wing)Apr 08 2010 | 17:24:50 | No Comments

Y-Wing Fighter: the force is strong with this one.

Y-Wing can be a very handy shortcut in a tough sudoku puzzle and it may even be the only way forward in some harder ones. It’s named after an ugly rebel fighter craft from the Star Wars movies.  True to its namesake, it is not as elegant or as powerful as its X-Wing brother, but it can still do some damage.

Y-Wing can be hard to spot, so today I’ll describe a method for quickly teasing out the best ones. It boils down to this — the best Y-Wing sets are the ones where two of the three squares in the set are in the same 3×3 box!

Really, don’t bother looking for a set that’s super spread-out. It’s very rare that you’ll find one and even if you do, it’s the weakest kind: you’ll only be able to remove one candidate from one square, and that’s if you’re lucky.

Y-What?

First, let’s make sure we all know what we’re looking for. The basic idea is, you find three squares that each have two remaining candidates. The “pivot” square can see both of the end squares.  All three squares share candidates from a pool of just three total numbers, ABC. So one end of the “V” is AB, the pivot has BC, and the other end is AC.

Important detail – no two squares in the set have the same pair of candidates.  So, if you whittle down three squares to 78, 48 and 47, you’re well on your way to a Y-Wing.  If you’re looking at 47, 48 and 47, no deal.

How to spot Y-Wing / XY-Wing

How to spot Y-Wing / XY-Wing

Any square that can see both ends of the Y-Wing may eliminate candidate A from its own candidate pool. It’s an easy proof, just look at the pivot — when the puzzle is done, the pivot will either be B or C.

If the pivot is B, then the first end is not B, and must be A. In the other “reality,” if pivot is C, then the other end is not C, and must be A. Since the pivot must be either B or C, at least one of those end squares will have A.  Here’s the neat part: squares that can “see” both end squares can never be A; not in the first case, and not in the second case (and there are only two cases total).

The Claw

Some people like to think of Y-Wing as a claw.  A simple way to visualize it is, the claw’s pincers (end squares) “pinch” candidate A out of any square they can both see.  The pivot is the “hinge” of the claw.

There are two kinds of Y-Wing. One can be very helpful, and one is usually not. If the three squares in your Y-Wing are all in different boxes, you’ve found the less useful Y-Wing variant (your claw is wide open, pincers at 90 degrees).  Only one square can see both pincers – so even if we are lucky, we can only eliminate/pinch one candidate from one square.

The kind I like is when one claw pincer and the pivot share a box. Then you’ll always have more than one “pinchable” square (up to five, in fact). Fortunately, finding this second type is easier anyway.

The Method

Look at each group of 9 squares (the nine large 3×3 boxes).  In each big box, look for two squares in that box with only two candidates left each. They must share exactly one candidate.  It’s okay if they are in the same row/column but you’ll cast a wider net for the other claw if they aren’t. Found a pair like this? Good. Now look at the two candidates they don’t have in common. Let’s call them AB.  We are looking for a third square, from a different box, that has only AB left in its candidate pool. It must be able to “see” one of our original squares (yep, either one).  The square that it sees from our original box becomes the pivot.

So, we really just scan four potential zones outside our box:

• the squares in the same row as square 1

• the squares in the same row as square 2

• the squares in the same column as square 1, and finally,

• the squares in the same column as square 2

Didn’t pan out?  Move along, find another potential pivot/claw pair, maybe in this box or probably the next.  You’d be surprised how often you can track down a set of three once you focus your search like this.  See if you can find the Y-Wing below.  hint: start in box 7.

Y-Wing Example

Y-Wing Example

Continue reading »

Fishy SudokuMar 29 2010 | 10:05:23 | No Comments

Fishy Sudoku

Fishy Sudoku: Challenging puzzles. Great Interface.

Well, it’s about time I came clean.  I am a Sudoku addict.  I do two fairly difficult puzzles a day, at a site that offers free daily puzzles.  I’m getting a little tired of the puzzles on that site because they tend to block forward progress until you find one or two X-Wing sets and then you’re done.  A bit predictable after a while, and once you get good at spotting X-Wing it gets kinda boring.

So about a year ago I started making my own puzzles.  I wrote a java program that generates random puzzles, and another java program that solves the puzzles by applying various techniques in a loop, in order of difficulty.  The second program rates the puzzles made by the first program.  I wrote a third program that lets the first two programs fight it out until they come up with a tough puzzle.

Hard puzzles should have one or two X-Wing sets.  Really hard puzzles, in my opinion, need an XY-Wing or a swordfish or even a jellyfish.  Thus the name of my new daily puzzle website, www.fishysudoku.com.

I put together a nice little sudoku puzzle interface in Flash.  It addresses all the things I found really annoying about other online sudoku sites.  First of all, the pencilmarks come up automatically.  My wife insists that Sudoku is a big waste of time, and she’s right, to an extent.  The interesting parts of solving a sudoku puzzle tend to just punctuate long stretches of tedium. God forbid you make a mistake during the pencil-mark tedium.  Anyone who has tried Sudoku has made a mistake at some point that went undiscovered for the better part of an hour.  This is not a rewarding feeling.

So in my interface, autohelp is on by default.  Glaring mistakes are immediately circled until they are fixed.  Obvious pencilmarks are done for you.  But most interfaces that do this prevent additional edits to the pre-determined marks.  So in my interface, you can grey out any pencilmarks that you know to be impossible.

I have plenty of features still to add — puzzle archive, access to the solver for hints & more — but I figured it was time to do an alpha launch.

To reach a broader audience, I also boxed it up as a facebook app. Add it to your facebook apps! I need at least five people to add it before I can get listed in the app directory.