I was reading some articles yesterday that finally made the light bulb go off about distributed source control management (scm) and why we should be using them. First off, a distributed scm, unlike CVS or Subversion, has no central repository that all others pull from. It’s possible to set one up and say that it’s the master and tell people to pull from and push to it but that’s more a matter of convention. What’s truly unique about these systems is that each checkout is it’s own self-contained ecosystem. And there are many reasons this is a good thing:
If Mozilla has taught us anything it’s that you’re NOT going to get thousands of developers working on your project. So, while huge numbers of developers is something that distributed scm handle exceedingly well I think the point is moot. But, in my experience, a developer interested in some OSS (Open Source Software) project will download the source from a traditional scm, poke around to understand it, and if they’re smitten with the idea will start customizing it for their needs. But, the are forced to either work without the benefits of version control or they have to check it into their own personal scm. If they check it into their own you can pretty much forget about ever getting patches from them because they’re no longer able to sync with your tree and it would be way more work than they generally want to do to get synced and give you a patch that was useful. If they work without scm (because they don’t have commit rights to your scm) you may get a patch from them but for them it’s like climbing a rock face without lines and harnesses.
If you were to use a distributed scm each developer would be working off of their own personal copy of the scm that could be synced at any point in time no matter how many changes, revisions, or commits they have made. They’re generally not going to check it into their own scm system because that’s work that doesn’t get them any real benefit. They already have version control via their checkout and the fact that it’s a distributed system. End result, they don’t need to work without the safety and security of an scm and they will generally always be working on a system they can easily send you changes from when they’re ready.
If you’re really working like a pro, you’re constantly branching and merging your code. You’ve got a live site branch. You’ve got a branch for each new functionality exploration. You’ve got a trunk branch that everyone merges into their other branches regularly. In the real world you probably have a live site branch and the trunk and cross your fingers that each developers functional exploration doesn’t screw over any other developer’s pokings. Or, in far too many cases, you just have the trunk. The problem comes (for those of us who hate dealing with the pain in the ass that is the current state of merging on most traditional SCMs and have minimal branches) when you decide you want to integrate one developers functional exploration into the live branch. How do you extract that code from the other code in the trunk (or any other common branch)?
If you were using a distributed scm it would go something like this: Everything starts with the live site repo (wherever you happen to keep that). Everyone’s local repo(s) started as a copy of that. It’s not uncommon to check out another copy to go explore some new feature set in. Maybe you sync it with the live. Maybe you trash it. It doesn’t matter no other repo was affected by your fiddling. You don’t have to make a new branch in some central repo that gets stored forever even if your fiddlings proved insignificant or were just abandoned. If everyone decides that the features you worked out in a particular repo are worth keeping they just sync with it. If you decide to wait to put it into a later release that’s fine too because there’s no need to untangle it from other work you, or others, have been doing. This is because to “branch” you just do a simple checkout from any other repo. When it comes to merging you benefit from the fact that any decent distributed scm is designed to work with syncing sweeping changes to entire code-bases not just individual files. They all handle this a bit differently of course, and some better than others, but the point is that while you’re almost always going to have conflicts you’re working with tools that have to be better equipped to avoid them.
I can’t really speak to those because I just haven’t worked on them but utilizing distributed scms does mean that you don’t have the huge demands on the server hosting your scm. Plus all the aforementioned benefits.
So what are your options? Well the main contenders appear to be darcs (written in Haskell), Mercurial (written in Python), and Git (written in c plus hooks into a bunch of other things I think). darcs seems to be the easiest to use, with some decidedly funky features, but isn’t great for projects with huge numbers of files (it can be ram intensive at times). Mercurial is going to be used by the newly open-sourced JDK, and Git is being used to manage the Linux kernel.
* My light bulb moment, and some of the quotes here are thanks in no small part to this blog post about the JDK moving to Mercurial by Mark Reinhold. Thanks Mark.
If you’re like me and you’re on Dreamhost and trying to do an upload to Amazon’s s3 using the AWS::S3 library, you may encounter the following bug:
undefined method `body=' for # [RAILS_ROOT]/vendor/plugins/aws/lib/aws/s3/connection.rb:37:in `request'
Now, obviously there is a body= method. Why it can’t find see it is something I haven’t determined. But I’m working on a live app so it was more important to get things working than to worry about obscure bugs in Dreamhost’s servers (It works on three other servers I’ve tried it on). So, how’d I solve it? Well, I’d been working on this app before AWS::S3 was released, and the best looking library at the time was s33r. It’s not in as polished of a state as AWS::S3 but it works, and in this case it has the distinction of working on Dreamhost too.
On a related side note, s33r can also generate a protected url for your s3 resource without having to make a connection to S3. It doesn’t appear to be possible to do anything with AWS::S3 without first starting up a connection. And when all you’re doing is generating an url it seems silly to make a connection that is completely unnecessary.
Ever wish you could have sparklines in your app without having to make another call to the server to generate a png/gif/svg/whatever image? Something that looked like these maybe?
Sparkline here:
Fat Sparkline here:
Unspaced sparkline here:
Unspaced fat sparkline here:
Those all have the same data, they’re just formatted differently.
The javascript is here: sparkline.js and the css is here: sparkline.css and this test example was implemented like this:
Much credit should go to TiddlyWiki for the original idea, which i then extracted, enhanced, and posted here for your enjoyment.
[updated to work in Safari too]
You know all those little star-rating widgets you see on sites like Amazon? Well, Kondomedia has come up with a great example of how to put one together. There are just two little problems: 1) it jumps you to the top of the page every time you click a star. 2) the star you clicked on doesn’t stay clicked. Neither are difficult problems to solve but there’s no reason you should have to figure it out when I’ve already had to. So here you go:
Step one. Go read their article on it to understand the basics of how this all works and what we’re working towards graphically. There’s no point in me rewriting something they wrote so well.
Next you’ll need this image.
Then you’ll need to tweak the html in two key ways. First to make it not jump you have to link to a non-existent anchor instead of #. If you link to # or any other valid anchor your page will jump, but if you link to an anchor that doesn’t exist the page stays where it is. This is about the only time failing silently is a good thing. So, in the example here I’ve changed the anchors to #b1 through #b5. They could all be the same it really doesn’t matter. I just know that i’ll never have a #bn anchor because I’m smart enough to use anchors that actually mean something when you see them.
Next I’m going to actually make it do something because I’m assuming you don’t want a widget that just lets people click on stars for no good reason. In this example I’ve used erb code examples ( <%= foo %> ) of how you’d put in the dynamically generated values but you’d use whatever it is that you use. Note that I’m filling in the default value and calculating the width of the current-rating li element.
And, of course, you’ll need the updateVoteUI javascript:
function updateVoteUI(new_value, is_safari){ var form_input = document.getElementById(“vote_value”); form_input.value = new_value; var current_rating_li = document.getElementById(“current_rating”); if (is_safari != true){ current_rating_li.style.width = “” + (new_value * 30) + “px;” ; } else { current_rating_li.style.width = “” + (new_value *30); } return false; }
The CSS remains exactly the same as created by Komodomedia:
/* styles for the star rater */ .star-rating{ list-style:none; margin: 0px; padding:0px; width: 150px; height: 30px; position: relative; background: url(star_rating.gif) top left repeat-x; } .star-rating li{ padding:0px; margin:0px; /*\*/ float: left; /* */ } .star-rating li a{ display:block; width:30px; height: 30px; text-decoration: none; text-indent: -9000px; z-index: 20; position: absolute; padding: 0px; } .star-rating li a:hover{ background: url(star_rating.gif) left center; z-index: 2; left: 0px; } .star-rating a.one-star{ left: 0px; } .star-rating a.one-star:hover{ width:30px; } .star-rating a.two-stars{ left:30px; } .star-rating a.two-stars:hover{ width: 60px; } .star-rating a.three-stars{ left: 60px; } .star-rating a.three-stars:hover{ width: 90px; } .star-rating a.four-stars{ left: 90px; } .star-rating a.four-stars:hover{ width: 120px; } .star-rating a.five-stars{ left: 120px; } .star-rating a.five-stars:hover{ width: 150px; } .star-rating li.current-rating{ background: url(star_rating.gif) left bottom; position: absolute; height: 30px; display: block; text-indent: -9000px; z-index: 1; }
Back in January of 2006 Ezra Zygmuntowicz came up with an exceptionally cool Rails plugin that, IMNSHO, should be in rails core. It’s called ez_where and it’s svn repo is here.
What’s so cool about ez_where? Well, the to really understand it’s beauty you have to step back to one of core concepts that’s at the heart of frameworks like Rails: Database Abstraction and Object Relational Mappings. Before these concepts really came into their own we were all writing raw SQL commands in our apps. Now we interact with a layer of abstraction that lets us work with the objects we’re actually programming with instead of database structures. Except, that’s not quite true with Rails. With rails you end up writing things that are possibly more complex than the SQL statements we’ve been trying to avoid. Here’s a particularly egregious example from a ticket system I’ve been working on:
Ticket.find(:all, :conditions=>["closed = ? AND product_id in (?) AND user_id = ? AND ticket_type_id=? ", product_ids, user_id, ticket_type_id], :order=>["weighted_vote_percentage DESC, ticket_id DESC"])
Personally I don’t see this as being particularly better than writing the raw sql since I am writing the raw sql. Yes Rails has saved me from writing the SELECT t.* from tickets t WHERE but then it forced me to write the entire where and order clauses and put them in a data contstruct that took more thinking and more characters than the SQL would have. How is this better? SQL is database agnostic anyway (unless you start adding in vendor specific additions ) so it’s not really buying me separation from that… So what is it buying me?
SELECT t.* from tickets t WHERE
Ezra gets it though. If you use his plugin you’ll be able to use the power of ruby in your find statements. Yes, it may be more wordy than SQL but what it buys you is a true separation from your database. His blog posting on ez_where gives this great example:
Model.find_with_conditons( :all, :limit => ..., :order => ... ) do foo == 'bar' # ["foo = ?", 'bar] baz <=> (1..100) # ["baz BETWEEN ?AND ?", 1,100] woo =~ 'substri%' # ["woo LIKE ?", 'substri%'] id === (1..4) # ["id IN (?)", [1,2,3,4]] fiz < 10 # lt, gt, leq, geq, etc., should all "just work" end
Now, to be totally up front with you, I haven't actually used this plugin yet, but, honestly, I don't even care if it's buggy. If it's even remotely close to working I'll be helping to fill in any holes that present themselves. For years experienced developers have been trying to get us to remove SQL from our code, and then Rails comes along and chucks that advice out the window. This, or something very much like it, is what we should be moving towards.
Would you read a newspaper that forced you to read through a list of every author in the current issue, then go to a list of what they wrote in today’s issue? Would you use an e-mail client that had no inbox but made you click on a list of all the people you ever got mail from in order to see what they sent you today?
I think we can safely assume the answer to that question is no!… hell no! So why is it that the creators of so many feed (rss, atom, etc.) aggregators make you do just that? Todays example comes from Newshutch. I read in one of the feeds I subscribe to that it was a nice ajax based ui so I gave it a test and uploaded an opml file of all my feeds only to be presented with the following UI horror. Click on the image to see it full size, this is just 50% but even at that size you can see how completely unworkable it is. I assume this would be useful if you were only subscribed to a few feeds, but what’s the point of only subscribing to a few feeds. It’s better to just bookmark them and view them in their full glory along with peoples comments.
Just imagine that this was your list of feeds for a second and imagine what a pain it would be to click on every single one that happened to have new content and you’ll know why I use Google Reader. Also, what’s the deal with that stupid first time user section across the top? It’s fine the first time you come to the page but there doesn’t appear to be any way to make it stop appearing there.
[update: there was an incredibly long screenshot here...but our server's disk got corrupted and ate it. If i come across a backup of that file i'll add it back in.]