OG Consulting http://og-consulting.com Leaders in Open Source Mon, 13 Jul 2009 22:30:31 +0000 en hourly 1 http://wordpress.org/?v=3.0.1 Drop Shadows and Snapshot Borders – Automating Image Manipulation http://og-consulting.com/2008/06/13/drop-shadows-and-snapshot-borders-automating-image-manipulation/ http://og-consulting.com/2008/06/13/drop-shadows-and-snapshot-borders-automating-image-manipulation/#comments Fri, 13 Jun 2008 15:04:10 +0000 admin http://www.og-consulting.com/?p=40 Many of the web projects we do have tons of images that require manipulation and processing. Although the GIMP and Adobe Photoshop are extremely powerful tools, they require a user. That would you be you, sitting in your chair, operating on images by hand with your mouse, stylus, and keyboard. You can do amazing things, but a lot of times you’re just processing over and over and over. When you want to speed things up and move on to more interesting tasks, you will turn to ImageMagick, a set of command line utilities for processing images en masse.

A nice effect that I enjoy is the "snapshotization" of digital photos.  Take a look.

Parameters I wish to adjust:

  • Rotation (arbitrary)
  • Border width and color
  • Shadow depth, transparency.
  • Background color

So what you want to do is draw a border.  ImageMagick’s "convert" has a -bordercolor and -border directives that allow you to set the color and the width.  Make sure to set -bordercolor first, because ImageMagick doesn’t parse the command line in a sane way.  It’s a small detail, but if you don’t set -bordercolor first, you’ll get gray borders every time.  Took me forever to figure out why it wasn’t working for me.

We will now rotate the image with the border.  In order to keep our image as a separate entity, i.e. with a transparent background, we need to specify -background none and then apply the -rotate directive.  Try this line without -background none to see what I’m talking about.

That’s not what we want, eh?  So remember to specify -background none first.

Next you want to use the -shadow directive in a cloned layer.  We want to create a layer in memory using the +clone directive, draw a rectangular shape under our first layer with the border, blur the layer and offset it.  The default creates a layer above our first one, which is no good, so we swap it and render it as a proper drop shadow.   See the script below for a complete example.


#!/bin/bash

BGCOLOR="#ffffff"

file="$1"

RANGE=30
number=$RANDOM
let "number %= $RANGE"
let number=$number-15

WIDTH=`identify -ping -format "%[fx:w]" "$file"`
HEIGHT=`identify -ping -format "%[fx:h]" "$file"`
STROKEWIDTH=`echo "scale=0; $WIDTH/50" | bc `
BLUR=20
SHADOW_OFFSET_X=10
SHADOW_OFFSET_Y=10
CURVATURE="0"

OUTPUT_FILE=`echo "$file" | iconv -f LATIN1 -t ASCII//TRANSLIT`
OUTPUT_FILE=`echo $OUTPUT_FILE | tr "[:upper:] " "[:lower:]_"`
echo $OUTPUT_FILE

convert -quality 90 "$file" -size ${WIDTH}x${HEIGHT} -fill none \
-background none -bordercolor "#ffffff" -border "$STROKEWIDTH" -rotate $number \
\( +clone -background black -shadow "$STROKEWIDTH"x${BLUR}+${SHADOW_OFFSET_X}+${SHADOW_OFFSET_Y} \) \
-swap 0 -background "$BGCOLOR" -layers merge +repage -resize 480x480 "${OUTPUT_FILE%.jpg}_sm.jpg"

$RANDOM is a built in random number generator which I use here to set the arbitrary rotation of the images, between -20 and +20 degrees.  It’s simple to return numbers in this range.  Take any random number, divide it by your desired range (40 in this case), and retrieve the modulo (remainder).  Then subtract half your range to get an even distribution between -20 and +20.   It’s an old trick, but it still works.

The variables $WIDTH, $HEIGHT are necessary to set the border and blur parameters.  Again, I use ImageMagick to pull in the dimensions of the image in question. 

identify -ping -format "%[fx:w]" "$file"

This will get you the width of the input file. "%[fx:w]" will get you the height. 

I set $STROKEWIDTH (for borderwidth) to be 1/50th of the image’s width.  That’s a pretty good number for what I’m doing.  Obviously, you can change that to something else.

I haven’t worked out exactly how ImageMagick’s blur works, but I set $BLUR at 20, which seems to work well (I’m not sure if it’s a pixel value or what).  I’ll post more when I figure out exactly what it’s doing and how to control it.

Now this script is not particularly pretty. It doesn’t take any parameters on the command line (except the filename), has no help, and does no input checking. This is a pretty quick hack to solve a simple problem for myself. Maybe later I’ll fancy it up a bit, optimize, and make a proper program out of it, but for now, it solves my problem.

If you want to process a directory of images, you can wrap it in the following:

ls *.jpg | while read file; do script_name "$file"; done

