<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>VotanWeb - Home</title>
  <id>tag:blog.votanweb.com,2008:mephisto/Home</id>
  <generator uri="http://mephisto.techno-weenie.net" version="666">Mephisto</generator>
  <link href="http://blog.votanweb.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://blog.votanweb.com/" rel="alternate" type="text/html"/>
  <updated>2008-02-13T20:51:26Z</updated>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2008-02-13:/article/2008/2/13/spybot-blocks-casalemedia</id>
    <published>2008-02-13T20:37:00Z</published>
    <updated>2008-02-13T20:37:00Z</updated>
    <category term="General Computing"/>
    <link href="http://blog.votanweb.com/2008/2/13/spybot-blocks-casalemedia" rel="alternate" type="text/html"/>
    <title>SpyBot Blocks CasaleMedia</title>
<content type="html">&lt;p&gt;Sometimes software does the darndest things&#8230;and it can drive you crazy.  That&#8217;s just what happened today when I attempted to login to my publisher account at CasaleMedia.com.  Oddly, enough my requests to the website were being redirected to the webserver running on my personal computer.  Being a Windows XP box, I issued the following command to bring up the hosts file:&lt;/p&gt;

&lt;pre&gt;
C:\WINDOWS\NOTEPAD.EXE C:\WINDOWS\SYSTEM32\DRIVERS\etc\HOSTS
&lt;/pre&gt;

&lt;p&gt;Much to my surprise, I found a &lt;em&gt;HUGE&lt;/em&gt; list of sites added by SpyBot Search &amp;amp; Destroy with casalemedia being one of them.  They are redirecting these sites to the computer owner&#8217;s PC as a means of blocking them.  I&#8217;m not sure why Casale was added to that list but here&#8217;s a small excerpt: &lt;/p&gt;

&lt;pre&gt;
127.0.0.1   www.casalemedia.com
127.0.0.1   casalemedia.com
127.0.0.1   www.cashdeluxe.net
127.0.0.1   cashdeluxe.net
127.0.0.1   www.cashengines.com
127.0.0.1   cashengines.com
127.0.0.1   cashsearch.biz
127.0.0.1   www.cashsurfers.com
127.0.0.1   cashsurfers.com
127.0.0.1   www.CashUnlim.com
&lt;/pre&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2008-02-08:/article/2008/2/8/small-biz-fights-big-socialism</id>
    <published>2008-02-08T13:45:00Z</published>
    <updated>2008-02-08T13:45:00Z</updated>
    <category term="Business"/>
    <link href="http://blog.votanweb.com/2008/2/8/small-biz-fights-big-socialism" rel="alternate" type="text/html"/>
    <title>Small Biz Fights Big Socialism</title>
<content type="html">&lt;p&gt;Sometimes people just don't get it.  They have forgotten their history lessons and somehow feel that this time around it will be possible to have both socialism and a thriving economy.   Fortunately, New York small business owners are reminding state lawmakers to reject plans that would extend family leave and increase the minimum wage.&lt;/p&gt;

&lt;p&gt;The National Federation of Independent Business, a Washington-based advocacy group, conducted a survey of 11,000 members of its New York chapter and found that 92 percent opposed the family-leave measure, which would extend paid employee absences to 12 weeks.  83 percent opposed the increase in minimum wage.&lt;/p&gt;

&lt;p&gt;Critics believe these measures will prevent small businesses from creating more jobs, especially in light of the current mortgage crisis.&lt;/p&gt;

&lt;p&gt;My rant:
3 months of paid time off!  WOW!  I do not know anyone that wouldn't LOVE for their employer to pay them for 12 weeks off from work, but it's really not the responsibility of the business to finance what you do at home.  It is amazing how the government so joyously pushes off it's socialist agenda on businesses.  Whether or not you believe the government should be responsible for providing for the people, we should all agree that businesses should NOT be responsible for this.  And yet, for most Americans, it is the employer that provides them with health insurance, facilitates their retirement, pays for them if they become unemployed, pays for schools and other taxes unrelated to the business itself, and pays for family leave.  When did it become alright for Small Business to be the whipping boy of Big Socialism?&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-12-14:/article/2007/12/14/developer-nirvana-amazon-simpledb</id>
    <published>2007-12-14T16:52:00Z</published>
    <updated>2007-12-14T16:52:00Z</updated>
    <category term="Web Development"/>
    <link href="http://blog.votanweb.com/2007/12/14/developer-nirvana-amazon-simpledb" rel="alternate" type="text/html"/>
    <title>Developer Nirvana - Amazon SimpleDB</title>
<content type="html">&lt;p&gt;Finally something worth talking about!  I love it when Amazon sends me their webservice emails because they always seem to be cooking up something clever that&#8217;s going to make my job easier.  First it was S3, then EC2, and now &lt;a href='http://www.amazon.com/gp/browse.html?node=342335011'&gt;SimpleDB&lt;/a&gt;.  In their own words:&lt;/p&gt;

&lt;div style='margin:15px;background:#ddd;'&gt;
Amazon SimpleDB is easy to use and provides the core functionality of a database - real-time lookup and simple querying of structured data - without the operational complexity.  Amazon SimpleDB requires no schema, automatically indexes your data and provides a simple API for storage and access.  This eliminates the administrative burden of data modeling, index maintenance, and performance tuning. Developers gain access to this functionality within Amazon&#8217;s proven computing environment, are able to scale instantly, and pay only for what they use.
&lt;/div&gt;

