<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>Onehub blog</title>
    <link>http://onehub.com</link>
    <language>en</language>
    <webMaster>info@onehub.com (Chuck Mount)</webMaster>
    <copyright>Copyright 2008-2009</copyright>
    <ttl>60</ttl>
    <pubDate>Thu, 29 Oct 2009 03:15:00 GMT</pubDate>
    <description>Happenings at a stealth mode startup</description>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/onehubblog" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>Incremental Improvements to the Onehub Bar</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/yzrgC_jNd_4/</link>
      <pubDate>Thu, 29 Oct 2009 03:09:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/10/29/incremental_improvements_onehub_bar/</guid>
      <author>manderson@onehub.com (Matthew Anderson)</author>
      <description>&lt;p&gt;As most of you probably already noticed, we made some incremental improvements to the Onehub bar last night. I thought I would take a quick second to outline what changes were made and why we made them.&lt;/p&gt;

&lt;h3&gt;Out with the old&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://onehub.com/assets/images/onehub-bar-old.png" alt="Screenshot" title="Onehub Bar (Old)"/&gt;&lt;/p&gt;

&lt;p&gt;The old Onehub bar served us well; however, there were a couple of issues with it that needed to be addressed.&lt;/p&gt;

&lt;h5&gt;1. It was only available in Hubs&lt;/h5&gt;

&lt;h5&gt;2. Personal settings (profiles) were getting buried&lt;/h5&gt;

&lt;h5&gt;3. Not enough horizontal space for new features&lt;/h5&gt;

&lt;h5&gt;4. We can't reveal this one just yet - it's a secret, &lt;a href="http://twitter.com/Onehub" title="Onehub on Twitter"&gt;follow us on Twitter&lt;/a&gt;&lt;/h5&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;In with the new&lt;/h3&gt;

&lt;p&gt;The Onehub bar now persists everywhere. No matter where you are in the service, you can always rely on the Onehub bar to get you around. Second, we moved some of the existing links in to drop-down menus. This also allowed us to add some new ones. Now, everything is within a single click (or a hover and a click). Below is a screenshot of my Onehub bar.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://onehub.com/assets/images/onehub-bar-new.png" alt="Screenshot" title="Onehub Bar (New)"/&gt;&lt;/p&gt;

&lt;h3&gt;The breakdown&lt;/h3&gt;

&lt;h5&gt;A. The Onehub logo&lt;/h5&gt;

&lt;p&gt;Just like before, this will always take you &lt;strong&gt;home&lt;/strong&gt; to the main management area of Onehub.&lt;/p&gt;

&lt;h5&gt;B. Hubs&lt;/h5&gt;

&lt;p&gt;Clicking Hubs will also take you home. Hovering over Hubs will trigger a drop-down listing all of your available Hubs. Just like before, you can click on a Hub name to quickly jump to that Hub.&lt;/p&gt;

&lt;h5&gt;C. You&lt;/h5&gt;

&lt;p&gt;We've added your profile picture and your full name to the Onehub bar. Clicking on your picture will allow you to change it. Clicking on your name takes you to your Profile area. Hovering over your name will trigger a drop-down listing all of your profile settings individually.&lt;/p&gt;

&lt;h5&gt;D. Search&lt;/h5&gt;

&lt;p&gt;Hovering over Search will drop down a search box. Type in whatever you're looking for, then click the search button or hit &lt;strong&gt;enter&lt;/strong&gt;. Just like before, if you are in a particular Hub at the time, your search will automatically be constrained to search only that Hub. If you are outside of a Hub, your search will be global.&lt;/p&gt;

&lt;h5&gt;E. Help&lt;/h5&gt;

&lt;p&gt;Hovering over Help will trigger a drop-down listing all of our available help resources (much to the delight of our Support team).&lt;/p&gt;

&lt;h3&gt;Just the tip of the iceberg&lt;/h3&gt;