And that’s it.  Stupid simple, no?

]]>
http://og-consulting.com/2008/06/13/drop-shadows-and-snapshot-borders-automating-image-manipulation/feed/ 0
Mysql 4.0.x LATIN1 to Mysql 4.1.x UTF-8 Nightmares http://og-consulting.com/2007/12/02/mysql-40x-latin1-to-mysql-41x-utf-8-nightmares/ http://og-consulting.com/2007/12/02/mysql-40x-latin1-to-mysql-41x-utf-8-nightmares/#comments Mon, 03 Dec 2007 01:07:21 +0000 admin http://www.og-consulting.com/2007/12/02/mysql-40x-latin1-to-mysql-41x-utf-8-nightmares/ Whew! Finally I have accomplished what I had been putting off for a while, namely a MySQL upgrade that had been due. Here’s the problem:

­What would normally be a straightforwa­rd LATIN1 or ­ISO-8859-1 to UTF-8 character conversion turns out NOT to be. Why? Well, just because the old database character set defaulted to LATIN1, and most things were stored in LATIN1, not everything was. This very website, powered by WordPress, has been storing data as UTF-8 since forever. So we have a problem. Can you see it? The database and its data are mostly LATIN1, but some data are not.

An automated mass conversion would not be possible.

See why I had been putting it off?

The solution, if you can call it a solution, is to convert all the tables that are NOT WordPress first.

mysqldump -h localhost -u username -p --all-databases -c dbname > dump.sql

Then modify that file by cutting and pasting WordPress from the SQL file (or any other application that stores its data in UTF-8). Using vim you only have to place your cursor at the beginning of WordPress, where it says CREATE DATABASE wordpress, hit "ctrl-v" then "shift-v" and then "/" and type CREATE DATABASE. This has the result of selecting all text between the CREATE DATABASE statements. It’s extremely convenient for selecting possibly hundreds of megabytes of text. Next, hit the key "d" to delete the SQL statements pertaining to WordPress. WordPress is now stored in your buffer. You can save that file, then type "e" and a filename like "wordpress.sql". Next hit "ctrl-p" to paste what is in your buffer (possibly hundreds of megabytes of data). Exit and save. You now have two files: one called dump.sql with all of your LATIN-1 data, and another called wordpress.sql with just your WordPress stuff.

Now convert your dump.sql file to UTF-8

iconv -f ISO-8859-1 -t UTF-8 dump.sql > dump_utf8.sql

In this case, we will start with a fresh install of Mysql (so we don’t have to drop any databases). Import like this (because we used –all-databases in the dump, all the DROP and CREATE statements are included, so no need to manually create the databases):

mysql -u username --max_allowed_packet=16M -p --default-character-set=utf8 dbname < dump_utf8.sql­ ­

I assume you have backed up your old installation, just in case this whole procedure goes south.­ In my case, keyword changes between MySQL 4.0.x to MySQL 4.1.x resulted in various import errors. I have to go through the SQL dump and alter the database schemas by hand. Be advised. It was thorny, but I write this little tutorial to let you know that it is possible. I received no less than 20 different errors in my database import. I altered them one by one, wiped, and re-imported. Eventually, my database was ticking along just fine. It can be done.

Next you just have to import your wordpress.sql file as it was, and you are done.

Of course, MySQL 5.x is out and 4.1.x is screaming to be upgraded, so I’ll now have to wade knee deep into the thicket of thorns again. This exercise above, has prepared me for the pain though, I think I’ll be able to handle it.

Actually, 4.1.x to 5.x wasn’t bad.  No problems.  Just follow the standard upgrade guide.  Make sure to do a full dump and just import everything as specified.  Since we were already on UTF-8, there weren’t any gotcha on my end. 

]]>
http://og-consulting.com/2007/12/02/mysql-40x-latin1-to-mysql-41x-utf-8-nightmares/feed/ 0
Fighting the Good Fight Against Spammers http://og-consulting.com/2006/12/22/fighting-the-good-fight-against-spammers/ http://og-consulting.com/2006/12/22/fighting-the-good-fight-against-spammers/#comments Fri, 22 Dec 2006 19:06:53 +0000 admin http://www.og-consulting.com/2006/12/22/fighting-the-good-fight-against-spammers/ The holiday season is crazy enough for ordinary citizens going about their daily routine, shopping, fighting traffic, long lines, time deadlines.  Then there's the threat of credit card and identity theft.  If that's not enough, we workers in the IT world have to deal with the maleficent opportunists that seem to come out of the woodwork to ply their warez, spam, and botnets at this time of year.

Over at Altamente, I've been battling spammers and hackers constantly since the day after Thanksgiving.  Why Thanksgiving, do you ask?  I'm so glad you asked.  It's simple.  In the US, from Thanksgiving to the last shopping day before Christmas, consumers will account for roughly 17% of all retails sales. 

Spammers and hackers want their cut. 

Whether it be phishing, hacking, or spamming, they have been a constant pain in the neck. 

Imagine my surprise this morning when I noticed the email was slow.  I peeled back the carpet to find a hoard of roaches swarming about. 

Yeach. 

Tons of messages were in the outgoing queue from an anonymous user, spam messages sent by my server to unwilling recipients.  I was shocked and disgusted.  How could this have happened?   I took a deep breath, decided not to panic and calmly looked through the logs and web traffic.  I already suspected a rogue web script on some virtual host somewhere.  Let's have a look at which client has gotten a bump in server traffic recently.

And there is was, a script being used by one of Altamente's clients, wp-email.php.  Now, in all fairness to the author, he has since applied a bit of paint to his "Email Article" plugin for WordPress in the form of a Captcha.  In my case, however, I overlooked the patch and the result: spammers had been injecting an automated attack against the script to deliver their payload as if it was a normal email.