&lt;p&gt;Ahhhh.  Doesn&#8217;t that sound nice?  No software to maintain.  No db server to maintain.  No data modeling.  No need to monitor storage space or server load.  If this sounds good to you,  check out the &lt;a href='http://www.amazon.com/gp/browse.html?node=342335011'&gt;full page&lt;/a&gt;.&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-10-05:/article/2007/10/5/blog-admin-nazis-and-link-love</id>
    <published>2007-10-05T15:47:00Z</published>
    <updated>2007-10-05T15:47:00Z</updated>
    <category term="Business"/>
    <category term="Search Engines"/>
    <link href="http://blog.votanweb.com/2007/10/5/blog-admin-nazis-and-link-love" rel="alternate" type="text/html"/>
    <title>Blog Admin Nazis and Link Love</title>
<content type="html">&lt;p&gt;In an attempt to fight the evil legions of spammers that threaten to descend upon blogs everywhere, some bloggers have taken up arms and become what I endearingly refer to as &quot;Blog Admin Nazis&quot;.  Despite the &quot;U Comment, I Follow&quot; badges that adorn their pages, these warriors will not hesitate to decapitate your comment with one swift click of the mouse.&lt;/p&gt;

&lt;p&gt;But is this fair?  Is this in alignment with the &quot;Do Follow&quot; movement?  Certainly spam needs to be deleted.  Little one line comments like &quot;Loved this post!&quot;, or &quot;I agree with Tom!&quot; certainly deserve to vanish.   However, my understanding of the “Do Follow” concept was that people who take the time to write a thoughtful post on a dofollow blog have earned the right to a link. Naturally, I’ve been surprised to visit some blogs that proudly display the “U Comment, I Follow” logo, and when I take the time to write out a thoughtful, on-target post, they remove my link, but keep my post. To me that is the ultimate insult. I’d rather them delete the post entirely then to keep my contribution, but deny me a link.&lt;/p&gt;

&lt;p&gt;There you have it.  You will find no Blog Admin Nazis on this site.  Nothing but link love for those who take the time to write a thoughtful comment.&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-09-19:/article/2007/9/19/rails-performance-diary</id>
    <published>2007-09-19T19:48:00Z</published>
    <updated>2007-09-19T19:48:00Z</updated>
    <category term="Ruby"/>
    <category term="Web Development"/>
    <link href="http://blog.votanweb.com/2007/9/19/rails-performance-diary" rel="alternate" type="text/html"/>
    <title>Rails Performance Diary</title>
<content type="html">&lt;p&gt;Although this blog post is titled &lt;b&gt;Rails&lt;/b&gt; Performance Diary, it actually has more to do with SQL.  For many websites, much of the work is being done by the database server.  Such is the case for a simple dog site that I am working on.  Having done quite a few websites using Ruby on Rails, I was surprised to find this simple site giving me some major performance problems.  Pages were loading slow and sometimes timing out and there was no traffic to the site, other than the developers.&lt;/p&gt;

&lt;p&gt;Fortunately, the Rails log outputs all of the queries by default, which is always the first place that I look.  And here's what I found -- 2 queries:&lt;/p&gt;

&lt;p&gt;1)
SELECT * FROM breeds&lt;/p&gt;