&lt;p&gt;These improvements help pave the way for some very exciting things that are coming in the near future. After your eyes adjust and you get used to the changes - we hope you like them. As always, customer feedback is very important to us. So, If you have any praise or concern about the new Onehub bar, we would love to hear it.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/yzrgC_jNd_4" height="1" width="1"/&gt;</description>
      <category domain="http://onehub.com/past/tags/design">design</category>
      <category domain="http://onehub.com/past/tags/ui">ui</category>
    <feedburner:origLink>http://onehub.com/past/2009/10/29/incremental_improvements_onehub_bar/</feedburner:origLink></item>
    <item>
      <title>What does IT mean?</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/L0WRqtnn41M/</link>
      <pubDate>Tue, 20 Oct 2009 23:47:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/10/21/what_does_it_mean/</guid>
      <author>bmoran@onehub.com (Brian Moran)</author>
      <description>&lt;p&gt;Sometimes it's not about technology, even while it is. &lt;/p&gt;

&lt;p&gt;My kids are trying to figure out a way pool their money to buy a new Microsoft XBOX when it comes out in a couple of days. &lt;/p&gt;

&lt;p&gt;Unfortunately I have also been trying to revive a Windows XP machine that 'woke up dead' from an overnight Windows Update. "Great, all we needed was another Microsoft product right now. We need another IT person around here" I grumbled.&lt;/p&gt;

&lt;p&gt;My middle child (the biggest gamer in the household, all of ten), asked what "IT" meant. &lt;/p&gt;

&lt;p&gt;Quick as a whip, my wife replied "Insensitive Toad."  &lt;/p&gt;

&lt;p&gt;Guess I'm waiting for some "amphibians from Microsoft" to call me back.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/L0WRqtnn41M" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://onehub.com/past/2009/10/21/what_does_it_mean/</feedburner:origLink></item>
    <item>
      <title>Using Godaddy SSL Certificates with NGINX</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/l-l7EkAC714/</link>
      <pubDate>Fri, 02 Oct 2009 02:24:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/10/2/using_godaddy_ssl_certificates_with/</guid>
      <author>bmoran@onehub.com (Brian Moran)</author>
      <description>&lt;p&gt;Have you just installed your new Godaddy certificate into your NGINX web server, and are you finding that some browsers (notably Safari) don't trust your website when using your Godaddy SSL Certificate? &lt;/p&gt;

&lt;p&gt;This is manifest by the error message "Safari can't identify the identity of the website 'your.url.here'" and is caused by the "chain of trust" being incomplete between your certificate and any of the root certificates that your browser client has installed.&lt;/p&gt;

&lt;p&gt;Here's a quick cure for an NGINX installation:&lt;/p&gt;

&lt;p&gt;Download the gd_bundle.crt and gd_intermediate.crt certificates from &lt;a href="https://certs.godaddy.com/anonymous/repository.seam"&gt;Godaddy's certificate repository&lt;/a&gt;, then combine them:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cat yourcert.crt gd_intermediate.crt gd_bundle.crt &amp;gt; yourcert_bundle.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This concatenates your certificate and the Godaddy intermediate certificates into one file.&lt;/p&gt;

&lt;p&gt;Put the file yourcert_bundle.crt in the place that NGINX is looking for your certs (specified in nginx.conf). &lt;/p&gt;

&lt;p&gt;Reload your NGINX configuration with &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;kill -HUP &amp;lt;pid of nginx&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should be ready to go!&lt;/p&gt;

&lt;p&gt;If you want more information on the entire chain of trust, you can download the Godaddy root certificate (gd-class2-root.crt) and use the OpenSSL command utility:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;openssl s_client -CAfile gd-class2-root.crt -connect www.yourdomain.com:443  -verify 10
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will pull the certificate from yourdomain.com server, and attempt to verify the chain of trust to whatever root you've specified (-CAfile gd-class2-root.crt):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;verify depth is 10
CONNECTED(00000003)
depth=2 /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
verify return:1
depth=1 /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=07992287
verify return:1
depth=0 /O=*.yourdomain.com/OU=Domain Control    Validated/CN=*.yourdomain.com
verify return:1
&amp;mdash;-
Certificate chain
 0 s:/O=*.yourdomain.com/OU=Domain Control Validated/CN=*.yourdomain.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=07992287
 1 s:/O=*.yourdomain.com/OU=Domain Control Validated/CN=*.yourdomain.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=07992287
 2 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=07992287
   i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