Solved!  But I'm still annoyed.  Remember people, any php or web script that allows a user to send email needs to be thoroughly checked against such variable over-writing.  All input strings must be parsed and checked.  Put up email forms at your own peril.

Or at least watch them carefully during the Holidays. 

]]>
http://og-consulting.com/2006/12/22/fighting-the-good-fight-against-spammers/feed/ 0
Multi-lingual WordPress with Apache2 and Content Negotiation via index.html.var http://og-consulting.com/2006/09/26/multi-lingual-wordpress-with-apache2-and-content-negotiation-via-indexhtmlvar/ http://og-consulting.com/2006/09/26/multi-lingual-wordpress-with-apache2-and-content-negotiation-via-indexhtmlvar/#comments Tue, 26 Sep 2006 16:32:46 +0000 admin http://www.og-consulting.com/2006/09/26/multi-lingual-wordpress-with-apache2-and-content-negotiation-via-indexhtmlvar/ That’s a mouthful, isn’t it. In short, I’m writing this little tutorial for those that need to maintain a WordPress site in more than one language. This particular setup is geared toward WordPress, but the techniques can be used for other html files and Content Management Systems.

First, use Apache’s new index.html.var file. You will find a copy in your default webroot that comes with a default Apache installation. This index.html.var file will take the place of your index.html or index.html.xx file residing in your root directory. Without getting too technical the file is just a mapping of user language requests to appropriate localized content wherever it may be.  It’s way more flexible than MultiViews.

To create a two language WordPress site, one for Spanish and one for English, I set up the two blogs on the same codebase (WordPress 2.0.4). The base URL for Spanish is /es/ and for English is /en/. I also wanted my users to be drawn from the same users table (no sense in having them register twice for the site). Place the following line your wp-config.php

define ('CUSTOM_USER_TABLE', 'YOUR_TABLE_PREFIX_users');

Where YOUR_TABLE_PREFIX is wp_ or whatever is in the variable $table_prefix for your common users table.

Also, in order that your users won’t have to log in twice in case they visit both the English and Spanish sites, we’ll have to modify the cookie paths. Basically, if you login in English then pass over to the Spanish, your login will stay valid (rather than prompting you to login again). We need to modify the wp-config.php in both directories to make sure where ever the user enters first, that login sticks.

In your es directory put the following in your wp-config.php:

define ('COOKIEPATH', '/en/');

In your en directory put the following in your wp-config.php:

$public_cookiehash = md5('http://foo.com/es');
define('USER_COOKIE', 'wordpressuser_'. $public_cookiehash);
define('PASS_COOKIE', 'wordpresspass_'. $public_cookiehash);
define ('COOKIEPATH', '/es/');

The result: if you login to the English side and then get a hankering for Spanish, your login stays valid. If you are feeling a little latino at first and then later decide to peruse some English content, your login stays valid. ¿Entienden?

Apache and Content Negotiation

Place the index.html.var file I mentioned before in your base directory / with the following mappings for my localized blogs.

URI: /en/
Content-language: en
Content-type: text/html

URI: /es/
Content-language: es
Content-type: text/html

Normally, in the default index.html.var, index.html.es maps to Spanish content, and index.html.en maps to English content. I didn’t want that, since the base directory is meaningless and empty except for index.html.var. My actual localized content is in the respective directories /es/ and /en/. I didn’t want a splash screen asking the user to choose his/her language either. The computer should comply with the user’s browser preferences. If a Spanish speaking user has their language preference configured as Spanish, Apache should very well give it to them.

You can think of index.html.var as Apache mod_rewrite specifically geared towards internationalization. Now any English-speaking request to http://foo.com/ will negotiate to http://foo.com/en/ and Spanish-speaking requests map to http://foo.com/es/

As usual, I write this because the process is so simple no one thought to spell it out quite so explicitly.

To sum up: index.html.var has replaced the MultiViews directive in Apache, is more flexible, and will help you out way more than trying to write php, mod_rewrite, or javascript to replicate the same functionality.

]]>
http://og-consulting.com/2006/09/26/multi-lingual-wordpress-with-apache2-and-content-negotiation-via-indexhtmlvar/feed/ 0
The Five Most Common Lies in Business http://og-consulting.com/2006/06/27/the-five-most-common-lies-in-business/ http://og-consulting.com/2006/06/27/the-five-most-common-lies-in-business/#comments Tue, 27 Jun 2006 22:17:55 +0000 admin http://www.og-consulting.com/2006/06/27/the-five-most-common-lies-in-business/ From an article on Fast Company

Lie: "People are our most important asset."

Truth: "People are our most worrisome and unpredictable asset. Our most important assets are really our financial assets."

How is this true? A pile of capital – so what does it do? Really, I’d like to know about this autonomous manifestation. If true, I could retire today. While I agree, people are our most worrisome and unpredictable asset, they are no doubt the most IMPORTANT asset.

Lie: "This was a rational decision."

Truth: "I wanted to do this."

Well maybe you wanted to do this because it was a rational decision. Emotional or irrational decisions in business lead to disaster.

Lie: "We judge people by their performance."

Truth: "I judge your performance based on how much I like you."