&lt;p&gt;2)
SELECT breeds.&lt;code&gt;id&lt;/code&gt; AS t0&lt;em&gt;r0, breeds.&lt;code&gt;name&lt;/code&gt; AS t0&lt;/em&gt;r1, breeds.&lt;code&gt;alias&lt;/code&gt; AS t0&lt;em&gt;r2, breeds.&lt;code&gt;lookup&lt;/code&gt; AS t0&lt;/em&gt;r3, breeds.&lt;code&gt;info&lt;/code&gt; AS t0&lt;em&gt;r4, breeds.&lt;code&gt;line_breaks&lt;/code&gt; AS t0&lt;/em&gt;r5, breeds.&lt;code&gt;has_pics&lt;/code&gt; AS t0&lt;em&gt;r6, breeds.&lt;code&gt;has_videos&lt;/code&gt; AS t0&lt;/em&gt;r7, pictures.&lt;code&gt;id&lt;/code&gt; AS t1&lt;em&gt;r0, pictures.&lt;code&gt;breed_id&lt;/code&gt; AS t1&lt;/em&gt;r1, pictures.&lt;code&gt;original&lt;/code&gt; AS t1&lt;em&gt;r2, pictures.&lt;code&gt;large&lt;/code&gt; AS t1&lt;/em&gt;r3, pictures.&lt;code&gt;medium&lt;/code&gt; AS t1&lt;em&gt;r4, pictures.&lt;code&gt;thumbnail&lt;/code&gt; AS t1&lt;/em&gt;r5, pictures.&lt;code&gt;caption&lt;/code&gt; AS t1&lt;em&gt;r6, pictures.&lt;code&gt;email&lt;/code&gt; AS t1&lt;/em&gt;r7, pictures.&lt;code&gt;notes&lt;/code&gt; AS t1&lt;em&gt;r8, pictures.&lt;code&gt;disabled&lt;/code&gt; AS t1&lt;/em&gt;r9, pictures.&lt;code&gt;order_field&lt;/code&gt; AS t1&lt;em&gt;r10, pictures.&lt;code&gt;created_at&lt;/code&gt; AS t1&lt;/em&gt;r11, pictures.&lt;code&gt;filename&lt;/code&gt; AS t1&lt;em&gt;r12, pictures.&lt;code&gt;breed_lookup&lt;/code&gt; AS t1&lt;/em&gt;r13, videos.&lt;code&gt;id&lt;/code&gt; AS t2&lt;em&gt;r0, videos.&lt;code&gt;breed_id&lt;/code&gt; AS t2&lt;/em&gt;r1, videos.&lt;code&gt;title&lt;/code&gt; AS t2&lt;em&gt;r2, videos.&lt;code&gt;description&lt;/code&gt; AS t2&lt;/em&gt;r3, videos.&lt;code&gt;code&lt;/code&gt; AS t2&lt;em&gt;r4, videos.&lt;code&gt;created_at&lt;/code&gt; AS t2&lt;/em&gt;r5, videos.&lt;code&gt;orig_url&lt;/code&gt; AS t2&lt;em&gt;r6, videos.&lt;code&gt;embed_src&lt;/code&gt; AS t2&lt;/em&gt;r7, videos.&lt;code&gt;thumbnail&lt;/code&gt; AS t2&lt;em&gt;r8, videos.&lt;code&gt;time_length&lt;/code&gt; AS t2&lt;/em&gt;r9, videos.&lt;code&gt;length_seconds&lt;/code&gt; AS t2&lt;em&gt;r10, videos.&lt;code&gt;youtube_id&lt;/code&gt; AS t2&lt;/em&gt;r11, videos.&lt;code&gt;lookup&lt;/code&gt; AS t2&lt;em&gt;r12 FROM breeds LEFT OUTER JOIN pictures ON pictures.breed&lt;/em&gt;id = breeds.id LEFT OUTER JOIN videos ON videos.breed&lt;em&gt;id = breeds.id WHERE (breeds.&lt;code&gt;lookup&lt;/code&gt; = 'airedale&lt;/em&gt;terrier' )&lt;/p&gt;

&lt;p&gt;The next step was to run each of these queries in the MySQL Query Browser, so I could see how long it took the queries to run.  The first query took 13 seconds to execute, so I felt that I had found the problem.  Much to my chagrin, however, I found the second query to take over a minute!!!  Clearly, neither one of these queries are acceptable, even with caching.&lt;/p&gt;

&lt;h2&gt;The First Query : SELECT * FROM breeds&lt;/h2&gt;

&lt;p&gt;This query was being used simply to get a list of the dog breeds so that I could link to each of their info pages, yet the query was returning the entire record, which includes a long &quot;description&quot; column containing a lot of text.  This query was generated by ActiveRecord from the following code:
&lt;code&gt;
@breeds = Breed.find(:all)
&lt;/code&gt;
To solve the problem, let's force a specific query that doesn't include the description field:
&lt;code&gt;
@breeds = Breed.find_by_sql(&quot;SELECT id, name FROM breeds&quot;)
&lt;/code&gt;
Immediately, the query dropped from 13 seconds to a fraction of a second.&lt;/p&gt;

&lt;h2&gt;Second Query:  SELECT breeds.&lt;code&gt;id&lt;/code&gt; AS t0_r0, breed....&lt;/h2&gt;