&amp;mdash;-
Server certificate
&amp;lt;Continued Output&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This shows that the certificate obtained from the site was verified all the way to a root certificate (specified by -CAfile).&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/l-l7EkAC714" height="1" width="1"/&gt;</description>
      <category domain="http://onehub.com/past/tags/certificate">certificate</category>
      <category domain="http://onehub.com/past/tags/godaddy">godaddy</category>
      <category domain="http://onehub.com/past/tags/nginx">nginx</category>
      <category domain="http://onehub.com/past/tags/safari">safari</category>
    <feedburner:origLink>http://onehub.com/past/2009/10/2/using_godaddy_ssl_certificates_with/</feedburner:origLink></item>
    <item>
      <title>Partial Insight</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/hAYb2rN2rp8/</link>
      <pubDate>Wed, 30 Sep 2009 02:22:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/9/30/partial_insight/</guid>
      <author>loe@onehub.com (W. Andrew Loe III)</author>
      <description>&lt;p&gt;Sooner or later every web application is going to need to render HTML to its users, but keeping this view code modular, reusable, and consistent can be quite a challenge. DRY, Don't Repeat Yourself, is one of the guiding design principles of Ruby on Rails, and no where is it more evident than in Action View's templating system. Rails' tempting encourages the use of partials, small templates can be used all over the application. However, there is a cost to this flexibility, it is common for developers to end up with complex series of nested partials, turning a simple-to-fix HTML glitch into a full-on search expedition. &lt;a href="http://github.com/loe/partial_insight" title="Partial Insight"&gt;Partial Insight&lt;/a&gt; is a simple plugin that injects template filenames in HTML comments as each template is rendered. This ingenious idea has the potential to save millions of developer hair follicles annually, assuming there are any left...&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/hAYb2rN2rp8" height="1" width="1"/&gt;</description>
      <category domain="http://onehub.com/past/tags/code">code</category>
      <category domain="http://onehub.com/past/tags/plugin">plugin</category>
      <category domain="http://onehub.com/past/tags/rails">rails</category>
    <feedburner:origLink>http://onehub.com/past/2009/9/30/partial_insight/</feedburner:origLink></item>
    <item>
      <title>We're Hiring for Inside Sales</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/uL9svzwUrrk/</link>
      <pubDate>Tue, 29 Sep 2009 04:55:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/9/29/were_hiring_for_inside_sales/</guid>
      <author>cmount@onehub.com (Charles Mount)</author>
      <description>&lt;h3&gt;We are looking for a highly driven sales professional to help drive growth of the Onehub service.&lt;/h3&gt;

&lt;p&gt;Onehub is a fast-paced, energetic environment where we work hard and play hard too. Onehub provides file sharing and collaboration web apps for business users and is looking for the right person to help accelerate growth. &lt;/p&gt;

&lt;h3&gt;What we are looking for in the right candidates&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Strong telesales background with experience selling software or software services over the phone&lt;/li&gt;
&lt;li&gt;Understanding of business web applications and ability to demonstrate to customers via web conferencing tools&lt;/li&gt;
&lt;li&gt;Ability and willingness to jump in and get things done in a fast-paced startup environment&lt;/li&gt;
&lt;li&gt;Previous experience working with Salesforce.com&lt;/li&gt;
&lt;li&gt;Track record of consistently exceeding quota&lt;/li&gt;
&lt;li&gt;Great attitude and strong work ethic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Email us at jobs@onehub.com to learn more!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/uL9svzwUrrk" height="1" width="1"/&gt;</description>
      <category domain="http://onehub.com/past/tags/hiring">hiring</category>
    <feedburner:origLink>http://onehub.com/past/2009/9/29/were_hiring_for_inside_sales/</feedburner:origLink></item>
    <item>
      <title>The Joy of Calendars</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/jpzeN5X1OZc/</link>
      <pubDate>Mon, 28 Sep 2009 04:19:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/9/28/the_joy_of_calendars/</guid>
      <author>lcaplan@onehub.com (Leigh Caplan)</author>
      <description>&lt;p&gt;Calendars are an essential part of many personal organization tools– they also predate computers by several thousand years, so you would think that implementing a shared web calendar would be relatively simple, given the tools at a modern programmer's disposal and the long precedent set by previous implementations. Oh, but you would be wrong. So, so wrong.&lt;/p&gt;

