Wednesday, October 13, 2010

Recipe: Whole Wheat Pizza Dough

  • 1 cup warm water
  • 1 tablespoon honey
  • 2 teaspoons yeast (quick rise)
  • 3 cups whole wheat flour (the finer the flour, the more elastic the dough is. Use less water or oil as necessary)
  • 1/4 cup ground flax
  • 6-8 teaspoons olive oil
  1. Pour warm water into a bowl, stir in honey until it dissolves. Add yeast.
  2. In a mixing bowl, mix flour and flax. Add oil and break up lumps.
  3. Add yeast solution to flour/flax bowl. Mix and knead until you have a ball of dough.
  4. Coat ball of dough in a thin layer of oil and cover (with something like tinfoil) for at least 10 minutes.
  5. Roll out dough and build your pizza.
A ball yields enough dough for a 15" pizza.

Update (November 9, 2012): In step two, I have lately made a hole in the center of the flour/flax mixture and poured in the eight teaspoons of oil, mixing with the walls of flour until firm enough to hold my spoon. In step 3, when the yeast is ready I pour it into the hole and continue mixing in from the walls of dough until it is too hard to mix with the spoon. I do this because it's fun.

Saturday, August 14, 2010

Using triggers to automatically set created and updated date fields in a mysql table

So your application uses a mysql database and you want to keep track of when rows were created and updated. You add a created and updated column and then redo all your insert and update queries: setting created and updated to now() for inserts, and setting updated to now() for updates. Commit the code, test, fix the spots where you spelled created craeted, test, commit, wash, rinse, guh. Oh, now you want to do this with the other dozen tables in your application. If only mysql could just do this for you. Well, obviously it can otherwise I wouldn't be writing this.


I'm going to create a new table to show how to use triggers to achieve the goal of automatically time-stamping your rows on inserts and updates. Imagine if you will that the table looks something like the following:
mysql> create table demo (
-> id int(10) unsigned not null auto_increment,
-> test varchar(20) collate utf8_unicode_ci not null,
-> created datetime not null default '2000-01-01 00:00:00',
-> updated datetime not null default '2000-01-01 00:00:00',
-> primary key (id)
-> ) engine=innodb auto_increment=1 default charset=utf8 collate=utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)

mysql> describe demo;
| Field | Type | Null | Key | Default | Extra |
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| test | varchar(20) | NO | | NULL | |
| created | datetime | NO | | 2000-01-01 00:00:00 | |
| updated | datetime | NO | | 2000-01-01 00:00:00 | |
4 rows in set (0.00 sec)

The default value I selected for the created and update columns is Y2K as this should be a pretty unreasonable date for any of your current and future updates. In theory should something break, mysql will use this default date and you'll be able to pick them out with ease. The created and updated columns don't need to prevent nulls for this to work, I chose this option as there is no conceivable reason for these columns to not be populated. I want an insert trigger and an update trigger so I use create trigger to make both ins_setdates and upd_setdates:
mysql> create trigger ins_setdates before insert on demo
-> for each row set new.created=now(), new.updated=now();
Query OK, 0 rows affected (0.01 sec)

mysql> create trigger upd_setdates before update on demo
-> for each row set new.created=old.created, new.updated=now();
Query OK, 0 rows affected (0.01 sec)

mysql> show triggers;
+--------------+--------+-------+------------------------------------------------+--------+- :
| Trigger | Event | Table | Statement | Timing | :
| ins_setdates | INSERT | demo | set new.created=now(), new.updated=now() | BEFORE | >8
| upd_setdates | UPDATE | demo | set new.created=old.created, new.updated=now() | BEFORE | :
+--------------+--------+-------+------------------------------------------------+--------+- :
2 rows in set (0.00 sec)

(Note that the show triggers result was truncated as the table was 197 characters long and described the character sets (utf8) and collations (utf8_unicode_ci) and the pre would have splooged over everything)

The insert trigger, ins_setdates sets demo.created to now() and demo.updated to now() when you insert a row. The new prefix on new.created and new.updated tells mysql to set the new value of these fields.

The update trigger, upd_setdates sets demo.created to the value that it previously held (old.updated), and demo.updated to now().

Let us now see them in action. First we will insert a few rows. Note that I am not specifying values for either created or updated (or id, as this is an auto_increment field). This will be of serious use to you if you are adding these columns to an existing table and do not want your existing queries to break.
mysql> insert into demo set test='this is a test';
Query OK, 1 row affected (0.00 sec)

mysql> insert into demo set test='that is not a moon';
Query OK, 1 row affected (0.00 sec)

mysql> insert into demo set test='1234567890';
Query OK, 1 row affected (0.00 sec)

mysql> select * from demo;
| id | test | created | updated |
| 1 | this is a test | 2010-08-14 05:17:29 | 2010-14-08 05:17:29 |
| 2 | that is not a moon | 2010-08-14 05:17:40 | 2010-14-08 05:17:40 |
| 3 | 1234567890 | 2010-08-14 05:17:51 | 2010-14-08 05:17:51 |
3 rows in set (0.00 sec)

So each row was inserted with the current date and time. On the insert, I have chosen to put a time in for updated as (IMHO) an insert of data is the last time it was updated. Since updated == created, you know there have been no further updates since the insert. You could chose to insert a null (or have the default value null). Whatever, as long as you can tell from looking whether there have been updates. Both these fields currently show the time the row was inserted as expected based on the insert trigger.