&lt;p&gt;Here was the stumper.  This vast expanse of SQL was generated from the following Ruby:
&lt;code&gt;
@breeds = Breed.find_by_lookup(lookup, :include =&gt; [pictures, videos])
&lt;/code&gt;
Typically, including relations speeds things up because it allows an SQL join to be used rather than multiple SQL queries.  But, in this case, the join only reduces 3 queries to 1 query and incurs a large overhead to do so.  Join tables multiply the number of records for each table joined, so in this case the number of results was extremely large.  Now, I'm sure a veteran database wizard could enlighten you with SQL magic to solve this problem.  But, not being such a wizard, I simply broke the query into 3 separate queries as shown below:
&lt;code&gt;
@breeds = Breed.find_by_lookup(lookup)
@pictures = Picture.find(:all, :conditions =&gt; &quot;breed_id = #{@breed.id}&quot;)
@videos = Video.find(:all, :conditions =&gt; &quot;breed_id = #{@breed.id}&quot;)
&lt;/code&gt;
Voila!  Each of the 3 queries executes in less than a second!&lt;/p&gt;

&lt;p&gt;Note: although it's not mentioned above, I also added appropriate indexes to each of the database tables to speed up the queries.  These did not help much, but are always a good practice.&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-09-07:/article/2007/9/7/couchdb-not-a-threat-to-rdbms</id>
    <published>2007-09-07T13:40:00Z</published>
    <updated>2007-09-07T13:40:00Z</updated>
    <category term="Erlang"/>
    <link href="http://blog.votanweb.com/2007/9/7/couchdb-not-a-threat-to-rdbms" rel="alternate" type="text/html"/>
    <title>CouchDB:  No Threat to RDBMS</title>
<content type="html">&lt;p&gt;Eventually I plan on getting around to doing some in-depth Erlang programming.  Until then, it's nice to read up on current projects like the much-hyped CouchDB.  According to the CouchDB website...&lt;/p&gt;

&lt;p&gt;&lt;img src='http://blog.votanweb.com/assets/2007/9/7/erlang.gif' style='float:right' /&gt;&lt;/p&gt;

&lt;p&gt;CouchDb is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A document database server, accessible via a RESTful JSON API.&lt;/li&gt;
&lt;li&gt;Ad-hoc and schema-free with a flat address space.&lt;/li&gt;
&lt;li&gt;Distributed, featuring robust, incremental replication with bi-directional conflict detection and management.&lt;/li&gt;
&lt;li&gt;Query-able and index-able, featuring a table oriented reporting engine that uses Javascript as a query language. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...And although they claim it is not a replacement for RDBMSs, there are &lt;a href='http://blog.leetsoft.com/2007/9/2/futuretalk-couchdb'&gt;people who think it is&lt;/a&gt;.  I have to say, this project looks very promising.  I can envision lots of uses for it in which it would simplify apps that just want to quickly save some data.  Or apps that are storing lots of &quot;objects&quot; that all differ slightly.  Perhaps aggregating content from multiple sources.  I love stuff like this that get you to think about something in a whole new light.&lt;/p&gt;

&lt;p&gt;But, &lt;em&gt;here's the problem.&lt;/em&gt;  When a nifty project like this becomes over-sold and pushed beyond its expectations, I can't help but put on my critical hat.  The problem is fueled by the fact that there are lots of Erlang programmers out there that are itching to see Erlang take off, so they'll gladly prop up an Erlang project with inflated claims.  Let's take a look at some of the reasons why CouchDB will never be a threat to RDBMSs and some of the fallacies being spread.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No fixed columns = less ability to optimize&lt;br /&gt;
It's been a while since my database theory class in grad school, but I seem to recall discussion about the fixed structure of database columns as a key ingredient in achieving high performance.  Knowing the distance that each record takes up in a binary file allows the data to be read much faster.  And, extracting the necessary record(s) from file is where most of the time is spent for a given query.  Because CouchDB takes a &quot;no fixed structure&quot; approach, then it seems that it will lose to an RDBMS in disk access, which is the most time-consuming operation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bidirectional replication and peer setup = extra overhead or transactional issues&lt;br /&gt;
Replication is not my area of expertise, but I do know how to count and how to think, so let's do some basic math and logic.  For simplicity, let's pretend we have 4 beefy db servers.  In configuration A, we have 1 master server and 3 slave servers.  Whenever there is an update it takes place on the master server and the changes are sent to the 3 slave servers simultaneously.  Thus, 1 update = 3 messages.  &lt;br /&gt;
In configuration B, we have 4 server nodes connected in a peer-to-peer fashion.  If the machines are each connected to no more than 2 other machines, then messages will have to travel along mutliple hops, which would increase the number of messages and the time it takes for the message to be broadcast to all peers.  So, instead, let's assume that each peer is connected to every other peer.  Now, 1 update = 3 messages, but there is a different problem that has cropped up.  Any peer wishing to update a record will have to check with every other peer for changes first before it can safely do so.  Or, peers will have to be assigned as authoritative for subsets of the global data.  I'm not saying the P2P way of doing things is bad.  In fact, I think it allows for the system to scale rather easily.  But, we have to acknowledge the performance and transaction issues that come with this approach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No tables = less structure = worse performance&lt;br /&gt;
Every means of organizing data also leads to performance optmizations.  Storing data in tables is an additional means of classifying the data, which allows for faster extraction later.  CouchDB's table-less approach will be great for allowing people to easily store and retrieve things because they don't need to think about tables, but there will be a performance hit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transactional weakness = no enterprise use&lt;br /&gt;
Ooops.  I said the 'e' word.  I know, I know.  I don't like when people throw around the word &quot;enterprise&quot; in a demeaning way.  Like &quot;Your Ruby is not as enterprise-ish as my Java or .Net or C++&quot;.  But, sometimes when the shoe fits...Personally, I would like to know that Fidelity Investments is safeguarding the integrity of its data and every transaction that takes place so that my account balance is accurate.  Here's my favorite &lt;a href='http://blog.labnotes.org/2007/09/02/couchdb-thinking-beyond-the-rdbms/'&gt;scary quote&lt;/a&gt; on this issue:  &lt;br /&gt;
&quot;Features like referential integrity, constraints and atomic updates are really important in the client-server world, but irrelevant in a world of services.&quot;&lt;br /&gt;
You're kidding, right?  So, in a world of services, you don't need transactional support across a number of operations?  And referential integrity is for the birds?  That's fine if CouchDB wants to skimp on transactional support and use optimistic locking to attempt to boost performance, but you can't have your cake and eat it too.  That may work for some apps, but it's not going to fly for ones in which the data and the operations on that data are critical to the business and stakeholders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;C is faster than Erlang&lt;br /&gt;
I don't program in C because it takes too long and is way too tedious.  But you better believe the workhorse of my web apps (usually a database server) is going to be programmed in C.  As mentioned previously, CouchDB is programmed in Erlang while all the major database players use C.  I don't think this point needs to be discussed further.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I know this post is coming across a little hard on CouchDB, but it seems there needs to be some balance in the discussion.  This seems like a great project, but lets acknowledge that it has some strengths and some weaknesses.  It's a great concept, but as the documentation states, it's not a replacement for relational databases.&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-08-10:/article/2007/8/10/votan-website-marketplace-re-opens-for-business</id>
    <published>2007-08-10T13:22:00Z</published>
    <updated>2007-08-10T13:22:00Z</updated>
    <category term="Business"/>
    <link href="http://blog.votanweb.com/2007/8/10/votan-website-marketplace-re-opens-for-business" rel="alternate" type="text/html"/>
    <title>Votan Website Marketplace: Re-Opens for Business</title>
<content type="html">The VotanWeb &lt;a href='http://www.votanweb.com/buyers'&gt;website marketplace&lt;/a&gt; has re-opened and is now FREE to buyers and sellers!  There are still paid packages available for those that are interested, but we wanted to open up the majority of the site at no cost to YOU.  Even the Premium Listings for sellers are free to those sites that have an Alexa traffic rank of less than 250K.</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-08-09:/article/2007/8/9/whatever-happened-to-less-code</id>
    <published>2007-08-09T03:25:00Z</published>
    <updated>2007-08-09T03:25:00Z</updated>
    <link href="http://blog.votanweb.com/2007/8/9/whatever-happened-to-less-code" rel="alternate" type="text/html"/>
    <title>Whatever Happened to Less Code?</title>
<content type="html">&lt;p&gt;When I heard about the C# Application Markup Language, &lt;span class='caps'&gt;CSAML&lt;/span&gt;,  (http://www.charlespetzold.com/etc/CSAML.html) I was a little intrigued by the idea of declaratively being able to program in C#.  &lt;span class='caps'&gt;HTML&lt;/span&gt; is a good example of how markup can be more concise than code, while allowing people of all degrees of skill create web pages.&lt;/p&gt;


	&lt;p&gt;Then I saw the Hello World application&#8230;IMHO, 10 lines of code for a C# Hello World app is too long, but the &lt;span class='caps'&gt;CSAML&lt;/span&gt; Hello World app came in at 20 lines of ugly, bloated &lt;span class='caps'&gt;XML&lt;/span&gt;.  How is this an improvement????&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-07-25:/article/2007/7/25/link-building-tip-of-the-day</id>
    <published>2007-07-25T18:46:00Z</published>
    <updated>2007-07-25T18:46:00Z</updated>
    <category term="Search Engines"/>
    <link href="http://blog.votanweb.com/2007/7/25/link-building-tip-of-the-day" rel="alternate" type="text/html"/>
    <title>Link Building Tip of the Day</title>
<content type="html">Don't believe the hype about .gov and .edu domains.  They are no better than .com or other TLDs for PageRank -- at least according to Google sources.  (We can't speak for Yahoo, MSN, Ask, or others)</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-06-14:/article/2007/6/14/no-need-to-checkout-googlecheckout</id>
    <published>2007-06-14T18:11:00Z</published>
    <updated>2007-06-14T18:11:00Z</updated>
    <category term="Search Engines"/>
    <category term="Web Development"/>
    <link href="http://blog.votanweb.com/2007/6/14/no-need-to-checkout-googlecheckout" rel="alternate" type="text/html"/>
    <title>No Need to Checkout GoogleCheckout</title>
<content type="html">&lt;p&gt;PayPal is a wonderful thing in that it allows me, a website owner, to easily collect payments w/o a merchant account.  Even so, there are times when I&#8217;ve sought an alternative.  It&#8217;s not often, but occasionally, PayPal goes down and online sales begin to suffer.&lt;/p&gt;


	&lt;p&gt;So, I was very pleased to find out about Google Checkout, another way to collect money online.  After reading through the documentation and beginning to implement a simple payment system I was stopped dead in my tracks by some egregious flaws.&lt;/p&gt;


	&lt;p&gt;1) Users must already have, or create, a Google account&lt;/p&gt;


	&lt;p&gt;There is a non-trivial percentage of customers that are going to walk when they see that, and I&#8217;m not sure that I blame them.&lt;/p&gt;


	&lt;p&gt;2) The setup process is somewhat involved&lt;/p&gt;


	&lt;p&gt;If you require real-time online payment processing, the Google setup may be somewhat more complex than PayPal.  To use the equivalent of Instant Payment Notifications (IPN) in GoogleCheckout, you have to first send Google information about what the user is wanting to purchase.  Whereas using PayPal, you simply let PayPal notify your server-side script as to what was purchased.&lt;/p&gt;


	&lt;p&gt;After you inform Google what the person is purchasing, you then forward the person to GoogleCheckout and wait for Google to notify you about the transaction.  Here&#8217;s where it gets bad.  When Google notifies you, they force you to be notified over &lt;span class='caps'&gt;SSL&lt;/span&gt; using a valid certificate from a Certificate Authority.  That&#8217;s going to cost some money, especially if you have a load balanced configuration with multiple servers processing payments.  No thanks Google&#8212;I&#8217;ll stick with PayPal.&lt;/p&gt;


	&lt;p&gt;3) GoogleCheckout does not allow the purchaser to be redirected to a &lt;span class='caps'&gt;URL&lt;/span&gt; after the purchase is completed&lt;/p&gt;


	&lt;p&gt;This is a &lt;span class='caps'&gt;MUST&lt;/span&gt;.  When a user purchases something online, they want to immediately gain access to it.  There has to be a way to send that user back to a custom &lt;span class='caps'&gt;URL&lt;/span&gt; after purchase&#8212;&lt;span class='caps'&gt;BUT&lt;/span&gt; GoogleCheckout doesn&#8217;t provide this.&lt;/p&gt;


	&lt;p&gt;So, you see, don&#8217;t be fooled by Google&#8217;s tempting $0 fees until 2008.  The truth is that Google Checkout is not ready for primetime, unless perhaps you are selling tangibles.&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-04-14:/article/2007/4/14/rubygems-zlib-rails-problems</id>
    <published>2007-04-14T16:14:00Z</published>
    <updated>2007-04-14T16:14:00Z</updated>
    <category term="Ruby"/>
    <link href="http://blog.votanweb.com/2007/4/14/rubygems-zlib-rails-problems" rel="alternate" type="text/html"/>
    <title>Problems w/ Zlib, Ruby, Gems, Rails?</title>