&lt;p&gt;Granted, there are many difficult problems already solved by many dedicated people, and their solutions are available to the programming community at large. Date parsing and calculations, time zone offset calculations... if one programmer had to handle all of these issues, they could spend years getting the implementations right (and many programmers undoubtedly have). I'm lucky enough to be using Rails, so for me, working with dates is at times incredibly easy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;today         = Date.today
next_week     = today + 1.week
two_days_ago  = today - 2.days
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This may seem like "cute" syntactic sugar, but it really smoothes over a lot of the mental overhead involved with date calculations, and lets you focus on the problem domain at hand. I can easily throw out snippets like &lt;code&gt;Date.today + 1.month&lt;/code&gt; without having to worry about how many days are in this month or if next month has less days than this month, etc.&lt;/p&gt;

&lt;p&gt;Anyway, enough gushing about ActiveSupport. Today I want to offer an example of an issue for which there *is* no easy software solution, because, like so many time-related programming issues, it's a human problem.&lt;/p&gt;

&lt;p&gt;&lt;a name="allday"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;All-day events: What could possibly go wrong?&lt;/h3&gt;

&lt;p&gt;Let's say Professor Farnsworth, CEO of Planet Express (a large multinational company) is setting up a company holiday calendar. "Good news, everyone!" he exclaims, "all PlanEx employees get the Thanksgiving holiday off of work!"&lt;/p&gt;

&lt;p&gt;In order to ensure that everyone's on the same page, he creates an all-day event in the company's shared calendar spanning November 19th and November 20th. Now, Professor Farnsworth and his office staff reside in the sprawling metropolis of New New York, so their calendars all show events in Eastern Standard Time. However, Mr. Zoid in the Los Angeles satellite office notices something strange. When he looks at the calendar, it appears to last all day Wednesday, Thursday, &lt;em&gt;and&lt;/em&gt; Friday (November 18-20). Obviously this is a bug. Or is it?&lt;/p&gt;

&lt;p&gt;It depends on who you ask. The problem stems from the ambiguity of the meaning of "all-day." In general, calendars need to deal with discrete units of time. For instance, when I make an appointment from 2-3pm Eastern time on September 9th, I've specified a span of time that everyone can agree on. If you're on the west coast, this appointment will occur from 11am-12pm, but if we were scheduling a conference call, we'd both pick up the phone at the correct time. When Farnsworth says that he wants an event to occur all day on November 19th and 20th, most calendar programs will mark the event so that it displays differently than regular timed events (showing "all-day" for the duration rather than the start and end times) but in the background, an event is created which starts at 12am on the 19th and ends at 11:59pm on the 20th.&lt;/p&gt;

&lt;p&gt;If I'm on the west coast, the start and end times of the all-day event will be shifted 3 hours earlier, so from my perspective, the event actually starts at 9pm on November 18th and ends at 8:59pm on November 20th. Since it's still displayed as an all-day event, it will appear to last &lt;em&gt;three days&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For a lot of people, this behavior is unexpected, but a lot of calendar programs actually work this way (Microsoft Outlook being a notable example). Some other programs, such as Apple iCal, handle all-day event display differently, and always show them on the same day(s) regardless of time zone. When the people sharing a calendar are all within a few time zones of each other, this is probably the most expected behavior, however there are cases when even this breaks down.&lt;/p&gt;