On what else can you judge them? Paul LaFontaine mentions that we keep people we like and get rid of people we don’t. This makes sense because generally people we like do a good job and people who get along with no one generally make a mess of things. Why is that so hard to understand? Is he honestly trying to say that companies get ahead by promoting suckups over performers? No, people you really like tend to be people you respect. Respect is a clear marker for a solid performer. This one’s a no brainer, Paul.

Lie: "This is business, it isn’t personal."

Truth: "Everything’s personal."

Yes, everything is personal, but those that can get past it and see the sunk cost, or eliminate the factors that really have no bearing on the problem, then we can get ahead. Look, I don’t hate you, but the fact remains, I performed $100,000 of work for which I have not been paid. That makes me mad, but I’m not taking action because I’m mad. I’m taking action because I can’t write off $100,000. I’m sorry that your company is in a bind, that your several hundred employees might be in the unemployment line next week. If you don’t pay me X% by %Y, I will file suit. It sucks, so yes, go ahead and yell. Everything is personal, but the fact that you can rise above and maintain objectivity regardless of the sob story will be the difference between your employees in unemployment or his.

Lie: "The customer comes first."

Truth: "I come first."

This is true, of course, but HOW do I come first? By staying in business and earning a profit. How do we, in fact, stay in business: By serving our customers well enough to make a profit. So who comes first again?
]]>
http://og-consulting.com/2006/06/27/the-five-most-common-lies-in-business/feed/ 4
Procedural Flash Animation in Linux http://og-consulting.com/2006/03/18/procedural-flash-animation-in-linux/ http://og-consulting.com/2006/03/18/procedural-flash-animation-in-linux/#comments Sat, 18 Mar 2006 15:06:30 +0000 admin http://www.og-consulting.com/2006/03/18/procedural-flash-animation-in-linux/ This is an introduction to creating completely non-interactive, or procedural flash animation using Linux. The beauty of this is not that you can do more, or that it's prettier, or even faster to create. The beauty lies in the power. Once an animation procedure is set, the elements can be changed simply by including new images, colors, or messages. In fact, I'm working on a simple web-form to generate the above animation by simply uploading elements and text inputs.

But first, let's get to the tutorial, shall we?

The door scene modeled in POV-ray scene description language and is typical of Old San Juan, Puerto Rico Spanish Colonial architecture. The real doors are beautiful. If you ever get a chance to take a cruise from/to Puerto Rico, don't miss the chance to walk around Old San Juan (El Viejo San Juan) and check them out. I rendered three frames with the doors rotated from 0 to 75 degrees to simulate... guess what? Opening doors. Clever, huh?

]]>

This is an introduction to creating completely non-interactive, or procedural flash animation using Linux. The beauty of this is not that you can do more, or that it’s prettier, or even faster to create. The beauty lies in the power. Once an animation procedure is set, the elements can be changed simply by including new images, colors, or messages. In fact, I’m working on a simple web-form to generate the above animation by simply uploading elements and text inputs.

But first, let’s get to the tutorial, shall we?

The door scene modeled in POV-ray scene description language and is typical of Old San Juan, Puerto Rico Spanish Colonial architecture. The real doors are beautiful. If you ever get a chance to take a cruise from/to Puerto Rico, don’t miss the chance to walk around Old San Juan (El Viejo San Juan) and check them out. I rendered three frames with the doors rotated from 0 to 75 degrees to simulate… guess what? Opening doors. Clever, huh?

There’s a lot of POV code, here’s a little bit of what it looks like:

cylinder { <0, 0.5, 0>, <0, -0.5, 0>, 0.5
texture {
pigment { color rgb <0.6, 0, 0> }
normal { granite 0.02 turbulence <0.5, 0.9, 0.2> scale 0.25 }
finish { specular 0.1 reflection .1 }
}
}

It’s pretty simple. You place objects in an X-Y-Z space (Cartesian coordinates) like a sphere, cylinder, box or any other of the predefined primitives. You can merge them, subtract them, intersect them in creative ways. Finally, you apply some sort of texture which includes a pigment, a surface (normal), and a finish (reflections effects etc). There are easier ways to model, but sometimes POV-ray’s scene description language is just the most elegant and easiest way to model something.

The next step was to convert the png files to jpegs for inclusion in the flash animation. I used a little sprinkle of bash and a dash of kosher ImageMagick’s convert.

for file in *.png; do convert -quality 100 "$file" "${file%.png}.jpg"; done

For each png file, convert the png file to a 100 percent quality jpeg file. We use 100% quality because I’m going to let the swftools take care of the final compression. There’s no sense in lossy compressing then lossy compressing again. That’s just crazy talk.

We will now create the flash source file. Open a new file slideshow.sc. This is the textual language for the swftools Linux Flash toolkit. I have never ever ever looked at a flash source file from any Macromedia product, so I have no idea if this animation description method looks/acts/walks/talks in anyway shape or form like Macromedia’s products. Don’t know, don’t care.

.flash bbox=640x480 filename="slideshow.swf" version=6 fps=25 compress background=white