<content type="html">&lt;p&gt;If you experience problems with zlib and rubygems you are not alone.  With practically every Rails installation that I&#8217;ve done, I have encountered some sort of problem with zlib and rubygems.  So, I wanted to highlight my latest installation woes in case anyone else out there could benefit from the steps that I took.  Here we go&#8230;&lt;/p&gt;


	&lt;p&gt;I&#8217;m starting with a hefty 2 x dual core &lt;span class='caps'&gt;AMD 64&lt;/span&gt; Opteron machine and this is what I do.  
- I grab the latest Ruby source (1.8.5).  
- I&#8217;m also a big fan of Yum, the nifty package manager that makes installation and maintenance of Linux machines a breeze (well, not always), so I use Yum to grab needed developer packages like gcc, gcc-cpp, zlib, and the corresponding &#8220;-devel&#8221; packages. 
-  I configure, make, make install Ruby
-  I grab the latest RubyGems source (0.9.2) and install it
- I then attempt to install Rails with dependencies (gem install rails&#8212;include-dependencies), but I get the following error:
gzip error installing rake-0.7.2.gem
- After searching on the web and finding nothing helpful, I decide to try removing the current ruby gems installation and using rubygems 0.9.0
- Unfortunately, this just causes another error related to zlib:  gzip error installing sources-0.0.1.gem
- Finally, here&#8217;s what fixed the problem:
1) uninstall ruby (recursively delete the main ruby folder)
2) install zlib 1.2.3 from source
3) re-install Ruby
4) re-install RubyGems&lt;/p&gt;


	&lt;p&gt;Voila&#8212;it works!  So, the moral of the story is that sometimes the Yum package manager doesn&#8217;t install zlib properly and you may need  to install from the source.&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2007-02-24:/article/2007/2/24/javascript_memory_limit</id>
    <published>2007-02-24T22:07:00Z</published>
    <updated>2007-02-24T22:07:00Z</updated>
    <category term="Web Development"/>
    <link href="http://blog.votanweb.com/2007/2/24/javascript_memory_limit" rel="alternate" type="text/html"/>
    <title>JavaScript Memory Limit</title>