&lt;p&gt;Imagine I have a business in Honolulu, and my company has a satellite office in Tokyo. In my time zone, I set an all-day company holiday for November 19th (we're using a one-day event here for simplicity's sake). Our Tokyo office looks at their calendar, plans accordingly, and everyone there takes November 19th as a free day to spend with their family. All is well, until someone from our Honolulu office calls someone from our Tokyo office on the 18th regarding an urgent piece of business, and finds that nobody is there. As it turns out, Tokyo is 19 hours ahead of Honolulu, so most of November 18th in Honolulu takes place on November 19th in Tokyo. The holiday should have shown up on November 20th for the Tokyo office.&lt;/p&gt;

&lt;p&gt;Calendars are full of edge cases and compromises like this, and oftentimes there is no answer which is definitively "right"... there's only "wrong" and "less wrong".&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/jpzeN5X1OZc" height="1" width="1"/&gt;</description>
      <category domain="http://onehub.com/past/tags/calendar">calendar</category>
      <category domain="http://onehub.com/past/tags/development">development</category>
    <feedburner:origLink>http://onehub.com/past/2009/9/28/the_joy_of_calendars/</feedburner:origLink></item>
    <item>
      <title>Customizing Zendesk</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/KfWYmKOZric/</link>
      <pubDate>Tue, 22 Sep 2009 03:09:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/9/22/customizing_zendesk/</guid>
      <author>mtierney@onehub.com (Michael Tierney)</author>
      <description>&lt;p&gt;We use &lt;a href="http://zendesk.com"&gt;Zendesk&lt;/a&gt; for our support site, but even though it's a third party site we want our users to feel right at home when they are visiting there. In order to accomplish this, we have made use of Zendesk's impressive customization options, which let us write our own custom CSS and Javascript.&lt;/p&gt;

&lt;h3&gt;It's All About the Widgets&lt;/h3&gt;

&lt;p&gt;As part of Zendesk's service, users have access to an array of "widgets" that can be leveraged to customize your presence. These widgets have the capacity to be exposed to as many, or as few, end users as you'd like. Zendesk breaks it down into three groups &amp;ndash; "Agents," or members of the support team, "Logged in end-users" and "Anyone." For our customization, I used the CSS and Javascript widgets.&lt;/p&gt;

&lt;p&gt;I broke up my CSS into two widgets &amp;ndash; one for all users, and one just for Agents, since Zendesk offers added functionality for Agents that's not present for everyone else. The bulk of my CSS was applied to the Everyone stylesheet, and then I just tweaked the Admin stylesheet to account for the differing interface elements.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://onehub.com/assets/images/zendesk_widgets.png" alt="Zendesk's CSS and Javascript Widgets"/&gt;&lt;/p&gt;

&lt;h3&gt;Javascript to the Rescue!&lt;/h3&gt;

&lt;p&gt;The trickiest aspect to this customization was that I needed more "hooks" (unique identifiers) to attach CSS rules to than I was provided. I applied a handful of scripts that used Prototype's &lt;code&gt;addClassName&lt;/code&gt; method to get some extra classes (my biggest target was the navigation links). We also wanted to update some of the links in the header of the Support site. Unfortunately, Zendesk doesn't offer any mechanism to adjust those links through their management console, but Javascript again came to the rescue. Using Prototype's &lt;code&gt;update&lt;/code&gt; method we changed the content of a handful of the navigational links, and then with &lt;code&gt;insert&lt;/code&gt; we added a few new links (back to the main site, for example). This was all relatively painless, and so far has worked without issue.&lt;/p&gt;

&lt;h3&gt;Something to Keep in Mind&lt;/h3&gt;