Now let's update the data. It looks like I entered an incorrect quote, so I will update that:
mysql> update demo set test='that\'s no moon' where id=2;
Query OK, 1 row affected (0.08 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from demo;
| id | test | created | updated |
| 1 | this is a test | 2010-08-14 05:17:29 | 2010-08-14 05:17:29 |
| 2 | that's no moon | 2010-08-14 05:17:40 | 2010-08-14 05:18:13 |
| 3 | 1234567890 | 2010-08-14 05:17:51 | 2010-08-14 05:17:51 |
3 rows in set (0.00 sec)

As you can see, the update query updated not only the test field as I asked it to, but the trigger also set updated to the current date and time. The created field remained the same as before (check above if you don't believe me) as we didn't just create this row.

Now, let's say it's really important for my application to always know that the created field is and will always be the real time the row was created (say to prove I got my high score before you did). We would never want this field to change ever. If you remember the update trigger, it set the value of created to whatever was there before the update. So if we try to change created to April Fools day, our change won't happen (but updated will update -- so there is now a record that someone attempted an update):
mysql> update demo set created='2010-04-01 0:00' where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from demo;
| id | test | created | updated |
| 1 | this is a test | 2010-08-14 05:17:29 | 2010-08-14 05:18:55 |
| 2 | that's no moon | 2010-08-14 05:17:40 | 2010-08-14 05:18:13 |
| 3 | 1234567890 | 2010-08-14 05:17:51 | 2010-08-14 05:17:51 |
3 rows in set (0.00 sec)



Triggers can get much more involved and complicated than this, but will (could) benefit your code by making it less involved and complicated. Your results may vary, but give them a try and have fun.

Wednesday, July 28, 2010

The game for which the object is to concoct an expansive set of words placed together to form identical context and meaning to an originally terse and uninteresting different yet smaller set of words that may have actually been a very well thought out and efficient communication.

That's the name of this game that I invented on the train. It probably already exists and probably also already has a boring name. That won't stop me from advertising it to you here and now.

The game is simple: take a simple sentence and attempt to re-write it in a manner that is ridiculously and unnecessarily obtusely verbose while maintaining the context and meaning of the original sentence. A good rewrite will be much more interesting or funny or entertaining than the original sentence.

Here are the base rules, designed to prevent exploiting the game in ways that are not fun. It goes without saying that these rules don't apply if the original sentence contains content that the rule aims to prevent (if this is the case you should probably pick another starting sentence):

  • No recursion or infinity scenarios: "I looked up at the stars and wondered if there was a spaceman near the star who was sitting there and looked up at the stars and wondered if there was a spaceman near the star who was sitting there and looked up at the stars and wondered if there was a spaceman near the star who..." Zzzzzzzzzzz.
  • No repetition: Referencing a character each time with the same descriptive text, "the tall dark-haired comedic ex-baseball player turned bar owner" is boring. Think of other ways to say it--you shouldn't be able to use a find and replace algorithm to change these references back to "Sam."
  • No enumeration (lists). If you take the original sentence "I went to the beach" and then try to list every step and turn you took to get there you have broken this rule: "I opened the door and stepped outside and closed the door and locked the door and stepped off the porch and walked down the driveway and put the car key in the lock and..." SNORE. You can break this rule only if you figure out how to make a list entertain the reader.

These rules boil down to a single rule: The new sentence must be interesting.

In addition to the base rules, I have come up with some guides in order to make attempts more difficult:

  • EASY: Commas, periods, exclamation points, semicolons, question marks, quotation marks, and parenthesis that occur in the original sentence will appear in the same (relative) position in the final sentence, with no additional marks. If the original sentence has a single comma to indicate a spot to take a breath, so must your re-write. You cannot add these punctuation marks for the purposes of extending your sentence (I think this should be a base rule).
  • MEDIUM: Along with the easy guideline: you are forbidden from using a thesaurus for the purposes of finding longer words. Think of this like the rule in that popular trademarked crossword-based game with wooden letter tiles and triple word scores where you can't use the dictionary to figure out if you can spell a word with your tiles Q, Z, J, L, X, U, and B.
  • HARD: Along with the easy and medium guidelines: you cannot use hyphens to string words together and you cannot use more than three logical operators (and, or, not) in the entire text (excluding original occurrences).

I suspect there is a proportional relationship between the amount of verbosity and the sentence's comedic properties.

Here are some examples. Please feel free to generate your own pompous flowery run-on sentences based on these examples, or start with a new simple sentence. The choice is up to you my friend.

Original: Dog bites man.

Canine devours hominid.

Ancient lupine descendent consumes by method of oral pre-emptive strike post-industrial bipedal big-brained chimpanzee cousin.

Original: "Hello, how are you?"

Good morrow to you my exquisitely presented gentle-sir or -madam, in this modern age of post-industrial high-technology society how do you find your worldview rewarding you?

Original: "I'm going to buy a pack of smokes."

"I am going to the store to buy a package of cigarettes."

"In a moment slightly in the future from the present the speaker of this sentence will transport to a location of commerce upon which said agent will enter into a market transaction involving the trade of government-issued denominations of currency that was earned in exchange for the scarce resource of time used in an effort to construct a modest facility for post-industrial bipedal large-brained chimpanzee cousins to engage in modern war-time battle simulators in the grand pursuit of leisure with a single container of twenty or twenty five cylindrical devices specifically designed and manufactured for the purposes of delivering an addictive narcotic by method of ignition and inhalation of the incomplete combustion into the lungs when it then enters into the blood stream where this highly potentially fatal intoxicant will travel throughout the host body and react with devices in the brain that will calm and relax and provide the drug's user with an opportunity to appear cool."

Saturday, July 10, 2010


$hurrr = "derp\n";
echo $hurrr;