<content type="html">&lt;p&gt;Ever wonder what is the maximum amount of memory Javascript is able to allocate?  I&#8217;ve been considering a Javascript app requiring a decent amount of memory and wanted to find out the answer to that question.  After searching on Google without luck, I decided it would be easier to code my own test.  Here it is:&lt;/p&gt;


&lt;table class='CodeRay'&gt;&lt;tr&gt;
  &lt;td title='click to toggle' class='line_numbers'&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class='code'&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='ta'&gt;&amp;lt;h1&lt;/span&gt; &lt;span class='an'&gt;id&lt;/span&gt;=&lt;span class='s'&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;max_mem&lt;/span&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class='ta'&gt;&amp;gt;&lt;/span&gt;Max Memory = ?&lt;span class='ta'&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='ta'&gt;&amp;lt;script&lt;/span&gt; &lt;span class='an'&gt;language&lt;/span&gt;=&lt;span class='s'&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;javascript&lt;/span&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class='ta'&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;var kilo_str = ''&lt;tt&gt;
&lt;/tt&gt;for(var i=0; i&lt;span class='ta'&gt;&amp;lt;1024&lt;/span&gt;&lt;span class='er'&gt;;&lt;/span&gt; &lt;span class='an'&gt;i&lt;/span&gt;&lt;span class='er'&gt;+&lt;/span&gt;&lt;span class='er'&gt;+&lt;/span&gt;&lt;span class='er'&gt;)&lt;/span&gt;&lt;span class='er'&gt;{&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class='an'&gt;kilo_str&lt;/span&gt; &lt;span class='er'&gt;+&lt;/span&gt;&lt;span class='er'&gt;=&lt;/span&gt; &lt;span class='er'&gt;'&lt;/span&gt;&lt;span class='an'&gt;a&lt;/span&gt;&lt;span class='er'&gt;'&lt;/span&gt;&lt;span class='er'&gt;;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='er'&gt;}&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='an'&gt;var&lt;/span&gt; &lt;span class='an'&gt;large_str&lt;/span&gt; = &lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class='er'&gt;;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='an'&gt;var&lt;/span&gt; &lt;span class='an'&gt;size&lt;/span&gt; = &lt;span class='av'&gt;1&lt;/span&gt;&lt;span class='er'&gt;;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='an'&gt;while&lt;/span&gt;&lt;span class='er'&gt;(&lt;/span&gt;&lt;span class='an'&gt;true&lt;/span&gt;&lt;span class='er'&gt;)&lt;/span&gt;&lt;span class='er'&gt;{&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class='an'&gt;large_str&lt;/span&gt; &lt;span class='er'&gt;+&lt;/span&gt;&lt;span class='er'&gt;=&lt;/span&gt; &lt;span class='an'&gt;kilo_str&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class='an'&gt;var&lt;/span&gt; &lt;span class='an'&gt;x&lt;/span&gt;=&lt;span class='av'&gt;document.getElementById&lt;/span&gt;&lt;span class='er'&gt;(&lt;/span&gt;&lt;span class='er'&gt;&amp;quot;&lt;/span&gt;&lt;span class='an'&gt;max_mem&lt;/span&gt;&lt;span class='er'&gt;&amp;quot;&lt;/span&gt;&lt;span class='er'&gt;)&lt;/span&gt;&lt;span class='er'&gt;;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class='an'&gt;x.innerHTML&lt;/span&gt; = &lt;span class='s'&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;max memory = &lt;/span&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class='er'&gt;+&lt;/span&gt; &lt;span class='an'&gt;size&lt;/span&gt; &lt;span class='er'&gt;+&lt;/span&gt; &lt;span class='er'&gt;&amp;quot;&lt;/span&gt; &lt;span class='an'&gt;kb&lt;/span&gt;&lt;span class='er'&gt;&amp;quot;&lt;/span&gt;&lt;span class='er'&gt;;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class='an'&gt;size&lt;/span&gt;&lt;span class='er'&gt;+&lt;/span&gt;&lt;span class='er'&gt;+&lt;/span&gt;&lt;span class='er'&gt;;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='er'&gt;}&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='er'&gt;&amp;lt;&lt;/span&gt;&lt;span class='er'&gt;/&lt;/span&gt;&lt;span class='an'&gt;script&lt;/span&gt;&lt;span class='ta'&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Just stick that in an &lt;span class='caps'&gt;HTML&lt;/span&gt; page and run the page.  But, before you do so, please be aware that it may crash your browser.  I ran this in Firefox and it would present me periodically with a popup asking if I wanted to stop the unresponsive script.  After letting it continue through several iterations of the popup, I stopped the script and the max memory shown on the screen was 20480 KB (~20 MB).  If I had more patience, then I could come up with a more accurate figure, but it looks like Firefox&#8217;s Javascript interpreter can allocate at least 20 MB, which is pretty fantastic!  I would bet that the amount varies per browser though.  Please note that this experiment also assumes that each character is stored as 1 byte.&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2006-11-01:/article/2006/11/1/broken-images-broken-rails</id>
    <published>2006-11-01T20:23:00Z</published>
    <updated>2006-11-01T20:23:00Z</updated>
    <link href="http://blog.votanweb.com/2006/11/1/broken-images-broken-rails" rel="alternate" type="text/html"/>
    <title>Broken Images, Broken Rails</title>