&lt;p&gt;Widgets (at least the CSS and JS widgets) are loaded in alphabetical order. So if you name you CSS widgets 'admin' and 'everyone,' the 'admin' widget is going to get loaded first, which means that anything you're trying to reset in the 'everyone' stylesheet won't work. In order to offset this, and still give the widgets meaningful names, I just numbered them &amp;ndash; "1 - Everyone", "2 - Admin," etc. With the Javascript widgets you'll want to keep this in mind, too, since occasionally load order is important.&lt;/p&gt;

&lt;p&gt;Also, the presented experience varies widely from user to user, with the forms that are being filled out and the different potential use cases for the application, so make sure to test as many of those paths as possible. Submit forms as an anonymous user, then have an Agent interact with that ticket, and make sure that all of the presented experiences are what you would expect. This does mean that you'll clutter up your help desk a bit, but you can always go back in and remove the extraneous content before you deploy the site.&lt;/p&gt;

&lt;p&gt;Customing Zendesk was largely an easy and pleasant experience. Getting all of the pieces in place was simple, and load times weren't noticeably hampered by our customization. Furthermore, when we had questions, Zendesk's support crew were quick to respond with informative answers that solved our problems quickly. Feel free to check out our &lt;a href="http://help.onehub.com"&gt;support site&lt;/a&gt; and let us know what you think!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/KfWYmKOZric" height="1" width="1"/&gt;</description>
      <category domain="http://onehub.com/past/tags/css">css</category>
      <category domain="http://onehub.com/past/tags/javascript">javascript</category>
      <category domain="http://onehub.com/past/tags/support">support</category>
      <category domain="http://onehub.com/past/tags/zendesk">zendesk</category>
    <feedburner:origLink>http://onehub.com/past/2009/9/22/customizing_zendesk/</feedburner:origLink></item>
    <item>
      <title>Introducing Invitation Email Templates</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/N-iZIFPjo7A/</link>
      <pubDate>Fri, 18 Sep 2009 02:50:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/9/18/custom_email_templates/</guid>
      <author>bcaplan@onehub.com (Brandon Caplan)</author>
      <description>&lt;p&gt;&lt;strong&gt;Invitations&lt;/strong&gt; are a very important part of Onehub. It is generally the &lt;strong&gt;first thing&lt;/strong&gt; your clients and coworkers see when you first &lt;strong&gt;invite them to collaborate&lt;/strong&gt;. Because of this, we have seen a lot of requests for the ability to &lt;strong&gt;save these messages&lt;/strong&gt; and have more &lt;strong&gt;control over their contents&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While you could always customize them, we didn't offer full control over all of the text in the invitations or the ability to save them. This has been drastically improved with one of our latest new features, Email Templates featuring Auto Fields.&lt;/p&gt;

&lt;p&gt;With all of our plans, you can now add special pieces of text we call Auto Fields that will automatically be replaced with information (such as the name of the person you are inviting) when the invitation is sent. On the Team Edition of Onehub and above you can also save these templates and assign certain ones to be the default template on a Hub by Hub basis.&lt;/p&gt;

&lt;h3&gt;Using Auto Fields&lt;/h3&gt;

&lt;p&gt;The list of available Auto Fields can always be found on the right side of the screen whenever you are editing an Email Template or sending a custom invitation. This makes it easy to copy and paste them into your message.&lt;/p&gt;

&lt;p&gt;Each Auto Field is surrounded by double curly braces to distinguish it from the rest of your message:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;&lt;code&gt;Please join the {{ hub.name }} Hub by clicking here: {{ accept_link }}&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can place them anywhere in the message you would like. All of them are optional except for the accept link. This is needed to accept the invitation, after all.&lt;/p&gt;

&lt;h3&gt;Creating Email Templates&lt;/h3&gt;

&lt;p&gt;Email templates are created and managed from the &lt;em&gt;Account&lt;/em&gt; tab in the &lt;em&gt;Email Templates&lt;/em&gt; section. From here you can also set a template to be the default for all of your account Hubs. When creating the template you can provide the text that will appear in both the subject and the body of the email.&lt;/p&gt;