.jpeg s1 "puerta_open03.jpg"
.jpeg s2 "puerta_open02.jpg"
.jpeg s3 "puerta_open01.jpg"
.font font "gilc____.ttf"
.font arial "arialbi.ttf"
.text text1 text="Opening Doors" font=font
.text text2 text="Opening Doors" font=font
.text text3 text="Opening Doors" font=font
.text text4 text="OG" font=arial
.text text5 text="Experts in" font=font
.text text6 text="Open Source" font=font

.put s1 scalex=640 scaley=480 alpha=100%
.put text1 scale=100% x=40 y=220 alpha=0%

.frame 25
.put s2 scalex=640 scaley=480 alpha=0%
.change text1 alpha=100%
.put text2 scale=100% x=40 y=220

.frame 100
.change s2 alpha=0%
.change text1 alpha=100%
.change text2 alpha=100%

.frame 125
.change text1 alpha=0%
.change text2 alpha=100%
.change s2 alpha=100%
.put s3 scalex=640 scaley=480 alpha=0%
.put text3 scale=100% x=40 y=220

And so on (that’s not the whole file, but the rest is just repetition. There are 71 total lines of code for that little flash animation. Is that a lot or a little? Seems pretty small to me anyway. Basically, with swftools you define an object (image, or text); you put it; then you change it. You can change its fade, size, location, and more. The swfc program will implement the change from the object’s last known state. Check out swftools for more examples (that’s where I got all the reference I needed to make my little flash thingie).

So there you have it. I walk through the frames, changing elements, putting, fading, growing, moving stuff around. It’s was all described from start to finish in a procedural language, from the POV-ray scene description language, to bash and ImageMagick for command line image manipulation, and finally to swftools flash scene language for the final animation. Pretty nifty, huh?

Check out: http://www.altamente.com/ for another example.

The neat thing about this is that once the procedure has been developed, you can reuse it for other clients, other looks, colors, messages, etc. In fact, you could directly render it on the server to update information on the fly via end user input. There’s no limit to what you can do with something like this.

Of course if you’re on Windows, you would probably just buy Macromedia’s software… but where’s the fun in that?

]]>
http://og-consulting.com/2006/03/18/procedural-flash-animation-in-linux/feed/ 0
Ruby on Rails – Insert Multiple Child Records http://og-consulting.com/2006/03/09/ruby-on-rails-insert-multiple-child-records/ http://og-consulting.com/2006/03/09/ruby-on-rails-insert-multiple-child-records/#comments Thu, 09 Mar 2006 06:39:47 +0000 admin http://www.og-consulting.com/2006/03/09/ruby-on-rails-insert-multiple-child-records/ I have been having a bafflingly hard time trying to figure out the proper way to insert multiple child records from one single webform.  It is the standard fare for posting things like invoice headers and details.  Say for example, you've got an invoice record which consists of an order number, date and whatnot.  That particular piece of tabular data is then considered the parent of its child line items (product_id, description, quantity, price, etc).  So you've got this Order which consists of an invoice and line items.

]]>
I have been having a bafflingly hard time trying to figure out the proper way to insert multiple child records from one single webform.  It is the standard fare for posting things like invoice headers and details.  Say for example, you’ve got an invoice record which consists of an order number, date and whatnot.  That particular piece of tabular data is then considered the parent of its child line items (product_id, description, quantity, price, etc).  So you’ve got this Order which consists of an invoice and line items. 

It’s pretty basic, but I’ve had the hardest time figuring out how to do this is Ruby on Rails.  I know it’s not hard in theory, but with Rails, since there is only One Right Way(TM) to do things, ’cause you’re on Rails, it takes a bit of doing to figure out this Right Way(TM).  I personally don’t have a problem doing it Rails’ way, but please dear God, just tell me what it is.  I bought the book and everything.

So here’s the dope, folks.  Please correct me if there’s a better way of doing this, ’cause I’m a Rails n00b.  For reference sake, I am using Ruby on Rails 1.0 with Postgres 8.0.4 and Ruby 1.8.4

First the webform:

<ul id=items>
   <% for item in @items %>
   <li><%= check_box_tag 'line_item', item.id, checked=false, {:name => "line_item[item_id][]", :id => "line_item_id_#{item.id}" }  %><label for="line_item_id_<%= item.id %>"> <%= item.title  %></label></li>
   <% end %>
</ul>

Make sure to use check_box_tag instead of check_box.  check_box holds a hidden text input that by default inserts a 0 into the database.  From http://rubyonrails.org/api/classes/ActionView/Helpers/FormHelper.html

The checked_value defaults to 1 while the default unchecked_value is set to 0 which is convenient for boolean values. Usually unchecked checkboxes don’t post anything. We work around this problem by adding a hidden value with the same name as the checkbox.

You don’t want that.  You want the plain vanilla check_box_tag which does none of that nonsense, because you in fact, don’t want your line_item table being filled with up with all kinds of line_items referring to product "0" or product "NULL".

So that’s our form.  The line <% for item in @items %> comes from the items.rb model and is just a little database query to get all the items associated with a particular order for posting in our invoice.  Why would we use checkboxes?  Well, maybe we’re not going to invoice the whole order.  Maybe we’re out of some items.  We’ll let our warehouse guy check off the checkboxes on his wireless pda.  How’s that?

If you were watching closely, you’ll notice that I modified the check_box_tag behavior with options of my own with the following:

:name => "line_item[item_id][]"