<content type="html">&lt;p&gt;One of the features of Rails that I find pretty nifty as a web developer is the ability to easily turn off sessions for parts of a web-app or for the entire web application.  This is important, because sessions on a high traffic website can cause tremendous strain on a server.  This is how you turn off sessions site-wide in Rails:
&lt;br /&gt;&lt;/p&gt;


&lt;table class='CodeRay'&gt;&lt;tr&gt;
  &lt;td title='click to toggle' class='line_numbers'&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class='code'&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='r'&gt;class&lt;/span&gt; &lt;span class='cl'&gt;ApplicationController&lt;/span&gt; &amp;lt; &lt;span class='co'&gt;ActionController&lt;/span&gt;::&lt;span class='co'&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  session &lt;span class='sy'&gt;:off&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='r'&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;&lt;br /&gt;
This turns off sessions to all controllers that inherit from ApplicationController&#8212;or at least that&#8217;s what the documentation tells you.  So, I was surprised to learn that one of my controllers was still generating sessions.  Here it is:
&lt;br /&gt;&lt;/p&gt;


&lt;table class='CodeRay'&gt;&lt;tr&gt;
  &lt;td title='click to toggle' class='line_numbers'&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class='code'&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='r'&gt;class&lt;/span&gt; &lt;span class='cl'&gt;OtherController&lt;/span&gt; &amp;lt; &lt;span class='co'&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class='r'&gt;def&lt;/span&gt; &lt;span class='fu'&gt;books&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class='r'&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='r'&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;&lt;br /&gt;
What in the world is going on here?  Of course, if you search online nobody else in the world is having the same problem, or they&#8217;re just keeping quiet about it.  Have the Rails gods screwed up (oops, blasphemy), or am I doing something wrong (probably).&lt;/p&gt;


	&lt;p&gt;&lt;br /&gt;