&lt;p&gt;Default Email Templates can also be set for individual Hubs in the Hub's &lt;em&gt;Manage&lt;/em&gt; section under &lt;em&gt;Email Templates&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://onehub.com/assets/images/create_email_template.png" alt="New Email Template" title="Creating an Email Template"/&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/N-iZIFPjo7A" height="1" width="1"/&gt;</description>
      <category domain="http://onehub.com/past/tags/email">email</category>
      <category domain="http://onehub.com/past/tags/feature">feature</category>
    <feedburner:origLink>http://onehub.com/past/2009/9/18/custom_email_templates/</feedburner:origLink></item>
    <item>
      <title>Introducing the Onehub Wiki Widget</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/Os_9g7GNQr0/</link>
      <pubDate>Thu, 17 Sep 2009 01:00:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/9/17/introducing_the_onehub_wiki_widget/</guid>
      <author>bcaplan@onehub.com (Brandon Caplan)</author>
      <description>&lt;p&gt;Today we released the newest Onehub widget, the &lt;strong&gt;Wiki Widget&lt;/strong&gt;. The Wiki Widget allows &lt;strong&gt;collaborative rich text editing&lt;/strong&gt;. With features such as inline images, tables, lists, and a complete revision history. It's a great way to &lt;strong&gt;collaborate on text-based content&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Wiki Widget is replacing the Text Widget. While existing Text Widgets will remain, the option to create new ones has been removed.&lt;/p&gt;

&lt;h3&gt;Editing For All&lt;/h3&gt;

&lt;p&gt;The Text Widget required you to be in design mode to make changes. This locked Contributors out of editing. With the Wiki Widget, Contributors can now edit because the edit button is always visible.&lt;/p&gt;

&lt;h3&gt;Revisions&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://onehub.com/assets/images/wiki_revisions.png" style="float: left; margin-right: 10px;"&gt;&lt;/p&gt;

&lt;p&gt;The Wiki Widget saves all edits as a new revision. This allows you to always revert to previous versions just in case you don't like the changes that were made.&lt;/p&gt;

&lt;div style="clear: both;"&gt;&lt;/div&gt;

&lt;h3&gt;Source Editing&lt;/h3&gt;

&lt;p&gt;For those with HTML knowledge, you can now manually edit the source of the wiki for even greater control over how it looks.&lt;/p&gt;

&lt;h3&gt;What Else is New?&lt;/h3&gt;

&lt;p&gt;Along with a beautiful and easy to use edit interface, here are some other great features that can be found in the Wiki Widget:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choice of 11 fonts, with 7 sizes&lt;/li&gt;
&lt;li&gt;Bold, italic, underline, and strike-through styles&lt;/li&gt;
&lt;li&gt;Text indenting and block quoting&lt;/li&gt;
&lt;li&gt;Images&lt;/li&gt;
&lt;li&gt;Tables&lt;/li&gt;
&lt;li&gt;Full screen edit view for when you need more room&lt;/li&gt;
&lt;/ul&gt;

&lt;hr/&gt;

&lt;p&gt;&lt;p /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://onehub.com/assets/images/wiki_widget.png" alt="Wiki Widget"/&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/Os_9g7GNQr0" height="1" width="1"/&gt;</description>
      <category domain="http://onehub.com/past/tags/collaboration">collaboration</category>
      <category domain="http://onehub.com/past/tags/feature">feature</category>
      <category domain="http://onehub.com/past/tags/widget">widget</category>
      <category domain="http://onehub.com/past/tags/wiki">wiki</category>
    <feedburner:origLink>http://onehub.com/past/2009/9/17/introducing_the_onehub_wiki_widget/</feedburner:origLink></item>
    <item>
      <title>Adding Columns to large MySQL Tables Quickly</title>
      <link>http://feedproxy.google.com/~r/onehubblog/~3/vGdv_tKoHbw/</link>
      <pubDate>Tue, 15 Sep 2009 01:57:00 GMT</pubDate>
      <guid isPermaLink="false">http://onehub.com/past/2009/9/15/adding_columns_to_large_mysql_tables/</guid>
      <author>bmoran@onehub.com (Brian Moran)</author>
      <description>&lt;p&gt;Suppose that you have a MySQL Database, and in that database you have a non-trivial table with more than a million records. If you're using that table with your Rails application, you might at some point like to add some additional columns.&lt;/p&gt;

