tag:blogger.com,1999:blog-15390460832689261172008-07-16T19:36:46.178-07:00Michael GreenlyMike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comBlogger34125tag:blogger.com,1999:blog-1539046083268926117.post-55796862367337500752008-06-28T11:39:00.000-07:002008-06-28T11:58:14.639-07:00Determine What Version of Ubuntu You're Running?The best way to determine the version of an Ubuntu (or any LSB compliant) distribution is to use the lsb-release command:<br /><pre>$ sudo apt-get install lsb-release<br />$ lsb_release -a<br /># Distributor ID: Ubuntu<br /># Description: Ubuntu 8.04<br /># Release: 8.04<br /># Codename: hardy</pre>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-60352560481125253072008-05-03T20:32:00.001-07:002008-05-03T20:44:51.727-07:00Gemified S3Sync on GitHubI created a shallow fork of the <a href="http://s3sync.net/wiki">S3Sync</a> project specifically to wrap it as a gem. My intention is most likely to hack on it but I haven't done that yet. The code is at <a href="http://github.com/mgreenly">http://github.com/mgreenly</a> and can be installed via rubygems (gem install mgreenly-s3sync) but first you'll need to check out the instructions at <a href="http://gems.github.com/">http://gems.github.com/</a>.Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-65855919337543228072008-04-05T13:32:00.001-07:002008-04-05T15:46:03.513-07:00NetBeans on UbuntuI'm usually a hardcore <a href="http://www.vim.org/">Vim</a> fan but I've started to use <a href="http://www.netbeans.org/index.html">NetBeans</a> for my <a href="http://www.ruby-lang.org/en/">Ruby</a> work. It's a fairly typical install but the one quirk is that $JAVAHOME has to be defined for the installer and Ubuntu's JDK package doesn't set it.<br /><br />That's easily remedied though; download NetBeans, install the JDK and pass --javahome to the installer as a command line option.<pre>#> netbeans-6.0.1-ml-linux.sh --java-home /<span class="blsp-spelling-error" id="SPELLING_ERROR_0">usr</span>/lib/<span class="blsp-spelling-error" id="SPELLING_ERROR_1">jvm</span>/java-6-sun</pre>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-3338973347062286072008-04-05T09:08:00.000-07:002008-04-06T07:31:51.809-07:00Ubuntu 8.04 "Hardy Heron"The new <a href="http://www.ubuntu.com/">Ubuntu release, 8.04 "Hardy Heron"</a>, is nearly out so I thought I'd take a few minutes to do a fresh 'from scratch' install on to my laptop, a <a href="https://wiki.ubuntu.com/LaptopTestingTeam/DellLatitudeD830">Dell Latitude D830</a>, <span style="text-decoration: underline;"></span> this weekend. I was pleasently suprised that almost everything worked exactly as expected out of the box, including; wireless networking, dual head monitor support, suspend, hibernate, compiz, etc....<br /><br />There was one small but very critical change I had to make. It appears that the <a href="https://bugs.launchpad.net/ubuntu/+source/acpi-support/+bug/59695">ACPI hard drive load/unload bug</a> has still not been fixed. It's critically important that you apply <a href="https://bugs.launchpad.net/ubuntu/+source/acpi-support/+bug/59695/comments/14">this work around</a> unless you want your hard drive to die prematurely.<br /><br />There was one other non-critical change I made. I didn't dig into the issue to understand it but for what ever reason the default ALSA settings don't support the audio pass through in the docking station. Fortunately the fix is extremely simple. You just need to install the "Gnome Alsa Mixer" and select the IEC958 check box.<pre>#> sudo apt-get install gnome-alsamixer</pre><div style="text-align: left;"><br /><div style="text-align: center;"><a href="http://picasaweb.google.com/mgreenly/PublicImages/photo#5185793414446116418"><img src="http://lh4.google.com/mgreenly/R_ejooqe7kI/AAAAAAAAAR8/OWy347hnQVI/s400/Screenshot-GNOME%20ALSA%20Mixer.png" /></a><br /><br /><div style="text-align: left;">I've been running Ubuntu on this laptop since the <a href="http://releases.ubuntu.com/7.04/">7.04 Feisty Fawn</a> release and this is by far the smoothest install yet. In the past I've been reluctant to declare Ubuntu's desktop experience to be better than Windows but I think I'm finally convinced.<br /></div></div></div>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-18219247514140112012008-04-05T06:18:00.000-07:002008-04-05T06:38:58.458-07:00Setting CFLAGSIt turns out the <a href="http://gentoo-wiki.com/Main_Page">gento-wiki</a> has a great page indicating which GCC -march flag should be set for which CPUs. To determine which CPU you have, run the following at a command prompt:<br /><pre>#> cat /proc/cpuinfo</pre><br />It will yield a page of output. The first few lines of output from my laptop are below:<br /><pre>processor : 0<br />vendor_id : GenuineIntel<br />cpu family : 6<br />model : 15<br />model name : Intel(R) Core(TM)2 Duo CPU T7500 @ 2.20GHz<br />stepping : 10</pre><br />The part you're interested in is the 'cpu family' and 'model'. Once you know those find the corresponding entries on <a href="http://gentoo-wiki.com/Safe_Cflags">http://gentoo-wiki.com/Safe_Cflags</a>. Then create an entry in $HOME/.bashrc file that looks something like this:<br /><pre>CFLAGS="-march=prescott -O3"<br />CXXFLAGS="${CFLAGS}"<br />export CFLAGS CXXFLAGS</pre><br />Of course substitute the -march value for the one you found on the wiki.Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-90738716770465924512008-03-30T18:36:00.000-07:002008-03-30T19:14:10.002-07:00Cleaning Up Revision HistoriesA <a href="https://lists.ubuntu.com/archives/bazaar/2008q1/039687.html">post</a> in the the <a href="https://lists.ubuntu.com/mailman/listinfo/bazaar">bazaar</a> email group described a better approach (than I had been using) to manage merges from personal working branches. For example; If I wanted to commit a change to the project 'Foo', according to the post, I'd do something like this...<pre>$> bzr init-repo foo-branches<br />$> cd foo-branches<br />$> bzr branch http://example.com/foo-trunk trunk<br />$> bzr branch trunk workbranch<br />$> cd mybranch<br />$> # hack, commit, hack commit, repeat as necessary<br />$> cd ../trunk<br />$> bzr pull<br />$> bzr merge ../workbranch<br />$> bzr commit<br />$> bzr push<br /></pre>What I've done above is to first create a shared repository. I do this because I'm going to be working with multiple branches of the same project. Then I branch Foo's trunk into my new shared repository. Next I branch the trunk (that's in the repository) to my personal working branch, make all the changes and as many commits as I want. When I'm done I go back to the trunk. Pull it to make sure it's up to date. Then merge in my changes. Once I've done that I commit them and push them up to the server.<br /><br />If you're worried about disk space you can remove the working trees for any branch you're not currently working in.Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-11961439297333244892008-03-30T11:00:00.000-07:002008-03-30T11:18:31.740-07:00Inspirational SpeechesMy feeds contained a <a href="http://www.scrollinondubs.com/2008/03/27/inspirational-speeches/">blog post from Sean Tierney</a> in which he links to a couple of excellent speeches, both very much worth taking the time to watch. He also mentions an <a href="http://www.scrollinondubs.com/2006/03/03/opensource-goals-meme-a-social-experiment-in-becoming-write-brained/">older post of his about publicly sharing your goals</a>. Which I agree is an excellent idea and easily done with <a href="http://www.43things.com">43Things.com</a>. You can find my recently started list <a href="http://www.43things.com/person/mgreenly">here</a>.Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-63636595992524955942008-03-25T17:46:00.001-07:002008-03-25T19:39:02.080-07:00Modeling MagicI never dreamed I'd ever come to find business software an interesting domain to study but that's exactly what's happened.<br /><br />Like it was for many people, I first got interested in programming because of games. In fact I can trace my interest to a specific event; I was about 10 and I was playing a game on an <a href="http://en.wikipedia.org/wiki/Atari_8-bit_family">Atari 400</a> computer and realized I had absolutely no understanding of how it worked. Prior to that moment I thought there was nothing in the world more complex than a light switch but after that moment I wasn't so sure. I had to learn how it worked; was it magic or a light switch?<br /><br />Well of course it was a light switch, a gazillion of them all packed on to a chip in fact, but while I was learning that I came to a realization, apparently one all programmers make; The only way to demonstrate your understanding of something was to model it in software.<br /><br />So now I find myself trying to model business processes but I'm not 100% sure there's not a bit of magic in this light switch.Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-43560738221216853822008-03-25T17:28:00.000-07:002008-03-25T17:44:12.995-07:00Before Filtering HTTP Method TypesPreviously I wrote the post '<a href="http://blog.michaelgreenly.com/2008/02/method-not-allowed.html">Method Not Allowed</a>' which is about how I decided to handle unsupported HTTP <a href="http://en.wikipedia.org/wiki/HTTP#Request_methods">request method types</a> in my actions. Today I realized I should <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a> up my code and put this logic into a <a href="http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html">before filter</a>.Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-55679156865977167082008-03-23T16:30:00.000-07:002008-03-25T17:45:02.228-07:00Bzr to GitI think it's safe to say that the Rails community has decided <a href="http://git.or.cz/">git</a> is the distributed revision control tool of choice. Unfortunately for me I've been using <a href="http://bazaar-vcs.org/"><span class="blsp-spelling-error" id="SPELLING_ERROR_0">bzr</span></a> for the last year or so. Lucky for me it's easy migrate from <span class="blsp-spelling-error" id="SPELLING_ERROR_1">bzr</span> to git using <span class="blsp-spelling-error" id="SPELLING_ERROR_2">svn</span> as an intermediary.<br /><pre><span class="blsp-spelling-error" id="SPELLING_ERROR_3">svnadmin</span> create --<span class="blsp-spelling-error" id="SPELLING_ERROR_4">fs</span>-type <span class="blsp-spelling-error" id="SPELLING_ERROR_5">fsfs</span> /path/to/<span class="blsp-spelling-error" id="SPELLING_ERROR_6">svn</span>/project<br /><span class="blsp-spelling-error" id="SPELLING_ERROR_7">cd</span> /path/to/<span class="blsp-spelling-error" id="SPELLING_ERROR_8">bzr</span>/project<br /><span class="blsp-spelling-error" id="SPELLING_ERROR_9">bzr</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_10">svn</span>-push /path/to/<span class="blsp-spelling-error" id="SPELLING_ERROR_11">svn</span>/project/trunk<br />git-<span class="blsp-spelling-error" id="SPELLING_ERROR_12">svn</span> clone -T /path/to/<span class="blsp-spelling-error" id="SPELLING_ERROR_13">svn</span>/project/trunk /path/to/git/project<br /></pre>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-69618133783454305912008-02-27T16:12:00.000-08:002008-02-27T17:24:31.821-08:00GNU Apps On Windows?There's a <a href="http://www.royalidea.com/site/?q=node/12">story circulating</a> that Microsoft is going to provide a GNU compatible tool chain for Windows. This would in theory allow pretty much any *nix application to run on Windows with very little or no change.<br /><br />I seriously doubt there's any truth in this mostly because it would create a horrible rift with their third party developers who'd they'd be throwing to the wolfs, but you never know, anythings possible. There is no technical reason it can't be done. Hell, from Microsoft's perspective, I'd think it would actually be easy. After all both <a href="http://www.mingw.org/"><span class="blsp-spelling-error" id="SPELLING_ERROR_0">MinGW</span></a> and <a href="http://cygwin.com/"><span class="blsp-spelling-error" id="SPELLING_ERROR_1">Cygwin</span></a> already provide this functionality. In fact all they'd really have to do is provide a standard re-distributable C library and compiler.<br /><br />Even though I think it's a bogus rumor I really do hope Microsoft does this. I've always thought it was the one thing they could do that would guarantee them another 25 years of market dominance. In fact it's the only thing I can think of that could buy them enough time to switch away from the "Software As A Product" business model.<br /><br />They just better hope other people are more forgiving than I am. While I really want this to be true, it makes it easier for software I write to run on Windows, I have no personal interest in ever doing business with them again. Any vendor who doesn't always try and do the right thing for their customers is not some one I want to give money to. <br /><br />After a decade of bullying everyone in the sandbox it's a bit hard to accept they really want to share there toys now and even worse for them I've come to realize most of the alternatives are significantly better.Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-37362968966599490032008-02-24T20:56:00.000-08:002008-02-25T03:48:14.695-08:00Marketing Open Source<a href="http://www.zedshaw.com/">Zed Shaw</a> gives a talk about <a href="http://mongrel.rubyforge.org/">Mongrel</a> where he touches heavily on how to market an Open Source project. It's worth watching if these things interest you at all, at the very least you'll learn what yak shaving is.<br /><br /><a href="http://www.infoq.com/presentations/zed-shaw-mongrel-loc-economics">http://www.infoq.com/presentations/zed-shaw-mongrel-loc-economics</a>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-55592784702416774822008-02-23T11:03:00.000-08:002008-02-24T21:04:58.293-08:00Patch Bombing and Change StashingI ran across the term <span style="font-weight: bold;">'patch bombing'</span> today, which could be defined as; <span style="font-style: italic;">"multiple application logic changes all rolled into a single source code commit"</span>, it's the opposite of an <span style="font-weight: bold;">'atomic change'</span><br /><br />I found the term relevant to a background thought I've been pickling over lately....<br /><br />It's not uncommon for me to be in the middle of adding a new feature when I run across a bit of crufty code that needs to be <span class="blsp-spelling-error" id="SPELLING_ERROR_0"><span class="blsp-spelling-error" id="SPELLING_ERROR_0">refactored</span></span>. Which poses the problem; How do I do the <span class="blsp-spelling-error" id="SPELLING_ERROR_1"><span class="blsp-spelling-error" id="SPELLING_ERROR_1">refactoring</span></span> with out mixing the change sets?<br /><br />In the past I'd just make both changes and write one fat commit message explaining everything but I always thought this approach <a href="http://en.wikipedia.org/wiki/Code_smell">smelled bad</a>. Then, Jay Fields blogged about '<a href="http://blog.jayfields.com/2008/02/using-patch-as-subversion-stash.html">using patch as subversion's stash</a>' and turned me on to <a href="http://kurt.karmalab.org/articles/2008/02/18/the-power-of-git-git-stash">'the power of git-stash</a>'.<br /><br />It turns out that <a href="http://bazaar-vcs.org/">Bazaar</a>, which I'm using for my current project, doesn't directly support this operation either but Jay's patch-stashing approach works just as well for <span class="blsp-spelling-error" id="SPELLING_ERROR_2"><span class="blsp-spelling-error" id="SPELLING_ERROR_2">bzr</span></span> as it does for <span class="blsp-spelling-error" id="SPELLING_ERROR_3"><span class="blsp-spelling-error" id="SPELLING_ERROR_3">svn</span></span>.Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-68362354856561988522008-02-22T19:30:00.000-08:002008-02-23T11:21:20.294-08:00Method Not AllowedQuite a bit of my old code just redirects when an action gets a request with an unsupported method, for example; <span style="font-weight: bold;">'get</span>' requests to <span style="font-weight: bold;">'destroy'</span> actions. While my old approach prevented anything bad from happening it always seemed wrong. It also made maintaining my tests a tiny bit more complicated because each seemed to have a different location they redirected to.<br /><br />So I decided to clean up the code in my current project today. The obvious choice was to render an error template and return the proper status code.<pre class="ruby"><br /> <span class="comment"># file: app/controllers/parts_controller.rb</span><br /> <span class="keyword">def </span><span class="method">destroy</span><br /> <span class="keyword">unless</span> <span class="ident">request</span><span class="punct">.</span><span class="ident">delete?</span><br /> <span class="ident">render</span> <span class="symbol">:layout</span> <span class="punct">=&gt;</span> <span class="constant">false</span><span class="punct">,</span> <span class="symbol">:template</span> <span class="punct">=&gt;</span> <span class="punct">"</span><span class="string">errors/405</span><span class="punct">",</span> <span class="symbol">:status</span> <span class="punct">=&gt;</span> <span class="number">405</span><br /> <span class="keyword">return</span><br /> <span class="keyword">end</span><br /> <span class="keyword">begin</span><br /> <span class="constant">Part</span><span class="punct">.</span><span class="ident">find</span><span class="punct">(</span><span class="ident">params</span><span class="punct">[</span><span class="symbol">:id</span><span class="punct">]).</span><span class="ident">destroy</span><br /> <span class="ident">flash</span><span class="punct">.</span><span class="ident">now</span><span class="punct">[</span><span class="symbol">:success</span><span class="punct">]</span> <span class="punct">=</span> <span class="punct">"</span><span class="string">The part has been successfully deleted.</span><span class="punct">"</span><br /> <span class="keyword">rescue</span><br /> <span class="ident">flash</span><span class="punct">[</span><span class="symbol">:failure</span><span class="punct">]</span> <span class="punct">=</span> <span class="punct">"</span><span class="string">Unable to delete part.</span><span class="punct">"</span><br /> <span class="keyword">end</span><br /> <span class="keyword">end</span><br /></pre>This also simplified my tests.<pre class="ruby"><br /> <span class="comment"># file: test/functional/parts_controller_test.rb</span><br /> <span class="keyword">def </span><span class="method">test_destroy_get</span><br /> <span class="ident">get</span> <span class="symbol">:destroy</span><br /> <span class="ident">assert_response</span> <span class="number">405</span><br /> <span class="ident">assert_template</span><span class="punct">("</span><span class="string">errors/405</span><span class="punct">")</span><br /> <span class="keyword">end</span><br /></pre>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-66820545929032699202008-02-10T07:42:00.000-08:002008-02-10T09:04:20.194-08:00The Application Appliance<span style="font-style: italic; color: rgb(51, 0, 51);"><span style="color: rgb(0, 0, 0);">This post is the continuation of a thread that started with:</span><span style="color: rgb(51, 102, 255);"> </span></span><a style="font-style: italic; color: rgb(51, 102, 255);" href="http://blog.michaelgreenly.com/2008/02/opportunities.html">Opportunities</a><br /><br />The hardware it's self would not be remarkable in anyway and since I'm really only interested in the software stack the logical choice is to resell some other vendors machines preconfigured to meet my needs.<br /><br />At this point I'm not exactly sure who's machines I'll use but I'd prefer it to be a vendor that sees Ubuntu (or maybe Debian) as a first class target. My short list at the moment really only contains <a href="http://system76.com/">System76</a> so if anyone has any other suggestions I'd love to hear from you?<br /><br />The software on the other hand is much more interesting. The software will be delivered through a private apt repository as customized packages and include specifically configured base tools such as Apache, Postgres and Ruby as well as management tools for deployment, monitoring, replication and backup.<br /><br />Now obviously there's nothing special about this approach, in fact that's kind of the point. I don't want to have to re-think the simple standard parts I want to focus on the newer more unique parts. The management tools, replication and fail over to cloud services, etc...<br /><br />More later....Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-31598253411270525242008-02-02T06:41:00.001-08:002008-02-10T09:02:29.524-08:00My Opinionated Application Stack<span style="font-style: italic; color: rgb(51, 0, 51);"><span style="color: rgb(0, 0, 0);">This post is the continuation of a thread that started with:</span><span style="color: rgb(51, 102, 255);"> </span></span><a style="font-style: italic; color: rgb(51, 102, 255);" href="http://blog.michaelgreenly.com/2008/02/opportunities.html">Opportunities</a><br /><br />Recently I've been thinking a lot about different ways to minimize duplication of work. Many of my projects have similar requirements, how best can I reuse the effort from one to the next?<br /><br />I've also been puzzling over another problem; How do I provide businesses with reliable application when they don't have the necessary I.T. support to manage it and they don't have a reliable enough internet connection to go the "software as a service" route?<br /><br />It turns out that both questions may have the same answer. An application appliance! A low cost plug and play application server that's configured with a well defined software stack and the ability to backup to a remote service that is able to double as a warm standby in a pinch.<br /><br />In future posts I'll explain in more detail.Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-73309748399587266772008-02-02T05:41:00.000-08:002008-02-10T09:01:17.445-08:00OpportunitiesA driving belief of mine is that there's an enormous <a href="http://en.wikipedia.org/wiki/The_Long_Tail">long tail</a> associated with the custom business software market. It exists because software development is difficult and in the past only the deepest pockets have typically tried to tackle the problem but I think this has already began to change! Things like agile test driven development methodologies, the use of free software, and opinionated design are going to make it a reality.<br /><br />I'd like to share my recipe for this but you'll need to keep in mind I'm focusing on the really (really) small business that just doesn't register on the radar of more established custom software providers.<br /><br />It's really simple and goes something like this...<br /><br />Stick to the small projects that can be completed quickly. Every business has itches that need to be scratched. Keep the customer involved, which should be easy if you're focusing on a real itches and provide a turn key (nearly) zero administration solution.<br /><br />Which gets me to what I wanted to talk about, <a href="http://blog.michaelgreenly.com/2008/02/my-opinionated-application-stacks.html">my opinionated application stack</a>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-14141468561896458332008-02-01T17:23:00.000-08:002008-02-02T14:18:26.226-08:00My Apache SetupI've been using Apache2 with mod_fcgid for quite a while because it's good enough. I use it primarily because it's really simple to administer and I'm hosting internal business applications with very little load on them. Here's my setup...<br /><br />Installation is really straight forward<pre>$> sudo apt-get install apache2 libapache2-mod-fcgid<br />$> a2enmod fcgid<br /></pre><br /><br />default config<br /><pre># serve everything from /var/www/ and use /var/www/default as the document root<br /><br />ServerAdmin webmaster@hostname<br /><br /># setup logs<br />ErrorLog /var/log/apache2/error.log<br />CustomLog /var/log/apache2/access.log combined<br />LogLevel warn\<br /><br /># limit the amount of info about server<br />ServerSignature Off<br /><br /># default permissions to all files<br />&lt;Directory /&gt;<br /> Options FollowSymLinks<br /> AllowOverride None<br />&lt;/Directory&gtp;<br /><br /># setup document root and permissions<br />DocumentRoot /var/www/default<br />&lt;Directory /var/www/default&gt;<br /> Options +FollowSymLinks +MultiViews<br /> AllowOverride None<br /> Order allow,deny<br /> allow from all<br />&lt;/Directory&gt;<br /><br /># define environment for fcgid processes<br />DefaultInitEnv PATH "/opt/ruby/bin"<br />DefaultInitEnv RAILS_ENV "production"<br /></pre><br /><br />per application config<pre># run the app from /var/www/appname and serve it aliased as http://hostname/appname<br /><br />Alias /appname "/var/www/appname/current/public"<br />&lt;Directory /var/www/appname/current/public/&gt;<br /><br /> Options -Indexes +MultiViews +FollowSymLinks +ExecCGI<br /> AllowOverride None<br /> Order deny,allow<br /> Allow from all<br /><br /> RewriteEngine On<br /><br /> # provide support for cap deploy:web:disable<br /> RewriteCond /var/www/appname/current/public/system/maintenance.html -f<br /> RewriteCond %{SCRIPT_FILENAME} !maintenance.html<br /> RewriteRule ^.*$ /appname/system/maintenance.html [L]<br /><br /> # standard rails rewrite with support for alias directory<br /> RewriteBase /appname<br /> RewriteRule ^$ index.html [QSA]<br /> RewriteRule ^([^.]+)$ $1.html [QSA]<br /> RewriteCond %{REQUEST_FILENAME} !-f<br /> RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]<br /><br /> # define error documents<br /> ErrorDocument 500 500.html<br />&lt;/Directory&gt;<br /></pre>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-34571438254688564572008-01-26T19:20:00.000-08:002008-02-01T19:12:30.851-08:00Setting Up A Shared Bazaar RepositoryCurrently I'm using a <a href="http://bazaar-vcs.org/Workflows#head-ca3ccf73574776b36453b2213789731549e54167">Decentralized Shared Mainline Repository</a>. Here's my recipe...<br /><br />You will of course need a server that's accessible to everyone.<br /><br />Create a group for project.<br /><pre>$> groupadd projectname</pre><br />Create an login for each of the users who will have commit access to the shared mainline.<br /><pre>$> adduser --ingroup projectname username</pre><br />Create a directory for the repostitory inside the web servers document root<br /><pre>$> mkdir /var/bzr/projectname</pre><br />Set the project folders group to the project groups name<br /><pre>$> chown :projectname /var/bzr/projectname</pre><br />Set the project folders permissions<br /><pre>$> chmod ug+rwx,g+s,o+rx,o-w projectname</pre><br />Now you can push updates<br /><pre>$> bzr push bzr+ssh://hostname/var/bzr/projectname</pre><br /><br />If you need to provide anonymous access to the repository one way would be to serve it with Apache.<br /><pre>Alias /bzr "/var/bzr"<br />&lt;Directory "/var/bzr"&gt;<br /> Options +Indexes +MultiViews +FollowSymLinks<br /> AllowOverride None<br /> Order deny,allow<br /> Allow from all<br />&lt;/Directory&gt;<br /></pre><br />This would allow you to do something like this<br /><pre>$> bzr branch http://hostname/bzr/projectname</pre>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-12286968054005794052008-01-18T17:47:00.000-08:002008-02-01T19:10:09.669-08:00Obfuscating IDs in URLs with RailsThere are a number of valid reasons to obfuscate IDs in URLs but it's not a replacement for authentication!<br /><br />My approach to this problem is to allow the database to assign a normal serial ID, which means I don't have to maintain any extra state or use special database features. Then after it's created I save the obfuscated value of the id which I can use on later lookups.<br /><br />I use Knuth's integer hash because it ensures there will be no collisions and the full range of values will be used.<br /><br />In this example I'm using a signed 32 bit integer for the hashed_id because it's supported by all common Rails databases. You could however adjust MAXID to any number of bits you want but then you may have to deal with storage and conversion issues.<br /><br /><span style="font-weight: bold;">Model:</span><br /><pre class="ruby"><span class="keyword">class </span><span class="class">Part</span> < <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><br /><span class="constant"> PRIME</span> <span class="punct">=</span> <span class="number">2654435761</span><br /><span class="constant"> MAXID</span> <span class="punct">=</span> <span class="number">2</span><span class="punct">**</span><span class="number">31</span><span class="punct">-</span><span class="number">1</span><br /><span class="keyword"> def </span><span class="method">after_create</span><br /><span class="constant"> self</span><span class="punct">.hashed_id</span> <span class="punct">=</span> <span class="punct">(</span><span class="constant">self</span><span class="punct">.</span><span class="ident">id</span> <span class="punct">*</span> <span class="constant">PRIME</span> <span class="punct">&amp;</span> <span class="constant">MAXID</span><span class="punct">)</span><br /><span class="constant"> self</span><span class="punct">.</span><span class="ident">save</span><br /><span class="keyword"> end</span><br /><span class="keyword">end</span><br /></pre><br /><span style="font-weight: bold;">Controller:</span><br /><pre class="ruby"><span class="keyword">class </span><span class="class">PartsController</span> < <span class="constant">ApplicationController</span><br /><span class="keyword"> def </span><span class="method">show</span><br /><span class="attribute"> @part</span> <span class="punct">=</span> <span class="constant">Part</span><span class="punct">.</span><span class="ident">find_by_hashed_id</span><span class="punct">(</span><span class="ident">params</span><span class="punct">[</span><span class="symbol">:id</span><span class="punct">])</span><br /><span class="keyword"> end</span><br /><span class="keyword">end</span><br /></pre>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-19291356616200277602008-01-04T13:12:00.000-08:002008-02-01T19:08:36.647-08:00Useful Launchpad TipsI ran across a useful <a href="http://www.bryceharrington.org/drupal/node/18">blog post</a> today that included some useful tips for for using <a href="http://launchpad.net/">Launchpad</a> that's worth sharing.<br /><ul><li><a href="http://article.gmane.org/gmane.comp.graphics.inkscape.devel/23326/match=launchpad+tips+tricks">basic of triaging</a></li><li><a href="http://article.gmane.org/gmane.comp.graphics.inkscape.devel/23327/match=launchpad+tips+tricks">tags</a></li><li><a href="http://article.gmane.org/gmane.comp.graphics.inkscape.devel/23413/match=launchpad+tips+tricks">duping bugs</a></li><li><a href="http://article.gmane.org/gmane.comp.graphics.inkscape.devel/23415/match=launchpad+tips+tricks">tracking upstream bugs</a></li><li><a href="http://thread.gmane.org/gmane.comp.graphics.inkscape.devel/23333/focus=23341">email managment</a></li><li><a href="http://article.gmane.org/gmane.comp.graphics.inkscape.devel/23380/match=launchpad+tips+tricks">graphing bug metrics</a></li></ul>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-9251924773142171192007-12-27T19:36:00.000-08:002007-12-29T09:17:59.444-08:00Multiple Versions of Ruby On Ubuntu<span style="font-size:85%;"><span style="color: rgb(0, 0, 153); font-weight: bold; font-style: italic;">edit: moved install from $HOME to /opt.</span></span><br /><br />With Ruby 1.9 out there's the obvious possiblitity some people will want to run multiple versions of Ruby so I thought I'd share this.<br /><br />My goal is to have the Ubuntu Ruby packages installed along side the most current releases of 1.8 and 1.9<br /><br />First I'll install using apt to create my default ruby install.<br /><pre>$> sudo apt-get install ruby irb ri rdoc libruby-extras rubygems ruby1.8-dev<br />$> sudo gem install rake</pre><br />Next I'll install the most current release packages of 1.8 and 1.9 in to /opt/ruby1.8.6 and /opt/ruby1.9.0 respectively.<br /><br />Before doing that I'll make sure I have all the necessary build dependencies for both packages<br /><pre>$> sudo apt-get build-dep ruby1.8 ruby1.9</pre><br />Next I downloaded both packages into a working directory and decompress them<br /><pre>$>mkdir temp; cd temp<br />$>wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p111.tar.gz<br />$>tar -xvzf ruby-1.8.6-p111.tar.gz<br />$>wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.0-0.tar.gz<br />$>tar -xvzf ruby-1.9.0-0.tar.gz</pre><br />Next I build each of the packages.<br /><pre>$> cd ruby-1.8*<br />$> ./configure --prefix=/opt/ruby1.8 --program-suffix=1.8.6<br />$> sudo make &amp;&amp; make install<br />$> cd ../ruby-1.9*<br />$> ./configure --prefix=/opt/ruby1.9 --program-suffix=1.9.0<br />$> sudo make &amp;&amp; make install<br /><br /></pre>Ruby 1.8 doesn't have built in support for gems like Ruby 1.9 so we'll have to install it.<br /><pre>$> wget http://rubyforge.org/frs/download.php/29548/rubygems-1.0.1.tgz<br />$> tar -xvzf rubygems-1.0.1.tgz<br />$> cd rubygems*<br />$> sudo /opt/ruby1.8.6/bin/ruby1.8.6 setup.rb</pre>Notice that I specified the entire path to the ruby executable while installing RubyGems for 1.8.6<br /><br />The next thing I do is create some symbolic links to make life a little bit easier.<br /><pre>$> sudo ln -s /opt/ruby1.8.6/bin/* /usr/local/bin<br />$> sudo ln -s /opt/ruby1.9.0/bin/* /usr/local/bin<br /></pre>Now test things a bit to make sure everything makes sense<pre><br />$> which ruby<br />>> /usr/bin/ruby<br />$> gem env<br />>> ....<br />>> GEM PATH: /var/lib/gems/1.8<br />>> ....<br /><br />$> which ruby1.8.6<br />>> /usr/local/bin/ruby1.8.6<br />$> gem1.8.6 env<br />>> ....<br />>> GEM PATH: /opt/ruby1.8.6/lib/ruby/gems/1.8<br />>> ....<br /><br />$> which ruby1.9.0<br />>> /usr/local/bin/ruby1.9.0<br />$> gem1.9.0 env<br />>> ....<br />>> GEM PATH: /opt/ruby1.9.0/lib/ruby/gems/1.8<br />>> ....<br /></pre><br />A couple of things to watch out for:<br /><ul><li>Make sure you don't have any RubyGems environment variables set. They're not needed for any of this and most likley will mess something up.<br /></li><li>Don't install any gems until after you create your symbolic links or the executable commands may clobber each other.</li><li>You have to specify the full path to an executable gem because they don't play nicely with program suffixes. So for example '/opt/ruby1.8.6/bin/rake' will do what you expect but just typing 'rake' may not.</li></ul>One last little tidbit. I'm not sure if the Ubuntu RubyGems packages deal with fixing up the $PATH yet? Regardless the fix is easy; add this little bit of code to the bottom of your ~/.bashrc file<br /><pre>if [ -d /var/lib/gems/1.8/bin ]; then<br />PATH=/var/lib/gems/1.8/bin:"${PATH}"<br />fi<br />export PATH</pre>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-53537504793019437722007-12-27T17:04:00.001-08:002007-12-27T20:53:16.455-08:00Customizing Debian PackagesDebian's packaging system makes it really easy to modify packages if you want to. In this little howto I modify ffmpeg to add MP3 support but the process can easily be adapted to any package.<br /><br />First create a work directory and drop down into it. This is just to make cleanup easy.<br /><pre>$> mkdir temp; cd temp</pre><br />Then make sure the ffmpeg build dependencies are installed<br /><pre>$> sudo apt-get build-dep ffmpeg</pre><br />Then download the source package<br /><pre>$> apt-get source ffmpeg</pre><br />Then install the extra (codec) libraries we're adding support for<br /><pre>$> sudo apt-get install liblame-dev libfaad2-dev libfaac-dev libxvidcore4-dev</pre><br />Then drop down into the ffmpeg source directory<br /><pre>$> cd ffmpeg*</pre><br />Now you will have to edit the first line of the the debian/changelog and modify the package version. If you don't system updates will want to 'replace' your modified package. The first line should look something like this:<br /><pre>ffmpeg (3:0.cvs20070307-5ubuntu4) gutsy; urgency=low</pre>. You will want append something at the end of the part in parentheses. In my case I use:<br /><pre>ffmpeg (3:0.cvs20070307-5ubuntu4-mg1) gutsy; urgency=low</pre><br />It's my initials followed by a revision number.<br /><br />Once you've modified the change log you can build the package but before we do we set an environment variable used by the build scripts that indicates we want the 'risky' libraries included.<br /><pre>$> DEB_BUILD_OPTIONS=risky &amp;&amp; fakeroot debian/rules binary</pre><br />Now we just need to install the packages. The packages were placed up one directory during the build process so we just move up and install.<br /><pre>$> cd .. &amp;&amp; sudo dpkg -i *.deb</pre><br />Now we just clean up after ourselves<br /><pre>$> cd .. &amp;&amp; rm -rf temp</pre>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-83485791268795556622007-12-24T20:03:00.000-08:002007-12-27T21:52:56.141-08:00The Generational Divide in Copyright MoralityThere's an interesting (but not surprising) <a href="http://pogue.blogs.nytimes.com/2007/12/20/the-generational-divide-in-copyright-morality/">article</a> in the New York Times about differences in perspective between the coming generation and the current in regards to intellectual property.<br /><br />This of course created plenty of <a href="http://yro.slashdot.org/yro/07/12/24/2138202.shtml">conversation on Slashdot</a> (most of it half baked) but still enough motivation to get me to post this....<br /><br />It's simply impossible to prevent sharing of media. I mean literally impossible! There's nothing you can do to stop it (unless you have a dooms day device in your garage?).<br /><br />All the effort spent trying to stop it is literally wasted!<br /><br />It seemed to me from both the NYT article and Slashdot comments people felt these kids should feel guilty, like they're doing something wrong? The reality is these kids realize our outdated views on Copyright have NO (you read that right 'NO' ) value in today's world.<br /><br />They understand that we're all better off when information is shared freely and they also understand there's no practical way to differentiate media from other types of information. They are correctly choosing to accept shared media as a consequence of free information exchange.<br /><br />They also I'm sure realize the impact this will have on their futures. I'm sure they understand that the media industry is a service industry and that they will have to live off the work they do (not the work they've already done) in the future.<br /><br />So even though everyone from the article and Slashdot seemed to imply these kids just don't get it. I think it's just the opposite. They are the ones that really do get it!Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.comtag:blogger.com,1999:blog-1539046083268926117.post-22425487756923051972007-12-24T14:32:00.001-08:002008-01-01T12:01:17.601-08:00Ruby Syntax Highlighting On Blogger<div class="ruby">It turns out that creating syntax highlighted source in blogger is not difficult even if it's not convenient<br /><br />The first step is to find an application that can syntax highlight and convert your code to HTML. I choose to hack together a quick little script on top of the <a href="http://syntax.rubyforge.org/">Syntax</a> library (the code's below)<br /><pre class="ruby"><span class="ident">require</span> <span class="punct">'</span><span class="string">rubygems</span><span class="punct">'</span><br /><span class="ident">require</span> <span class="punct">'</span><span class="string">syntax/convertors/html</span><span class="punct">'</span><br /><span class="ident">convertor</span> <span class="punct">=</span> <span class="constant">Syntax</span><span class="punct">::</span><span class="constant">Convertors</span><span class="punct">::</span><span class="constant">HTML</span><span class="punct">.</span><span class="ident">for_syntax</span> <span class="punct">"</span><span class="string">ruby</span><span class="punct">"</span><br /><span class="ident">puts</span> <span class="ident">convertor</span><span class="punct">.</span><span class="ident">convert</span><span class="punct">(</span><span class="constant">File</span><span class="punct">.</span><span class="ident">read</span><span class="punct">(</span><span class="constant">ARGV</span><span class="punct">[</span><span class="number">0</span><span class="punct">]))</span><br /></pre>Now when ever you want to make a post just choose 'Edit Html' in the composer and insert the output from your formatter application.<br /><br />Depending on on your formatter you may need to add it's CSS to your Blogger template.<br /></div>Mike Greenlyhttp://www.blogger.com/profile/15964361079720234778noreply@blogger.com