The answer appears to be a combination of the two.  A page rendered by OtherController happened to contain an image that was actually not present, as evidenced by the following snippet in the log files:&lt;/p&gt;


&lt;pre&gt;
ActionController::RoutingError (Recognition failed for &quot;/images/gradient_back.gif&quot;):
    /usr/lib/ruby/gems/1.8/gems/actionpack-1.12.5/lib/action_controller/routing.rb:522:in `recognition_failed'
    /usr/lib/ruby/gems/1.8/gems/actionpack-1.12.5/lib/action_controller/routing.rb:512:in `recognize!'
    /usr/lib/ruby/gems/1.8/gems/rails-1.1.6/lib/dispatcher.rb:38:in `dispatch'
&lt;/pre&gt;
&lt;br /&gt;

	&lt;p&gt;Apparently, this triggers Rails to generate a session.  Perhaps the Rails folks can rationalize this as useful, but it seems like a clear design flaw to me.  Unscrupulous users can create sessions simply by attempting to load non-existent URLs&#8212; &lt;span class='caps'&gt;BAD&lt;/span&gt;, BAD, &lt;span class='caps'&gt;BAD&lt;/span&gt;&#8230;&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2006-10-03:/article/2006/10/3/odesk-schmo-desk</id>
    <published>2006-10-03T01:37:00Z</published>
    <updated>2006-10-03T01:37:00Z</updated>
    <category term="Business"/>
    <category term="Outsourcing"/>
    <link href="http://blog.votanweb.com/2006/10/3/odesk-schmo-desk" rel="alternate" type="text/html"/>
    <title>oDesk schmo-desk</title>
<content type="html">&lt;p&gt;Perhaps you&#8217;ve been looking for some talent to supplement your team.  Or, maybe you have no team and you&#8217;d like to build one with inexpensive, offshore workers.  You&#8217;re not alone.  More and more people are jumping at the opportunities presented by small-scare outsourcing.  The concept seems pretty simple, yet from my own recent experiences, it&#8217;s harder than it looks.&lt;/p&gt;


	&lt;p&gt;I recently posted a Job Opportunity on oDesk for a Ruby developer with a few years of experience.  Within a few days I had received a handful of responses from developers that were either A) inexperienced, B) unqualified, or C) had poor ratings.  So, following the advice of the helpful oDesk staff, I searched for prospective workers and contacted them directly about setting up a virtual interview via instant messenger.  No dice.  0 for 4.  The workers are in the system, but they don&#8217;t seem to respond, which makes me wonder how many of these people are actively using oDesk.&lt;/p&gt;


	&lt;p&gt;In summary, the concept of oDesk seems great&#8212;pre-screened workers, detailed oversight of hours and productivity, and easy payment.  However, no matter how great the system may be, it is nothing without a supply of high-quality workers.&lt;/p&gt;</content>  </entry>
  <entry>
    <author>
      <name>admin</name>
    </author>
    <id>tag:blog.votanweb.com,2006-09-13:/article/2006/9/13/microsoft-search-misses-the-mark-again</id>
    <published>2006-09-13T09:17:00Z</published>
    <updated>2006-09-13T09:17:00Z</updated>
    <category term="Search Engines"/>
    <link href="http://blog.votanweb.com/2006/9/13/microsoft-search-misses-the-mark-again" rel="alternate" type="text/html"/>
    <title>Microsoft Search Misses the Mark AGAIN</title>
<summary type="html">&lt;p style='float:left'&gt;&lt;img src='http://blog.votanweb.com/assets/2006/9/13/live_search.png' alt='' /&gt;&lt;/p&gt;


	&lt;p&gt;You don&#8217;t have to do many searches on Microsoft&#8217;s newly unveiled &#8220;Live Search&#8221; to realize that it still falls far short of Google.  One revealing search is to type in &#8216;bulldog&#8217; in Live Search.  The majority of Microsoft&#8217;s first page of search results have nothing to do with bulldogs.  They are simply sites whose business name includes bulldog.&lt;/p&gt;


	&lt;p&gt;On the other hand&#8230;&lt;/p&gt;</summary><content type="html">&lt;p style='float:left'&gt;&lt;img src='http://blog.votanweb.com/assets/2006/9/13/live_search.png' alt='' /&gt;&lt;/p&gt;


	&lt;p&gt;You don&#8217;t have to do many searches on Microsoft&#8217;s newly unveiled &#8220;Live Search&#8221; to realize that it still falls far short of Google.  One revealing search is to type in &#8216;bulldog&#8217; in Live Search.  The majority of Microsoft&#8217;s first page of search results have nothing to do with bulldogs.  They are simply sites whose business name includes bulldog.&lt;/p&gt;


	&lt;p&gt;On the other hand, a search for bulldog on Google reveals solid results at the top of the page, with some not-so-good results near the bottom&#8212;precisely what you&#8217;d hope for.&lt;/p&gt;


	&lt;p&gt;See for yourself!&lt;/p&gt;


	&lt;p&gt;&lt;a href='http://beta.search.live.com/results.aspx?q=bulldog&#38;mkt=en-us'&gt;Live Search for &#8216;bulldog&#8217;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href='http://www.google.com/search?q=bulldog'&gt;Google Search for &#8216;bulldog&#8217;&lt;/a&gt;&lt;/p&gt;</content>  </entry>
</feed>