&lt;p&gt;It's tempting to just write the migration like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class AddThreeColumnsToQuarks &amp;lt; ActiveRecord::Migration
  def self.up
    add_column :quarks, :arbitrary_field1, :integer
    add_column :quarks, :arbitrary_field2, :string
    add_column :quarks, :arbitrary_field3, :integer
  end

  def self.down
    remove_column :quarks, :arbitrary_field1
    remove_column :quarks, :arbitrary_field2
    remove_column :quarks, :arbitrary_field3
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Should you do that, you will find that although it works, MySQL will take a fantastic amount of time to add the column when you have a lot of rows. What ActiveRecord is doing is adding each column individually with an alter statement:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ALTER TABLE `quarks` ADD `arbitrary_field1` int(11)
ALTER TABLE `quarks` ADD `arbitrary_field2` varchar(255)
ALTER TABLE `quarks` ADD `arbitrary_field3` int(11)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Each one of those ALTER statements makes a new temporary table, copies records from your existing table into the new table, and then replaces the old table with the new table.  Five thousand records in the database? Adding three columns will copy the DB three times. Fifteen thousand rows are copied. &lt;/p&gt;

&lt;p&gt;One can make this better by combining the ALTERs into one statement (as long as the ALTER contains a single type of operation, such as ADD COLUMN). The copy of the data in the table still takes a while. A few million rows? You might be waiting tens of minutes.&lt;/p&gt;

&lt;p&gt;A FASTER way of adding columns is to create your own new table, then SELECT all of the rows from the existing table into it. You can create the structure from the existing table, then modify the structure however you'd like, then SELECT in the data. &lt;em&gt;MAKE SURE&lt;/em&gt; that you SELECT the information into the new table in the same order as the fields are defined. Here's an example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class AddThreeColumnsToQuarks &amp;lt; ActiveRecord::Migration
  def self.up
    sql = ActiveRecord::Base.connection()
    sql.execute "SET autocommit=0"
    sql.begin_db_transaction
    sql.execute("CREATE TABLE quarks_new LIKE quarks")
    add_column :quarks_new, :arbitrary_field1, :integer
    add_column :quarks_new, :arbitrary_field2, :string
    add_column :quarks_new, :arbitrary_field3, :integer
    sql.execute("INSERT INTO quarks_new SELECT *, NULL, NULL, NULL FROM quarks")
    rename_table :quarks, :quarks_old
    rename_table :quarks_new, :quarks
    sql.commit_db_transaction
    # don't forget to remove quarks_old someday
  end

  def self.down
    drop_table :quarks
    rename_table :quarks_old, :quarks
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can change the NULLs into whatever default values you'd like the new columns in the existing rows to have.&lt;/p&gt;

&lt;p&gt;How much faster can this be? On one table in one of our databases, a single add_column was approximately 17 minutes. When we used this technique, we reduced the time to add a column to approximately 45 seconds. YMMV &amp;mdash;however you'll notice a big improvement.&lt;/p&gt;

&lt;p&gt;What about the indices? The CREATE TABLE .. LIKE preserves column attributes and indices.  For more information, see the &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/create-table.html"&gt;MySQL on line manual&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/onehubblog/~4/vGdv_tKoHbw" height="1" width="1"/&gt;</description>
      <category domain="http://onehub.com/past/tags/mysql">mysql</category>
      <category domain="http://onehub.com/past/tags/optimization">optimization</category>
      <category domain="http://onehub.com/past/tags/query">query</category>
      <category domain="http://onehub.com/past/tags/schema">schema</category>
    <feedburner:origLink>http://onehub.com/past/2009/9/15/adding_columns_to_large_mysql_tables/</feedburner:origLink></item>
  </channel>
</rss>