This is what gives us multiple lines (an array of items) to pass to the controller.  [] is the important part.

Now, so far this is easy, or at least I thought so.  I’ve done this a hundred times in php, but that’s just the problem, I got tired of writing and re-writing this.  I wanted Rails to handle all the parent child relationships for me and leave me alone.  I’m lazy.

But I couldn’t figure out exactly how to do this.  Frankly, I’m still trying to fit all the method/class/object/instance/variable blah blah blah into my head and keep all the Invoice invoice invoices straight.  I know, I know, it’s probably me, but I’ll wager there are a few more slow-witted programmers out there for whom this is all so confusing.  A phrase that I have been becoming more familiar with while working in Ruby on Rails is, "Use the force."  It’s funny, but most of the time when I relax and make stuff up without trying to "understand,"  things usually Just Work(TM).  Jedi Programming… who knew?

So we’ve got our form.  Now we need to post the parent and the children in one fell swoop.

Now for the model (no, not Victoria’s Secret):  Invoice will not reference the children (the children will come running when they hear their parent’s voice regardless of whether they are called by name).  The parent "has_many" children and does not bother remembering their names or ids or anything.  The children on the other hand "belong_to " (or reference) the parent and are tattooed with the parent_id stamp of ownership (big ears for example).   When they are required, they will all line up under the parent and file out like good little children.

Got it?  Parent -> has_many :children, Child -> belongs_to :parent – the model of a perfect Catholic Rails family.

Now we need to post the stuff.  This is a snippet from the invoice_controller.rb:

   def create
      @invoice = Invoice.new(params[:invoice])
      @invoice.order_id = @session["order_id"]
      for item_id in params[:invoice_item][:item_id] do
              @invoice.invoice_items << InvoiceItem.new(:item_id => item_id)
      end
      if @invoice.save
         flash[:notice] = 'Invoice was successfully created.'
         redirect_to :action => 'list'
      else
         render :action => 'new'
      end
   end

order_id is stored in the session array and is used to reference the invoice.  The invoice in turn has items added to it for each item_id in the params passed from our form.  What happens on @invoice.save is the following:

  1. Rails inserts the invoice header (the parent)
  2. Immediately fetches currval(invoices_id_seq) to retrieve the newly created invoice_id
  3. Uses that invoice_id number and iterates over the invoice_items inserting both the item_id and invoice_id
  4. commits the results if successful
That’s it!  Easy, huh?  Well it took me all day to figure it out.  I knew it was easy, but perhaps I don’t have mad google sklz or something, because it left me scratching my head.  Hopefully someone will find this useful.  Leave a comment and I’ll do my best to answer your questions.  If not, I’m sure I’ll forget it in a few months and have to reread this *G*.
]]>
http://og-consulting.com/2006/03/09/ruby-on-rails-insert-multiple-child-records/feed/ 20
Tras la Pista del Consumidor Tecno-Sapiens http://og-consulting.com/2005/11/14/tras-la-pista-del-consumidor-tecno-sapiens/ http://og-consulting.com/2005/11/14/tras-la-pista-del-consumidor-tecno-sapiens/#comments Mon, 14 Nov 2005 20:32:02 +0000 lmgorbea http://www.og-consulting.com/2005/11/14/tras-la-pista-del-consumidor-tecno-sapiens/ variante del ser humano moderno que está virando al revéz
su relación con los medios. Hasta ahora la literatura del
usuario del consumidor de televisión lo presentaba como una
persona aplataná en el sofá sirviendo de esponja a todo
lo que se sirve por las ondas televisivas o el famoso “couch
potato.”   Al pensar en mercadear o desarrollar marcas se pensaba
en exposiciones a productos a ese receptor pasivo.]]>
En la evolución del ser humano se han dado nombres a vertientes que muestra una divergencia significativa de la evolución. Homo Habilis era hábil con herramientas, Homo erectus caminó de pie. A modo de diversión pero a la vez para reflejar un cambio en la conceptualización del consumidor. Por ello en vez de empezar con “homo” empiezo con consumidor asumiendo que el poder adquisitivo lo ejerce un ser humano. En repaso de las nuevas tecnologías y su efecto sobre el consumidor hablo entonces del “Consumidor Tecno-Sapiens.” El Consumidor Tecno-Sapiens, variante del ser humano moderno que está virando al revéz su relación con los medios. Hasta ahora la literatura del usuario del consumidor de televisión lo presentaba como una persona aplataná en el sofá sirviendo de esponja a todo lo que se sirve por las ondas televisivas o el famoso “couch potato.” Al pensar en mercadear o desarrollar marcas se pensaba en exposiciones a productos a ese receptor pasivo.

Pero la tecnología sigue cambiando a un ritmo acelerado y las relaciones caracterizaban la creación y transmisión de información están sufriendo cambios dramáticos. Hoy día, si tienes una duda, ya no te razcas la cabeza, ni abres la encyclopedia, muchas veces antes de consultar con padres o amigos, lo más inmediato es buscarlo en portales como Google. “Google” ya no es una palabra rara sino para muchos es un verbo sinónimo a búscalo - “google it!” y para otros es el nombre de una sabia inversión monetaria. Conexiones de banda ancha en las casas, oficinas, hoteles y hasta en Starbucks, facilitan que el consumidor presente con más frequencia sus inquietudes y busque en el ciberespacio sus respuestas. Si esta es la economía de la información, los consumidores ya tienen el hábito de buscar información en el Internet. En esta nueva economía donde la información es el objeto de intercambio hay muchas relaciones de poder, entretenimiento y negocios que están siendo afectadas. En breve damos exploramos consecuencias de estos cambios y estrategias de negocios y mercadeo para atenderlos.

Tecno-Sapiens reorganiza el flujo de la información

En los 90 se hablaba de webcasts, se vaticinaba que el usuario dejaría de buscar su entretenimiento en el televisor. Quizás no hemos dejado a un lado el televisor pero el uso del mismo y el Internet han cambiado patrones de interacción. Probablemente no muchos conozcan el TiVo pero a sí el cambio fundamental que el TiVo impulsó. Hoy día por medio de muchas compañías de satélite se han introducido a las casas grabadores de televisión (TV DV-R’s) que permiten pausar la transmisión y automáticamente comenzar a grabarla. Cuando se re-establece la transmisión el televidente puede pasar por alto los comerciales. De igual manera con este dispositivo se puede seleccionar grabar todas las ocurrencias de un tema o programa y eliminar los comerciales de la grabación. El patrón trasciende de esta nueva tecnología: el consumidor evita los anuncios televisivos.

Nuestras computadoras no se han convertido aún en sustitutos del televisor pero sí se ha convertido en un agresivo proveedor de contenido. Nuevas generaciones buscan en el Internet música, grabaciones de programas o películas. No piensen que esto último es área exclusiva de piratas y contenido ilegal. El Internet ha reanimado a muchos artistas facilitando la creación de comunidades que apoyan su contenido. Un atractivo al consumidor de contenido en-línea es la ausencia de comerciales.

El fenómeno de pod-casting es un paso más en esta evolución que socava el acostumbrado impacto de comerciales. Se refiere a la transmisión de contenido de video o audio en dispositivos manuales como un “i-pod.” El patrón dominante favorece al consumidor que más y más puede disfrutar del contenido de su predilección a la hora de su conveniencia.

Cambios en el del consumidor Tecno-Sapiens

Las nuevas tecnologías están fomentando un cambio en la transmisión de contenido que apunta a la reducción en el impacto del comercial tradicional. Por un lado veremos más películas como “Herbie” sobrecargadas con publicidad de marcas a lo largo de la producción. Pero ciertamente, no estamos vaticinando la desaparición de comerciales. Lo que sí recomendamos es un cambio en su conceptualización. En un panorama donde el consumidor está tomando un rol más activo sobre su consumo de producciones de video y audio, y evitando ver comerciales, una alternativa es cuidar el contenido y crear en vez corto-metrajes atractivos.

Recientemente, en EEUU campañas comerciales que utilizan el web para darle mayor vida a los anuncios se están viendo más. El ejemplo más reciente fue el esándoloso comercial de Carl Jr’s con Paris Hilton lavando un carro hamburguesa en mano. Puerto Rico vió un ejemplo de esta misma estrategia de vanguardia que en la campaña reciente de Holsum. Holsum invirtió en la creación de algo más grande que lo que acostumbramos pensar cuando pensamos en un comercial. El corto metraje apeló a su audiencia mediante la selección de una historia que resonaba con el público puertorriqueño, el uso de artistas locales, y la elegancia de utilizar toda clase de suplidores locales. El corto metraje se anunció en varios medios. Corrió en la televisión y en el Internet. Miles de personas visitaron el sitio web designado para volver a ver el mega comercial y cientos de personas voluntariamente compartieron el video con familiares y amigos.

Este ejemplo enmarca al comercial como algo más que un anuncio en un espacio televisivo atractivo. El comercial se convierte en la generación de contenido con un valor añadido que invita al consumidor a participar. En términos de “push” y “pull.” El consumidor tecno-sapiens está buscando maneras de evitar ese contenido que le impulsan a modo de bombardeo. La innovación en mercadeo impulsada por las nuevas tecnologías será buscar maneras en las que se hala al consumidor a participar.

Contenido que hala

Si partimos del punto de vista del consumidor tecno-sapiens el mismo comienza con una pregunta o duda. Un portal efectivo hoy día debe ir más allá del monólogo “nuestra historia” y “quiénes somos,” para enfocar en la información que sus clientes estarán buscando y que podrían servir como antemesa a una venta o como servicio público que fomenta el desarrollo de su marca.

En esta economía de la información la tendencia de algunos es pensar que tienen que guardar sus secretos. Pero las tendencias en el mercado demuestran lo contrario. Hay que dar, o invertir para cosechar fruto. Al dar algo de valor en su sitio web la meta debe ser establecer una razón por la cual regresar. Esto suele ser contenido educativo, formularios para acortar procesos, entretenimiento como videos, galerías de imágenes, o juegos, calculadoras de costo, u otros programas que aclaran las dudas de sus clientes.Entre las empresas norteamericanas vemos que gigantes como Budweiser, Chrysler, Nabisco, AETNA y otras marcas ya tienen estrategias de internet que atienden sus consumidores tecno-sapiens. En estos sites uno puede buscar contenido educativo, entretenimiento y acortar pasos en el proceso de comprar o solicitar servicios.

Localmente la industria bancaria es la más adelantada en facilitar procesos para consumidores tecno-sapiens pero el contenido de sus sitios web no son multi-plataforma. A menudo la información reside en imágenes y animaciones que google no puede leer y catalogar. Esto restringe su consumo y uso a uno local donde se sepa cual es el nombre y dominio del banco. El sector automotriz revela los cambios más dramáticos en la evolución de un énfasis sobrecargado en diseño y efecto a utilidad y servicios al consumidor. Una industria que ha venido incorporando tecnología para hablarle a los Consumidores Tecno-Sapiens es la del turismo. Más y más gracias a esfuerzos en parte subsidiados por el gobierno se ha incorporado el uso del Internet para atender preguntas y reservaciones de consumidores vía el Internet.

Sectores empresariales puertorriqueños rezagados en el uso de la tecnología pero con gran potencial para desarrollo son la industria de alimentos y materiales de construcción. En este sector notables excepciones lo son el sitio web de Holsum, Lanco y Carmelo.

Preguntas guías para repensar su estrategia de Internet:

  • ¿Qué preguntas contestan en su portal?

  • ¿Porqué habría de toparse con su sitio web un Consumidor Tecno-Sapiens?

  • ¿Qué gestiones puede realizar el consumidor en el portal?

  • ¿Cuán versátil es su contenido? ¿Puede Google o una palm leer su contenido o está el mismo encerrado en un dibujo o animación?

  • ¿Puede el visitante compartir fácilmente la información con amistades?

  • ¿Porqué habrían de volver los consumidores tecno-sapiens?

]]>
http://og-consulting.com/2005/11/14/tras-la-pista-del-consumidor-tecno-sapiens/feed/ 0
Why Good Programmers Are Lazy and Dumb http://og-consulting.com/2005/08/26/why-good-programmers-are-lazy-and-dumb/ http://og-consulting.com/2005/08/26/why-good-programmers-are-lazy-and-dumb/#comments Fri, 26 Aug 2005 13:34:48 +0000 admin http://www.og-consulting.com/?p=21 We at OG Consulting have been saying this for years.  Frankly, we are the laziest and dumbest consultants around. 

Why Good Programmers Are Lazy and Dumb by Philipp Lenssen

I realized that, paradoxically enough, good programmers need to be both lazy and dumb.

Lazy, because only lazy programmers will want to write the kind of tools that might replace them in the end. Lazy, because only a lazy programmer will avoid writing monotonous, repetitive code – thus avoiding redundancy, the enemy of software maintenance and flexible refactoring. Mostly, the tools and processes that come out of this endeavor fired by laziness will speed up the production.

Of course, we work very hard at being lazy.  We’ll find resources you might not have thought of (because we’re lazy).  We might write a business automation system (because punching numbers is boring and computers are good at it… and we’re lazy).  We might help you better program your employees because we don’t want to do their work and neither do you.  And we will ask the dumb questions you might not.  In short, we don’t assume we know more than you do about your business.  In consulting there is no shortage of professionals who help you spend your hard earned money to complicate your processes, accounting, Internet strategy, or software implementation. 

We’ll probably lose our membership in the Secret Order of Consulting Professionals for saying this, but we don’t suppose it’s any secret – consultants obfuscate things to render the illusion of success or progress while billing by the hour.  OG Consulting is neither motivated enough nor smart enough to pull that off.  We’d rather help you make your business processes brain-dead simple so we don’t have to think so hard and neither will you.

And that’s the bottom line.  We’re too lazy and dumb to fail.

]]>
http://og-consulting.com/2005/08/26/why-good-programmers-are-lazy-and-dumb/feed/ 0
The True Price of Software http://og-consulting.com/2005/07/23/the-true-price-of-software/ http://og-consulting.com/2005/07/23/the-true-price-of-software/#comments Sat, 23 Jul 2005 23:15:50 +0000 admin http://www.og-consulting.com/2005/07/23/the-true-price-of-software/ Free/Libre Open Source Software has been criticized for undermining the pricing of software.  This interesting piece published in ONLamp, exposes the true financial underbelly of the software market.  We find out, that software really wasn’t worth much to begin with.

except from "Calculating the True Price of Software" by Robert Lefkowitz

… the major difference in worldview between open source advocates and proprietary software license advocates is explainable as a differing opinion on the correct value of the volatility of maintenance and upgrade pricing. People who believe that the pricing on maintenance is stable and unlikely to change see greater intrinsic value in the software. People who fear that the pricing is subject to large fluctuations see no intrinsic value in the up-front license; stripped of the options, the license value approaches $0.

For the open source movement, perhaps a better way to position the change that OSS is making is this: we’re converting warrants on future maintenance and enhancements into options, which means that instead of having a sole supplier (warrants), we have created a third-party market (options) of these derivatives.

How capitalistic is that?

The conclusion is that even without all the financial analysis, Free/Libre Open Source programmers have stumbled upon an inevitable truth; software by itself isn’t worth much and the proprietary vendors know it.  What has flourished in recent years is a free flowing market where vendors may compete to sell customers maintenance, support, and upgrades. 

]]>
http://og-consulting.com/2005/07/23/the-true-price-of-software/feed/ 0