Add migrated Hugo site

This commit is contained in:
Ariejan de Vroom 2015-03-26 12:28:08 +01:00
parent bd343ab96e
commit 95c92f33e4
692 changed files with 13451 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Generated site
/public
# Other things
.DS_Store

12
config.toml Normal file
View File

@ -0,0 +1,12 @@
baseurl = "https://ariejan.net/"
languageCode = "en-us"
title = "ariejan de vroom"
theme = "outerspace"
copyright = "Ariejan de Vroom"
disqusShortname = "ariejannet"
[author]
name = "Ariejan de Vroom"
[permalinks]
posts = "/:year/:month/:day/:slug/"

32
content/about.md Normal file
View File

@ -0,0 +1,32 @@
+++
type = "page"
title = "About Ariejan"
+++
<img class="avatar" id="about-photo" src="https://0.gravatar.com/avatar/a9bfdd0cc75c857b669c37548b8bfdf9?s=192" />
I'm Ariejan de Vroom and I'm a software engineer. My focus is on back-end systems
using Ruby, Ruby on Rails and Go. In my free time I like to play the piano and
experiment with electronics.
I live in [Son en Breugel, the Netherlands][1] with my wife and son and I'm currently
working at [Kabisa][3].
I am available for development, consulting and training. Please get in touch.
Check me out on [Twitter][4], [Github][6] or [LinkedIn][5] to get to know me a bit better.
Want to ask me a question? [Get in touch right now][10]
This site is static HTML, generated by [Hugo][11]. The theme and content are copyrighted, so there's
no public code.
[1]: https://www.google.nl/maps/place/Son+en+Breugel/@51.5928283,4.2716786,6z/data=!4m2!3m1!1s0x47c6de5ca934b9d9:0x6259d7f97b28e465?hl=nl
[3]: http://kabisa.nl/
[4]: http://twitter.com/ariejan
[5]: http://www.linkedin.com/in/ariejan
[6]: https://github.com/ariejan
[8]: mailto:ariejan@ariejan.net
[9]: /gpg
[10]: /contact
[11]: http://gohugo.io/

12
content/contact.md Normal file
View File

@ -0,0 +1,12 @@
+++
type = "page"
title = "Get in touch..."
+++
* Mail to [ariejan@ariejan.net][8] ([GPG key here][9])
* Tweet to [@ariejan][4]
[4]: http://twitter.com/ariejan
[8]: mailto:ariejan@ariejan.net
[9]: http://ariejan.net/gpg/

62
content/gpg.md Normal file
View File

@ -0,0 +1,62 @@
+++
type = "page"
title = "GPG Public Key"
+++
**Please do not sign my public key unless you have validated my
key credentials with me in person.**
Get my public key:
* Fetch [`0xF713697B`][1] from a [GPG Key server][1]
* Check out [keybase.io/adevroom][2] for more details
## Want to know more about GPG?
Check out the slides of my talk [Gnu Privacy Guard and You](https://speakerdeck.com/ariejan/gnu-privacy-guard-and-you-math-version)
## Proof of identity
As far as you can trust this website, this is a proof of my identity.
Also make sure to check me on
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
My name is Ariejan de Vroom and I use GPG.
My public key information is:
ID: 0xF713697B
Fingerprint: 8450 D928 4373 164E 25CC 7E0D AD73 9154 F713 697B
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
Comment: GPGTools - https://gpgtools.org
iQQcBAEBCgAGBQJTTjpmAAoJEK1zkVT3E2l7Wg4f/AxfJhiEYE1ZrgSPWCdoruio
jpGBiBhFIZXt4IJySrSU/BzfeErrHsUrZMea502ifIz5cLQrCR9qPuAvC+MwDxDh
hagcGtp68JEo8vT4oeov4glVCifP2pQSddshFOtw8UMJwfyhpOqQvjIOQGPObDMD
G6Dnbba6TAHtBrzAtD+lA6IQ41H4uTugp5cmf6zxVoP/UhGls+Ci7k2YINo2lst7
hKei/Hc+L0/6oauKMQc+CT66YHu+WYtf0N6WU/r2OosTbdoS7dsPg8sR94zKGivQ
siMYMF5WEgjlCwPjqRbnig46upjhxBRsdT+A64FOhRyxIlZjjVcC+N2BQc8S28hZ
aqvX7sh6ls3GmnTeAlGuaxSbdm7hEKwy4U8PXKS6wuZMmQ2c0jOHBvj0zHuNwoi6
RryxA1yxJh0g1T6HqEokP9nRdDmelgUDPYciplmWYdhKyUwtDZAUVsSoXc1jDao+
ZQ/MPx3liBy93sIXg+ckqCsD1SrddAOyTShA06KtgiXn93rbnJOZ26qqFL07yclA
GSx8TDkNnPLWyxoPT5LK05P54SAm6PSYqV1a3zws0jqlgJbmrOkcMX5mAeceQDhw
eulgHpo0wobqFbd/hjbBB60xdX7NQqDwBfV6UgYKEqv+dq0P1L2XkwJCksAmxvEs
2Irg6+TI/GF8b5p2Z59L+MBnKVWTsiMwKFnyaPSGjm3YttUr+TrYdyMK5mkrnpR3
h6RX07YQqDADL8rKS/0O+uzuRkdkz+e4VEqH72bQwJu7DfCrJBlX3O4epGqCgOzK
5+Cg5I39OXYzOF08iJj6SqRqH9MsDAFRmDTSq+mQ6W+fGW+qKUvcoCFYsC3sZkYb
MO+AnjvlfZhh+KHjb30mlLDl1MCheEdT9GcfZJjZcMPjOL3yMWf+zUAi1mmdJM85
F/+RYEmQfsapTwbmnL7kUwStNXw2XLTVFK/jUJVOtdx1hcRpbBvSY1YX20FBLDDU
l6BkgKHrn/4rJ2drS6K8zQL+xq0qQUpPaK+6JQfTDXFzASSyUZz8zrs9PrUU+TT3
hvVsMJpc+0LbnftwmoMsTD2V83b4DCzIBlEqtNNoFLKyDEphxxTLUkvLU0Ptr7ti
maZLnZFUTtMTmW7BEECzOJcZodsbMJ4vU1Ys5tnPD2MIhuEIuPAxUP/SPMOtvkmZ
sgtqO2IdKEGUmg27WOqGJSftXqVTMN4MPOnE286G2gtsGJr/dQxoV24JH0F12sUc
gNErAbXeK4wTc7OhxtbN1fbRKUMcfjAqLq2MbuLE6y00fFXIJ/CQaOvDz36ub+V6
9R20HC4ZmlcA44jwX607jX65hHjBovlJHBPMsFTKrHigzkDfAxKbxcYO22Yku5c=
=Zlrk
-----END PGP SIGNATURE-----
[1]: https://pgp.mit.edu/pks/lookup?search=0xF713697B&op=index
[2]: https://keybase.io/adevroom

View File

@ -0,0 +1,21 @@
+++
date = "2006-10-09"
title = "Welcome to Ariejan.net"
tags = ["General", "Everything", "Wordpress", "Ariejan.net", "Blog"]
slug = "welcome-to-ariejannet"
+++
Well, it has happened to me. Although I make regular backups of my site, this time I was screwed!
Since I'm very interested in <a href="http://rubyonrails.com">Ruby on Rails</a>, I gave a RoR weblog, <a href="http://typosphere.org/">TypoSphere</a>, a try. I exported my entire <a href="http://www.wordpress.org">Wordpress</a> blog to typo and I was a happy man. Until disaster struck...
<!--more-->
After a while I noticed that typo's search functionality was not working. I recieved a MySQL error messages that the table containing my artilces did not exists! To make a long story short, all database files containing data were gone. Luckily I make regular backups every day automatically.
Well, I make regular backups and keep the seven most recent backup files at hand. But, you guessed it, apparently the disaster happened more than a week ago. So, all my backup files contained the corrupted database files. Bugger!
So, after some flirting with <a href="http://www.adobe.com/products/dreamweaver/">Dreamweaver</a>, <a href="http://drupal.org">Drupal</a> and <a href="http://joomla.org">Joomla</a>, I'm back at Wordpress which really is the best, easy to use and customize publishing tool I know.
Since all my previous tutorials are gone, I'm going to start with a clean slate here. Please comment on my articles if you like and feel free to link anything you find here.
For now, I'll have to re-customize my site and then I'm ready to start posting useful things here.

View File

@ -0,0 +1,18 @@
+++
date = "2006-10-10"
title = "Easily create a FavIcon online!"
tags = ["General", "Everything", "Blog", "Web Development", "Links", "Personal"]
slug = "easily-create-a-favicon-online"
+++
You know those little icons you see in your browsers address bar? Yes, the ones in you bookmarks! Well, you want such an icon for your site?
These icons are called FavIcons, short for Favourites Icon. Most modern browsers make use of them.
To create such an icon you'll need some image first. Normally the process would be rather difficult involving several graphics manipulation programs and conversions. Don't fall for that! Use the followin <a href="http://www.chami.com/html-kit/services/favicon/">FavIcon from Pics</a> site!
Just upload a gif, jpeg or png image (with transparency if you like) and get a FavIcon for free! There are also some other goodies included!
Of course, there's information available on how to upload your FavIcon and how to let your browser know about it.
<!--more-->

View File

@ -0,0 +1,27 @@
+++
date = "2006-10-10"
title = "Generate a SQlite-based Rails app"
tags = ["General", "Everything", "RubyOnRails", "Databases", "SQlite", "Features"]
slug = "generate-a-sqlite-based-rails-app"
+++
When you create a Rails application a database.yml files is included with some default configuration for your database. Unfortunately these are defaults for MySQL. If you want to use another database, like SQlite, you'd have to rewrite the entire configuration file. And that's not what you want!
Luckily, rails is very adapative and we can make it do all the work for us.
<!--more-->
When you create a rails application, firstr check out the help message from rails itself.
<code>$ rails --help</code>
When you look closely you'll see that there's an option available called '--database'. It has the following message attached to it:
<blockquote>Preconfigure for selected database (options: mysql/oracle/postgresql/sqlite2/sqlite3).</blockquote>
Basically, you can specify, when create your rails project, what database type you want to use, and Rails'll create a matching configuration file for you. When you leave this option out, it defaults to MySQL.
As you can see there are several databases supported, including SQLite. In order to create a new rails project with SQlite3 configured by default, run this:
<code>$ rails --database=sqlite3 myproject</code>
Check out config/database.yml and you'll see that there are sensible defaults for you there.

View File

@ -0,0 +1,14 @@
+++
date = "2006-10-10"
title = "Hi-Res Wallpapers for your MacBook!"
tags = ["General", "Everything", "Blog", "Links", "Eye Candy", "MacBook", "Professional"]
slug = "hi-res-wallpapers-for-you-macbook"
+++
For all of you who have a flashy Apple MacBook (or any other device with a 1280x800 resolution) here's a nice site with lot's of hi-res wallpapers. Of course, they're all for free!
Oh, they have other sizes as well.
Go check out <a href="http://interfacelift.com/wallpaper/index.php?sort=downloads&w=1280&h=800">InterfaceLIFT</a>.
<!--more-->

View File

@ -0,0 +1,51 @@
+++
date = "2006-10-10"
title = "Top 5 DVDs you must have"
tags = ["General", "Everything", "Blog", "Lists", "Movies", "DVD", "Coding"]
slug = "top-5-dvds-you-must-have"
+++
Everybody at this point in time at least owns one or more DVD - Digital Versatile Disk - Videos. Some people try to collect as many DVD's as possible, others just buy the ones they like (or can afford).
I'm not sure how many DVD's I have at this time, but there are quite a few DVD's that you just have to have in your collection.
If you feel wronged because your favourite movie is not listed, feel free to add a comment stating your favourites. (Oh, let me know why it's such a great movie too!)
<!--more-->
<h3>5. Gladiator</h3>
<img align="right" id="image11" src="http://ariejan.net/wp-content/uploads/2006/10/06m1.jpg" alt="Gladiator" />Gladiator, by Ridley Scott, is tells the story off a Roman general who became a slave and then a gladiator. It sounds pretty boring when you put it like that, but Scott really makes it into a very gripping movie.
Gladiator is more than a few man in shorts fighting in a big bowl of sand. You should really check this one out and add it to your collection.
<h3>4. The Lord of the Rings Trilogy</h3>
<img align="right" id="image10" src="http://ariejan.net/wp-content/uploads/2006/10/10m.jpg" alt="Lord of the Rings" />Well, <a href="http://imdb.com/title/tt0120737/">The Lord of the Rings</a> is not really a trilogy since it is one big story. Still, this movie is great.
LOTR, by <a href="http://imdb.com/name/nm0001392/">Peter Jackson</a>, attracts old and young alike. It features humour, heroism, love, massive battles between good and evil and everything else needed to make a successful movie.
Many complain that the Fellowship (part 1) does not have much action in it and that Return of the king (part 2) is just one big fat ending. Well, that's correct. In my opinion you should watch the three movies in sequence all at once. That will give you the full sensation the way Jackson intended it.
Because this movie appeals to a very broad audience, it's placed at position 4.
<h3>3. Pulp Ficton</h3>
<img id="image7" align="right" src="http://ariejan.net/wp-content/uploads/2006/10/06m.jpg" alt="Pulp Fiction" />The combining of several story lines into one movie with a lot of violence by <a href="http://imdb.com/name/nm0000233/">Quentin Tarantino</a>. The result is <a href="http://imdb.com/title/tt0110912/">Pulp Fiction</a>.
Every story line has it's own characters and Tarantino was able to get a lot of big names attached to this film including Bruce Willis, John Travolta, Samuel L. Jackson and Uma Thurman.
This movie is not just entertainment, it's art. If you don't have it, you should probably get is a.s.a.p.
<h3>2. Star Wars (all six of 'em)</h3>
<img id="image9" align="right" src="http://ariejan.net/wp-content/uploads/2006/10/42m.jpg" alt="Star Wars" /><a href="http://imdb.com/title/tt0076759/">Star Wars</a> is the work of <a href="http://imdb.com/name/nm0000184/">George Lucas</a>. George has done many innovative things during the creation of his Star Wars movies. Not only was he the first to introduce (and claim the rights to) merchandising, he has also brought special effects to a new level. Of course, I don't have to remind you that George Lucas is also the genius behind the <a href="http://en.wikipedia.org/wiki/Thx">THX</a> sound system.
If I have to tell you what Star Wars is about, you should not be allowed to have a DVD collection at all.
<h3>1. The Godfather Trilogy</h3>
<img id="image8" src="http://ariejan.net/wp-content/uploads/2006/10/20m.jpg" alt="The Godfather" align="right" />I think everybody knows the <a href="http://imdb.com/title/tt0068646/">Godfather</a>. Directed by <a href="http://imdb.com/name/nm0000338/">Francis Ford Coppola</a>, this epic trilogy gives us an inside look in the Corleone family.
Part one is really the best movie of all three. It's based on the original novel by <a href="http://en.wikipedia.org/wiki/Mario_Puzo">Mario Puzo</a>. However, parts two and three really complement the whole story and that's what makes this such a great trilogy.
There are some very nice Trilogy DVD Boxes available. If you say you like movies, you cannot be taken seriously unless you have this trilogy in your collection.

View File

@ -0,0 +1,12 @@
+++
date = "2006-10-13"
title = "Google Ads: Cant click em, but you want to know more!"
tags = ["General", "Everything", "Blog", "Google", "AdSense", "Discussion"]
slug = "google-ads-cant-click-em-but-you-want-to-know-more"
+++
Do you have Google Ads on your site? You know you are not allowed to click 'em, because that's fraude. But what do you do when you see an ad on your site that really grabs your attention? Just google? Enter the URL manually? Or are you the kind of person that clicks that ad anyway.
What would you do? Please let me know.
<!--more-->

View File

@ -0,0 +1,20 @@
+++
date = "2006-10-13"
title = "Having fun with SPAM!"
tags = ["General", "Everything", "Blog", "Fun"]
slug = "having-fun-with-spam"
+++
I was just wading through my SPAM at Gmail to see if it flagged anything important. Then I came across this message:
<strong>Is your website www.gmail.com offline, or why can't I find it on Yahoo?</strong>
<blockquote>Your website (www.gmail.com) on top positions on Google, Yahoo and MSN search!
We will get your website (www.gmail.com) to the top positions on all major search engines.
Use our great value offer:
We will submit your website (www.gmail.com) to 890 Search Engines, including Google, Yahoo and MSN.</blockquote>
Just keep an eye out for funny SPAM mails. Feel free to let me know if you ever read a funny or really stupid SPAM message.
<!--more-->

View File

@ -0,0 +1,30 @@
+++
date = "2006-10-13"
title = "Migrate SQLite3 to MySQL easily"
tags = ["General", "Everything", "RubyOnRails", "Databases", "Features"]
slug = "migrate-sqlite3-to-mysql-easily"
+++
I've been using a simple Rails application locally with a SQlite 3 database for some time. Now I want to move to another host and use MySQL instead. But guess what? You can't just migrate your data!
Here are some easy steps on how to migrate your data to MySQL. First of all you need to dump your SQLite3 database. This includes transaction statements and create commands. That's fine. Since we also migrate the schema information, our RoR app will not know any difference after we change config/database.yml.
The biggest probem I encoutered was that the SQLite3 dump places table names in double quotes, which MySQL won't accept.
~
First, make sure you create your MySQL database and create a user to access that database. Then run the following command. (It's a long one, so where you see a \, just continue on the same line.)
sqlite3 db/production.sqlite3 .dump | \
grep -v "BEGIN TRANSACTION;" | \
grep -v "COMMIT;" | \
perl -pe 's/INSERT INTO \"(.*)\" VALUES/INSERT INTO `\1` VALUES/' | \
mysql -u YOURUSERNAME -p YOURPROJECT_production[/source]
This will take the SQLite 3 dump, remote the transaction commands. Next I use perl to replace all INSERT commands containing double quotes with something MySQL will understand.
That's it. You MySQL database will be populated with your data.
<em>Don't forget to change your config/database.yml file after this!</em>
Note. You may also migrate your MySQL database using Rails. If you do this I recommend that you dump the SQLite3 database to a file first before you commit it directly to MySQL. You'll have to remove the CREATE TABLE statements as well as any reference to the schema_info table.

View File

@ -0,0 +1,62 @@
+++
date = "2006-10-13"
title = "Tagging in ajax_scaffold"
tags = ["General", "Everything", "Web Development", "RubyOnRails", "Features"]
slug = "tagging-in-ajax_scaffold"
+++
I've been using the <a href="http://www.ajaxscaffold.com/">Ajax Scaffold</a> for quite some time now. It's a great piece of software by <a href="http://www.height1percent.com/">Mr. Richard White</a> for <a href="http://www.rubyonrails.com">Ruby on Rails</a>. It seems that the plugin version of AS is getting quite a bit more attention than the generator. I started out with the generator but quickly reverted to the plugin since it's way more flexible and easier to use.
Since I wanted to create a quick app to inventory my CD/DVD collection (which is now in a very sexy alu DJ case) I used Ajax Scaffold to get me started. In the spirit of Web 2.0 I wanted to add tags to every CD so it would be easier to find certain kinds of disks later on. So, I added <a href="http://wiki.rubyonrails.org/rails/pages/Acts+As+Taggable+Plugin">acts_as_taggable</a>.
Acts_as_taggable basically allows you to tag any model in your app. So, I made my Disk model taggable. Great. Now I could do this:
d = Disk.new(:number => 1, :name => "Mac OS X 10.4.6 Install DVD 1")
d.tag_with("macoxs apple macbook install")
d.save
The real problem was, how to get this functionality easily integerated in Ajax Scaffold?
~
First of all I had to show a column in AS that included the tags attached to a given disk. I specify all rows manually in the Manager controller. Manager is scaffolded using AS. Here's what my Manager controller looks like:
class ManagerController < ApplicationController
ajax_scaffold :disk
@@scaffold_columns = [
AjaxScaffold::ScaffoldColumn.new(Disk, { :name => "number" }),
AjaxScaffold::ScaffoldColumn.new(Disk, { :name => "name" }),
AjaxScaffold::ScaffoldColumn.new(Disk, { :name => "tags",
:eval => "row.tag_list", :sort => "tag_list"}),
]
end
This will show three columns, including a column named 'tags'. Every model that acts_as_taggable has some extra methods. tag_list is a single string containing all tags seperated by spaces. So, the tags column shows the tag_list for that row. With :sort I specify that AS can just sort keywords alphabetically.
Great! I now can see tags on disks! But, we also need to add those tags and that's where it got tricky.
<h4>Adding tags</h4>
Adding tags is not done by assignment but by calling a method with your tags, as shown before: tag_with (string). I could create a custom create and update method for the Disks, but there's a prettier solution available.
tag_list returns a string with the current tags. How about using that same name to assign tags? It's rather easy. Here's my Disk model:
class Disk < ActiveRecord::Base
acts_as_taggable
validates_presence_of :name, :number
def tag_list=(new_tags)
tag_with new_tags
end
end
Now we can assign tags to tag_list as well as read the tags out. Now the only step is to add a special textfield to the form partial for AS.
<label class="required">Tags</label>
<%= text_field 'disk', 'tag_list' %>
Now when a new disk is created or when one is updated, the tag_list will automagically be updated in a correct fashion.
Enjoy!

View File

@ -0,0 +1,14 @@
+++
date = "2006-10-13"
title = "Torrents for your iPod!"
tags = ["General", "Everything", "Blog", "Links", "Apple", "iPod"]
slug = "torrents-for-your-ipod"
+++
I normally wouldn't promote torrent sites here, but when I came across <a href="http://www.podtropolis.com">Podtropolis</a> I was amazed!
This site features a lot of (video) iPod specific stuff like music videos, TV Shows and even full length movies.
Of course, don't download any of the stuff! Buy it if you want it.
<!--more-->

View File

@ -0,0 +1,11 @@
+++
date = "2006-10-17"
title = "Happy birthday to me!"
tags = ["General", "Everything", "Ariejan.net", "Blog"]
slug = "happy-birthday-to-me"
+++
Today I'm turning 26. Yes, call me an old fart, but I still feel like 25!
Anyway, I'm off celebrating with my friends.

View File

@ -0,0 +1,24 @@
+++
date = "2006-10-23"
title = "Ruby On Rails for PHP: CakePHP"
tags = ["General", "Everything", "Blog", "Web Development", "RubyOnRails", "CakePHP"]
slug = "ruby-on-rails-for-php-cakephp"
+++
The framework has been around for some time, but I found out about it a few days ago: <a href="http://www.cakephp.org">CakePHP</a>.
I've been using <a href="http://www.rubyonrails.com">Ruby on Rails</a> for quite some time now. It's a very cool framework and it's fun to work with. However, there's one big problem I have with it: I can't host it anywhere!
Well, there are several hosting companies that offer Rails hosting, but the price is pretty steep when compared to my current hosting plan. I could get a VPS or dedicated server, but that just be overkill for the applications I want to run.
So, I started thinking. What can be done in Ruby could be done in PHP as well. Maybe not in such an elegant and intuitive way, but it should be possible. And I was right.
~
After some googling I came across <a href="http://www.cakephp.org">CakePHP</a>. CakePHP aims to implement the MVC (Model-View-Controller) structure in PHP much in the same way Rails does it for Ruby.
After giving it a try I found that CakePHP is a pretty good alternative to Rails. Most importantly, it runs with both PHP4 and PHP5 and it can handle MySQL, SQLite and other standard databases.
If you're an agile developer but you don't want to nail yourself down on hosting with Ruby or if you really want to use PHP, CakePHP is a great framework to use!
<a href="http://www.cakephp.org">http://www.cakephp.org</a>

View File

@ -0,0 +1,20 @@
+++
date = "2006-10-29"
title = "Do your ads pay your (blogging) bills?"
tags = ["General", "Everything", "Blog", "AdSense"]
slug = "do-your-ads-pay-your-blogging-bills"
+++
I've read many articles on earning money with <a href="http://www.google.com/adsense">Google's AdSense</a>. Some guru's claim to recieve five figure checks from Google every month.
The trick with these people is that they have a lot of content. More content, means more visitors, which means more clicks and thus more money. The content is written to attract certain keywords which are known earn a lot of money. Of course, professionals don't just have one site, they have several. In order to cope with all this content they have an almost full-time job. That's not bad if you earn a five figure amount every month.
~
But, how about us, regular bloggers who just want to share our bit of knowledge with the rest of the world. Most of us have Google Ads on our site, including me. My site has been refurbished quite a few times in the past few months and the content I had <a href="http://ariejan.net/2006/10/09/welcome-to-ariejannet/">is gone</a>. So, I'm not really hot in this business.
Most bloggers post a few items every few days. Some of us are really cool and post several items a day. What I want to know is: <strong>can Google Ads pay your (blogging) bills?</strong>
I mean, is there really anyone, except the kick-ass professional bloggers, who can make a bit of money of their blog? And if so, do they have any tips they'd like to share with the world?
Please let me know or post any relevant articles here. I'm looking forward to your reponse!

View File

@ -0,0 +1,42 @@
+++
date = "2006-10-30"
title = "Adsense Resource Inventory"
tags = ["General", "Everything", "Blog", "Links", "AdSense"]
slug = "adsense-resource-inventory"
+++
In addition to my <a href="http://ariejan.net/2006/10/29/do-your-ads-pay-your-blogging-bills/">previous post</a> I have gathered some popular resources from around the web that talk about making money off <a href="http://www.google.com/adsense">Google Adsense</a>. I hope this sums up all you need to start making money yourself.
Please, let me know if I missed something.
<h3>Things to know about making money with Google Adsense</h3>
There are three things you need in order to make money off your site or blog.
<ul>
<li>Visitors</li>
<li>Content</li>
<li>Ads</li>
</ul>
This post is about the last part, Ads. I'll talk about getting visitors and creating content in a later post, so stay tuned!
~
So, how to get those ads setup right so you generate the most revenue possible. It's not as easy as it sounds and mostly it's a trial-and-error process. But, there are some general guidelines that will help you get started.
<em>I highly recommend you do <strong>NOT</strong> buy any software that claims to track Google Ads or create content or sites for you! If you need to track your ads, use Google Analytics, it's free. Content and site generators give you the same site and same content as others. Google knows all and they don't like copy-cats whos only goal is to make money.</em>
<ol>
<li><a href="http://www.quickonlinetips.com/archives/2006/07/google-adsense-tips-and-tools-collection/">Google Adsense Tips and Tools Collection</a><br />This should be in your bookmarks! Great tips, tools and free software that will get you started immediately!</li>
<li><a href="http://www.adsensecalculator.com/">Adsense Calculator</a><br />This nifty device tries to predict how much money you can make of your site according to your current statistics. <em>Let me know if this actually works or not!</em></li>
<li><a href="http://www.associateprograms.com/articles/129/1/How-to-boost-your-AdSense-revenue">How to boost your Adsense revenue</a><br />Great article that introduces new users to Adsense and gives tips on how to get started. See my remark about buying software, though.</li>
<li><a href="http://adsensemaster.blogspot.com/2005/11/15-common-mistakes-by-google-adsense.html">15 Common mistakes</a><br />15 Common mistakes made by Adsense publishers. Read this, and don't make the same mistake.</li>
<li><a href="http://www.seobook.com/">SEOBook</a><br />Great site. It contains many links and resources to Adsense related articles.</li>
<li><a href="http://www.wolf-howl.com/22/google-adsense-tips-tricks-and-secrets/">More Adsense Tips and Secrets</a><br />Another site with great tips and Adsense secrets.</li>
<li><a href="http://wisdom-of-adsense.org/?q=node/13">Adsense Wisdom</a><br />10 Easy steps in making your Adsense experience successful.</li>
<li><a href="http://explorerdestroyer.com/">Explorer Destroyer</a><br />This site has some code that will kick Internet Explorer users to use Firefox instead. Oh, you use Google referrals for that.</li>
<li><a href="http://adsense.blogspot.com/">Inside Adsense</a><br />The official AdSense blog from Google.</li>
</ol>
Please post a comment if I have missed anything important.

View File

@ -0,0 +1,14 @@
+++
date = "2006-10-30"
title = "Cheat sheets? Look here!"
tags = ["General", "Everything", "Blog", "Links"]
slug = "cheat-sheets-look-here"
+++
Getting confused of all the tools you use on a daily basis? Don't remember all the exact method names and possibilities of SubVersion, Apache, HTML, CSS, MySQL, Ruby on Rails, CVS, AJAX, JavaScript, FireFox, Google, etc. etc.? There is a solution! Cheat sheets make your daily work easier by providing you all you need to know on a single paper!
Here's a <a href="http://www.smashingmagazine.com/2006/10/30/cheat-sheet-round-up-ajax-css-latex-ruby/">very comprehensive list</a> of cheat sheets.
Cheat sheets are simple put a collection of all important (if not just all) functions and methods you can use for a given product, framework or language. They're great to have on your desk if you just can't quite remember what function to use. Check 'em out, print 'em out and start loving 'em!
<!--more-->

View File

@ -0,0 +1,12 @@
+++
date = "2006-10-30"
title = "Confused about CSS Columns?"
tags = ["General", "Everything", "Blog", "Web Development"]
slug = "confused-about-css-columns"
+++
I'm mainly confused on how to make different layouts with pure CSS. Back in the time when tables were okay, it was rather easy. But with CSS it's gotten rather tricky.
<a href="http://www.dynamicdrive.com/style/layouts/">Dynamic Drive</a> has some great examples (with CSS code!) of different kinds of layouts. It's great to use as a starting point for your design!
<!--more-->

View File

@ -0,0 +1,15 @@
+++
date = "2006-10-30"
title = "How does your site look on …?"
tags = ["General", "Everything", "Blog", "Web Development", "Links"]
slug = "how-does-your-site-look-on"
+++
When designing a web site you always check how the site looks in different browsers, even maybe at different resolutions. But how many browsers do you really use? Firefox, Safari when on Mac, Internet Explorer when on Windows and that's mostly it.
<a href="http://browsershots.org/">Browser Shots</a> allows you to select different browsers and set several options like colour depth, screen resolution, java etc. and make screenshots of your site (by entering the URL).
I don't need to tell you this is a great resource. It's great to check if your design works and it's even better to get a screenshot generated from your new designs. Only problem is that you'll have to put them online first.
Check out some screenshots <a href="http://browsershots.org/screenshots/">here</a>.

View File

@ -0,0 +1,24 @@
+++
date = "2006-10-31"
title = "WordpressMu: Dont allow new blogs"
tags = ["General", "Everything", "Features", "WordPressMu"]
slug = "wordpressmu-dont-allow-new-blogs"
+++
If you're using <a href="http://mu.wordpress.org">WordpressMu</a>, the blog hosting tool used on <a href="http://www.wordpress.com">Wordpress.com</a>, you may want to disable the creation of blogs by your visitors.
Whatever your reasons for this are, I wanted to prevent this, because I (and my team of editors) want to maintain several blogs on different topics. Users are free to register and post comments, but creating new blogs is reserved for the administrator.
So, how do you implement this in WordpressMu? There is no checkbox (yet) that disables this feature. So, I had to hack the WordpressMu code a bit.
~
First, open up wp-signup.php. If you access a blog that does not exist, you'll be redirected to the signup page and be presented a signup form for that particular blog.
Open up wp-singup.php en just above the get_header(); call, place the following code:
if (!is_user_logged_in() || $user_identity != 'admin') {
header("Location: http://example.com/gofishatthispage/");
exit();
}
What this does is make sure that only a logged in user named 'admin' is allowed to proceed to the blog creation form. Others will be redirected to a location of your choice. A good idea is to send people to a page that explains why they can't' create a blog or what they have to do to get an administrator to create one for them.

View File

@ -0,0 +1,25 @@
+++
date = "2006-11-13"
title = "CUPS: 426 - Upgrade Required"
tags = ["General", "Everything", "Features", "Linux", "Ubuntu"]
slug = "cups-426-upgrade-required"
+++
As I was installing my printer on my Ubuntu 6.06 Dapper LTS server with CUPS I noticed the following error:
**426 Upgrade Required**
After some research I came to the conclusion that CUPS, by default, tries to use SSL whenever possible. So, with this 426 error, you are redirected to the SSL domain. Chances are, you haven't configured SSL properly, if at all.
In my case, I didn't want to configure SSL. To get rid of this problem, the key lies in editing your configuration files ( /etc/cups/cupsd.conf ) and adding the following line:
<pre lang="bash">DefaultEncryption Never</pre>
There are several options, Never, IfRequired and Required. By setting this to Never, SSL will never be enforced. Just restart your CUPS server with
$ /etc/init.d/cupsys restart
and you're good to go.

View File

@ -0,0 +1,74 @@
+++
date = "2006-11-15"
title = "Ubuntu 6.10 Live DVD on the Apple MacBook"
tags = ["General", "Everything", "Blog", "Linux", "Ubuntu"]
slug = "ubuntu-610-live-dvd-on-the-apple-macbook"
+++
Since I teach various Linux courses at Fontys Centrum IT, I want to run a live CD or DVD on my MacBook. First off, here are my specs:
<ul>
<li>Apple MacBook (White)</li>
<li>Intel Core Duo 2.0Ghz</li>
<li>1.0Gb RAM</li>
<li>13.3" 1280x800 TFT</li>
<li>60 Gb Internal Harddisk</li>
<li>300 Gb External FireWire harddisk</li>
</ul>
As my Live medium I chose the Ubuntu Linux 6.10 Live DVD. This DVD has several nice options (install server, for example) that I like. It also can boot up in a live desktop environment.
~
As a matter of fact, everything I need works out of the box. Wireless works fine, my mouse (USB Logitech) works, the FireWire harddisk (which has a FAT32 filesystem, so I can hook it to my girl friend's Windows PC) works perfectly.
There are only two things that didn't work.
1. Xvid codecs are missing, so I can't watch my Prison Break episodes from the Live environment, but that's perfectly fine. That's not what I need the live environment for.
2. The screen resolution can only be set to a maximum of 1024x768. As I mentioned before, the TFT has a native resolution of 1280x800. Because of the scaling, my screen doesn't look as sharp and sexy as it should.
In order to solve this problem I had to take a few, rather easy, steps.
To get started, let us assign a password to the default ubuntu user.
sudo passwd ubuntu
Now enter something that you'll remember easily, twice.
In order to get Ubuntu to recognize the native screen resolution automatically, we'll need a special package: 915resolution. Since the MacBook has an Intel 945 graphics chipset, we can use this tool. But, this tool is not in the default package respository. It's in the Universe.
So, we now need to change <strong>/etc/apt/sources.list</strong> and add the universe repository. This is rather easy, because these repositories already exist, but are commented out. Just open up /etc/apt/sources.list and uncomment the two universe lines. Make sure your sources.list looks like this:
deb http://archive.ubuntu.com/ubuntu edgy main restricted
deb-src http://archive.ubuntu.com/ubuntu edgy main restricted
## Uncomment the following two lines to add software from the 'universe'
## repository.
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## universe WILL NOT receive any review or updates from the Ubuntu security
## team.
deb http://archive.ubuntu.com/ubuntu edgy universe
deb-src http://archive.ubuntu.com/ubuntu edgy universe
deb http://security.ubuntu.com/ubuntu edgy-security main restricted
deb-src http://security.ubuntu.com/ubuntu edgy-security main restricted
Now, we can update our system and install the 915resolution package.
apt-get update
apt-get install 915resolution
You'll notice that 915resolution spits out a lot of information on your chipset and native resolution. You should check here that the 1280x800 resolution has been detected.
Now you're all set. Well, you'll need to restart the X Server in order for it to recognize the newly discovered resolution. I basically pressed CTRL-ALT-BACKSPACE to kick the X Server. I'm presented with a login screen. Here I login as 'ubuntu' with the password I specified earlier.
If everything went fine, you'll now get a clear and sharp display of your Ubuntu life desktop.
I also turned on sub-pixel smoothing in System -> Preferences -> Fonts to get some sexier and smoother looking fonts.
That's all. I can now boot-up the Ubuntu Live DVD and get the native resolution for my MacBook.
For those who want to keep the native resolution on their installed Ubuntu, just install the 915resolution package mentioned above and you're set. Easy as that.

View File

@ -0,0 +1,13 @@
+++
date = "2006-11-17"
title = "Announcing CSE-Tool: Deploy you Google CSE with ease"
tags = ["General", "Everything", "Blog", "CSE-Tool"]
slug = "announcing-cse-tool-deploy-you-google-cse-with-ease"
+++
This is just a short note to let you know that <a href="http://www.sourceforge.net/projects/cse-tool/">CSE-Tool 1.0</a> has been released.
The CSE-Tool allows you to easily (just copy-paste a few items presented to you by Google) deploy your Custom Search Engine. All you need is a CSE (of course) and optionally a Google Analytics account to track who's coming by.
System requirements are pretty low. You'll only need PHP 4.3.x or better. Check out the <a href="http://www.sourceforge.netl/projects/cse-tool/">SourceForge Project Page</a> or jump directly to the <a href="http://sourceforge.net/project/showfiles.php?group_id=182622&package_id=211849&release_id=464420">downloads section</a>.

View File

@ -0,0 +1,19 @@
+++
date = "2006-11-21"
title = "CSE-Tool 1.1.0 Released"
tags = ["General", "Everything", "Blog", "CSE-Tool"]
slug = "cse-tool-110-released"
+++
Hot of the press! CSE-Tool 1.1.0 has been released just a few minutes ago! <a href="http://sourceforge.net/project/showfiles.php?group_id=182622&package_id=211849&release_id=465386">Grab the code now</a> or check a <a href="http://www.search-london.net/">live demonstration</a>!
Please report any feature, support or bug requests back at the project's <a href="http://sourceforge.net/projects/cse-tool/">SourceForge page</a>.
Also, if you like CSE-Tool (and want your feature added sooner rather than later) please consider making a small donation to the project to encourage further development and support.
Donations are handled by <a href="http://www.sourceforge.net">SourceForge</a>.
<a href="http://sourceforge.net/project/project_donations.php?group_id=182622"><strong>Please consider making a donation to the project. Thank you!</strong></a>
To see how I manage a the creation of a release through SubVersion, check <a href="http://ariejan.net/2006/11/21/svn-how-to-release-software-properly/">this post over here</a>.

View File

@ -0,0 +1,62 @@
+++
date = "2006-11-21"
title = "SVN: How to release software properly"
tags = ["General", "Everything", "Web Development", "Features", "Subversion"]
slug = "svn-how-to-release-software-properly"
+++
Many projects use SubVersion nowadays to store their project code. I do this also at work, and for my personal projects like <a href="http://ariejan.net/tags/cse-tool/">CSE-Tool</a>.
The question, however, is how to release your current code properly to the public. You probably don't want your users to check out your current development code. Either you want them to check out a certain version (release) or you want to present them with a download archive containing the code.
I'm going to show you how to release a simple PHP application from SubVersion as an archive file to my users.
~
The base layout of my svn repository is like this. I have directory named 'trunk' that always contains the most recent version of the software. This is the development branch, so to say. I also have a 'branches' and a 'tags' directory. If you don't have these, you'll need to create them now:
$ svn mkdir -m "Creating branches directory" svn://yourrepository/branches
Commited revision 123.
$ svn mkdir -m "Creating tags directory" svn://yourrepository/tags
Commited revision 124.
In this case my current development code, in the trunk of the svn repository is at revision 10. All files in the trunk are marked to be develoment quality. This means that I don't display version numbers, but simply show 'HEAD' to indicate you're working with a development quality product. Before I release this code to the public, I want to tweak a few things. Since this is not general development, I create a <strong>Release Branch</strong>. This release branch is basically a copy of the current code in the trunk. Changes to that branch are stored seperately from the development code, so I can easily tweak it to release quality.
Creating the release branch is really easy. Let's say I want to release version 1.1.0 of CSE-Tool. I just copy the code in subversion. Note that I don't download and store the code on my local machine. SubVersion is smart and duplicates the code on the server. This can save you valueable bandwidth, especially when you're working on a large project.
Well, create the Release Branch which is named, by convention, RB-1.1.0.
$ svn copy -m "Creating release branch 1.1.0" https://svn.sourceforge.net/svnroot/cse-tool/trunk https://svn.sourceforge.net/svnroot/cse-tool/branches/RB-1.1.0
Committed revision 11.
You can see at <a href="http://cse-tool.svn.sourceforge.net/viewvc/cse-tool/branches/">http://cse-tool.svn.sourceforge.net/viewvc/cse-tool/branches/</a> that the new release branch (RB-1.1.0) was created as a directory containing a copy of the current develoment code.
I can now do two things. Either I checkout a seperate working copy of the release branch or I change my current working copy (which is using the trunk) to use the release branch. Checking out is easy, but I'll show it first to you anyway. Next I'll show you how to switch your repository.
Just check out your code as you'd normally do, but make sure you specify the release branch. I've also specified to store this code in a directory named cse-tool-1.1.0 so I don't confuse it with the trunk code, which is stored in a directory named 'cse-tool'.
$ svn co https://svn.sourceforge.net/svnroot/cse-tool/branches/RB-1.0.0 cse-tool-1.1.0
I could also swich my current working copy to the release branch. This may be useful if your project is very huge and you don't want to download the whole thing again. Switching between a release branch and the trunk is usually more efficient because you only need to download the differences between the two.
$ svn switch https://svn.sourceforge.net/svnroot/cse-tool/branches/RB-1.0.0
Okay, now I can work on the release branch. Branding it with the right version number among other things. In your case it might be a good place to two SQL files to install or update a database you are using. You might want to update the changelog and other documentation.
When you commit changes, they will be applied to the release branch only, <strong>not</strong> not to the current development code.
When you're done you may switch back to the current development code:
$ svn switch https://svn.sourceforge.net/svnroot/cse-tool/trunk
The code in the release branch is now ready to be shipped out. We want to mark this code as being Relese 1.1.0. This is called tagging. A tag is nothing more than a copy of the repository on a give moment. Technically, a branch and tag are the same. However, the conventions I use dictate that you don't change the code in a tag because it represents a certain state of your code, in this case the state the code was in at the time of Release 1.1.0.
Now, to actually create a release tag, named REL-1.1.0, we use the same procedure as with the creation of the release branch. Just note the differences in the source and destination repositories.
$ svn copy -m "Tag release 1.1.0" https://svn.sourceforge.net/svnroot/cse-tool/branches/RB-1.1.0 https://svn.sourceforge.net/svnroot/cse-tool/tags/REL-1.1.0
Committed revision 13.
With the REL-1.1.0 tag we can create an archive that we can distribute to our users. Because we don't want to include svn metadata in our release we can't use checkout for this. SubVersion allows us to export our code, which is basically a check out, but without all the svn metadata. This is ideal to ship to our customers.
$ svn export https://svn.sourceforge.net/svnroot/cse-tool/tags/REL-1.1.0 cse-tool-1.1.0
Next I can tar up the cse-tool-1.1.0 directory and put the files on SourceForge. (<a href="http://sourceforge.net/project/showfiles.php?group_id=182622&package_id=211849">Download them here :)</a>)

View File

@ -0,0 +1,15 @@
+++
date = "2006-11-22"
title = "Google Project Hosting: SourceForge Competitor"
tags = ["General", "Everything", "Blog", "Web Development", "Links", "Google"]
slug = "google-project-hosting-sourceforge-competitor"
+++
I just found out that <a href="http://code.google.com/">Google Code</a> is now offering <a href="http://code.google.com/hosting/">Project Hosting</a>! It's in the same style as <a href="http://www.sourceforge.net">SourceForge</a>, but the Google way!
As a Google user you can create a project with a built-in issue tracker and Subversion repository. And if that's not all, you can tie in a blog (at Blogger.com is you like) and adiscussion group (on Google Groups, of course).
This is really a nice package Google is offering and it looks like a serious competitor for SourceForge.
It's just that I didn't find any possibility to release files yet, but other than that, I'd like to move there!

View File

@ -0,0 +1,48 @@
+++
date = "2006-11-22"
title = "Plugins used on Ariejan.net"
tags = ["General", "Everything", "Wordpress", "Ariejan.net", "Blog"]
slug = "plugins-used-on-ariejannet"
+++
After I released <a href="http://ariejan.net/2006/11/21/iariejan-wordpress-theme-10/">iAriejan</a> I got some questions about what plugins I run on Ariejan.net. So, upon your request, here is the full listing.
I've included links to all the sites where you can download the plugins.
Note that <a href="http://ariejan.net/2006/11/21/iariejan-wordpress-theme-10/">iAriejan</a> comes bundeled with WP Wetfloor and AJAX Comments.
~
<ul>
<li><a href="http://www.mikesmullin.com/2006/06/05/ajax-comments-20/">AJAX Comments</a>
This plugin allows the instant posting of plugins with a nice and sexy AJAX effect. Very Web 2.0ish.</li>
<li><a href="http://akismet.com/">Askimet</a><br />
Allows the screening of comments for SPAM. This is great in combination with the AJAX Comments!</li>
<li><a href="http://mightyhitter.com/main-page/plugins/mightyadsense/">Mighty Adsense</a><br />
Places Google Ads on my blog (without editing the theme) in order to cover my hosting expenses.</li>
<li><a href="http://maxpower.ca/">Adsense Target</a><br />
AdSense Target marks the important stuff so Google Ads match even better with the content on Ariejan.net. This is called Ad Targetting and supported by Google. Invisible to you, but still very nice!</li>
<li><a href="http://blog.finke.ws/?p=11">FeedBurner Widget</a><br />
Allows me to publish my RSS feed through FeedBurner. This is great for the management of the feed and usage (not user!) tracking.</li>
<li><a href="http://boakes.org/analytics">Google Analytics</a><br />
This plugin makes use of Google Analytics' ability of tracking visitors on your site. This way I can see how people visiting Ariejan.net interact with my site and which parts need improvement.</li>
<li><a href="http://blog.igeek.info/wp-plugins/igsyntax-hiliter/">iG:Syntax Hiliter</a><br />
This plugin allows me to easily post different kinds of code like Ruby, PHP and C#. It will show the code properly formatted, syntax highlighting is included and it will allow you to copy it all as plain text! Want a <a href="http://ariejan.net/2006/11/21/svn-how-to-release-software-properly/">demonstration</a>?</li>
<li><a href="http://svn.wp-plugins.org/widgets/trunk">Sidebar Widgets</a><br />
Actually, I don't use widgets right now. I use a static sidebar. I plan on using it some time. I have it installed for the FeedBurner widget to do its work.</li>
<li><a href="http://www.siuyee.com/projects/wp-wetfloor/">WP Wetfloor</a><br />
This is a brilliant plugin. It uses Javascript to create reflections of images. It uses the current background colour as a basis and is fully configurable by adding a few CSS classes. Of course, this degrades very nicely on non-javascript clients. You'll just have to miss the eye-candy.</li>
</ul>
Well that's all there is. If you can think of any plugin that I should use (but am currently not using), feel free to drop a comment.
Edit: I completely forgot to mention <a href="http://www.mikesmullin.com/2006/06/05/ajax-comments-20/">AJAX Comments</a>. It has been added to the list.

View File

@ -0,0 +1,80 @@
+++
date = "2006-11-22"
title = "SVN: How to fix bugs properly"
tags = ["General", "Everything", "Web Development", "Features", "Subversion"]
slug = "svn-how-to-fix-bugs-properly"
+++
I've already told you about <a href="http://ariejan.net/2006/11/21/svn-how-to-release-software-properly/">releasing your project with help from Subversion</a>. Now I want to talk to you about using Subversion to fix bugs in your application.
Fixing bugs can be as easy as fixing a few lines of code or as hard as rewriting a significant portion of your application. Both situations need a different approach from us. Let's talk about the easy stuff first.
For this example let's say we have a project. It has a release branch named RB-1.0 and current development is going on in the trunk.
A user has submitted a bug report (numbered #3391) against your 1.0 release. Here's what to do:
~
### Easy bug fixes
Let's say bug #3391 is an easy fix. First, check out a working copy of the release branch.
$ svn co https://example.com/branches/RB-1.0 rb-1.0
Now, go in there, write tests that expose the bug and fix it. As I said, it's an easy fix so you can commit all your changes at once to the release branch. When you do this, remember the new revision number.
**Note:** it's always smart to include the number of the bug (in this case #3391) in your commit message. This will make sure other developers (and later on, yourself) know what bug was fixed here.
$ svn commit -m "Bug fixed #3391"
...
Committed revision 183.
As I said, remember the revision number: 183.
Now you have the bug fixed in the release branch for version 1.0, you are probably wondering if the bug exists in your current development code as well. Since branches are plain copies of your development code, the big probably is there too.
Don't start editing your working copy of the trunk and start fixing the bug all over again. Let Subversion do the work.
Go into your trunk working copy and update it to the latest revision, this is revision 183. But, we only made changes to the release branch, and not to the trunk, so we need to merge those changes. We can do this by running the following command:
$ svn merge -r182:183 https://example.com/branches/RB-1.0 rb-1.0
You'll now see the fix you applied in the release branch getting merged with your current development code. Great, isn't it?
Before you leave to party, don't forget to commit the changes to the trunk. Again, name the bug number you fixed here and also which revision you userd to merge it.
$ svn commit -m "Merge r183 (bug fixed #3391)"
You can apply this merge process with any other release branch you have if that' necessary.
### Difficult bug fixes
Another scenario is that the bug is not easy to fix. You need to rewrite a lot of tests to expose the bug in the first place, and even then you're not sure how to go about fixing it.
If that's the case, you are better of creating a seperate bug fix branch. This allows you to fix the bug in the background, possibly with the help of others, while current development can still go on. Also, you want to create snapshots of before (pre) and after (post) the bug fix. These tags will help you merge the fix into other branches later on.
First, create a bug fix branc. By convention Release Branches were called RB-1.0, Bug fix branches are called BUG-###. Of course, ### corresponds to the bug report number. In this case we create a branch named BUG-3391. We also need to create a snapshot of the code before we start fixing the bug. We call this tag PRE-3391.
$ svn copy -m "Create bugfix branch" https://example.com/branches/RB-1.0 https://example.com/branches/BUG-3391
$ svn copy -m "Tag start of bug fix" https://example.com/branches/BUG-3391 https://example.com/tags/PRE-3391
Now, you can checkout the bug fix branch and start work. You may call in the help of others if you need to. It's okay to make multiple commits to this branch.
When you have reached the point were the bug is fixed, you'll need to mark the end of it. We create a new tag named POST-3391 to mark the end of the bugfix:
$ svn copy -m "Tag end of bug fix" https://example.com/branches/BUG-3391 https://example.com/tags/POST-3391
Well. You're done! Your bug has been fixed! But wait a minute. The fix is not present in the release branch yet! Here, again, we need to merge the bug fix into the release branch (and possibly into the trunk also).
First, update your current working of the release branch and merge the changes between the PRE-3391 and POST-3391 tags with the release branch. When done, run your tests to make sure everything works as expected and commit your changes.
$ svn update
$ svn merge https://example.com/tags/PRE-3391 https://example.com/tags/POST-3391
$ svn commit -m "Merged bug fix for bug #3391"
### Final note
It's clear that fixing bugs the easy way is the preferred method. Try to use this method as much as possible. But it's okay to use the difficult way to solve the more difficult bugs.
Putting the bug report number into Subversion comments is a good way to keep track of what code changes have been made based on what bug report. Most bug tracking tools can make use of this and link bug reports to the appropriate revisitons and visa-versa. If your bug tracking tool doesn't have this ability, it's a good idea to comment the appropriate revision number or tags on the bug so that others know where to look for the fix.
Happy bug fixing!

View File

@ -0,0 +1,33 @@
+++
date = "2006-11-22"
title = "WordPress: Author comment highlighting"
tags = ["General", "Everything", "Wordpress", "Web Development", "Features"]
slug = "wordpress-author-comment-highlighting"
+++
I've seen it lots of times before, but I just added it to Ariejan.net (and the next release of the iAriejan theme). Sometimes there are lots of comments and it's nice for visitors to see what the official reaction of the blog author is.
Since I haven't really looked into a plugin or anything, this is just a very simple theme hack.
You can apply it to your current theme with almost no effort at all.
~
Open up your comments.php file in your themes directory. And look for the following code:
<li class="<?php echo $oddcomment; ?>" id="comment-< ?php comment_ID() ?>" id="comment-< ?php comment_ID() ?>">
and replace it with
<li class="<?php if ( $comment->comment_author_email == get_the_author_email() ) echo 'authorcomment'; else echo $oddcomment; ?>" id="comment-< ?php comment_ID() ?>" id="comment-< ?php comment_ID() ?>">
What this will do is match the e-mail address of the poster with the e-mail address of the post author. This is in some way spoofable, as users may be able to post a comment with your e-mail address on it.
If you posted the comment an extra CSS class named 'authorcomment' is added. So add the following to your style.css file. (You may change this to suit your own taste of course):
.authorcomment {
background-color: #363636;
border: 1px solid #969696;
}
To prevent this you can add your e-mail address (the one you use with your WP account) to Options -> Discussion -> Comment Moderation. This will keep any post that contains your email address back for moderation by you. This is the only fool-proof method I know right now to keep people from spoofing. There might be some other hacks for this, but I haven't had time to think about that yet.

View File

@ -0,0 +1,101 @@
+++
date = "2006-11-24"
title = "SVN: How to structure your repository"
tags = ["General", "Everything", "Features", "Subversion"]
slug = "svn-how-to-structure-your-repository"
+++
_You are reading an article about Subversion. That's great, because it
means you're thinking about the benefits of version control for your
project. However, I have long since moved from Subversion to Git. I
strongly recommend you read up on my <a
href="http://ariejan.net/2009/06/08/best-practice-the-git-development-cycle/">Best
Practice - The Git Developmenet Cycle</a>. Git is much faster an
flexible than Subversion, go check it out now!_
Most people know what Subversion is and that there's something called "The Trunk" with code in it. Well, there's more to your SubVersion repository than you think! This article will discuss how to structure your repository in order for you to take full advantage of Subversion's possibilities.
As you may have read in my previous <a href="http://ariejan.net/tags/subversion">Subversion articles</a> the base of your Subversion repository are three directories: branches, tags and trunk.
Each directory in subversion can be checked out seperately. See the examples for more information.
~
### Trunk
The trunk contains the most current development code at all times. This is where you work up to your next major release of code.
I see, almost too often, that people only use the trunk to store their code. Releases are pulled from a certain revision and then development continues. This is no good. Not for you, not for your product.
The trunk should only be used to develop code that will be your next major release. Don't brand the trunk with version numbers or release names. Just keep the trunk in "development mode" at all times.
Example:
https://svn.example.com/svnroot/project/trunk
### Branches
There are different types of branches. I'll tell you about the most common ones here.
With the branches directory you can create paths for you code to travel to more specific goals like an upcoming release. As I discussed in my <a href="http://ariejan.net/2006/11/21/svn-how-to-release-software-properly/">article on releasing software from Subversion</a> the branches directory contains copies of your trunk at various stages of development.
#### Release Branches
We have already seen the RB-x.x release branches. When the trunk reaches the stage that it's ready to be released (or when you want to freeze the addition of new features) you create a release branch. This release branch is just a copy of your current trunk code.
The branch can be checked out seperately and you can start branding and versioning the project. You can also use the release branch to fix bugs that pop up during (beta) testing (<a href="http://ariejan.net/2006/11/22/svn-how-to-fix-bugs-properly/">See my article on that too</a>). The idea of this is to keep development in the trunk going without being bothered by release specific stuff. So it's perfectly fine to add new features to your trunk while you (or others) prepare the release.
Of course, you can address a release branch directly to check it out:
https://svn.example.com/svnroot/project/branches/RB-1.0
#### Bug fix branches
Branches may also be used to address the more serious bugs found in the trunk or a release branch. The bugs are of such a magnitute that you can't fix them by yourself in a single commit. So, in order to focus on the problem of fixing this bug you should create a new branch for this purpose. This allows development in the trunk or your release branch to continue, and you won't disturb them with new bugs or tests that break the current code.
Bug fix branches are named after the ID they are assigned in your bugtracking tool. Mostly this is a number: BUG-3391
Of course, you can access your bugfix branch like any other.
https://svn.example.com/svnroot/project/branches/BUG-3391
Read my <a href="http://ariejan.net/2006/11/22/svn-how-to-fix-bugs-properly/">how to fix bugs properly</a> article for more specific bug fixing information. Also read on in this article to the tags section.
#### Experimental branches
Something that also happens a lot is the introduction of new technologies. This is fine, of course, but you don't want to bet your entire project on it.
Imagine that you want to change from PHP 4 to PHP 5 for your web application. How long would it take you to convert your entire project? Do you want your entire code base (trunk) to be useless until you have converted all of your code? Probably not!
These experiments, maybe PHP 5 is a bridge too far for your app, should be given their own branch. You can hack your way to PHP 5-ism there and if you fail, you still have your current PHP 4 code in the branch.
Experimental branches may be abandonned when the experiment fails. If they succeed you can easily merge that branch with the trunk and deliver your big new technology. These branches are named after what you're experimenting with. I always prefix them with 'TRY-':
https://svn.example.com/svnroot/project/branches/TRY-new-technology
### Tags
Tags are, like branches, copies of your code. Tags, however, are not to be used for active development. They mark (tag) a certain state your code is in.
#### Release tags
Release tags mark the release (and state) of your code at that release point. Release tags are always copies of the corresponding release branch. Release tags are prefixed with 'REL-' followed by a version number.
You can access these tags easily:
https://svn.example.com/svnroot/project/tags/REL-1.0.0
See <a href="http://ariejan.net/2006/11/21/svn-how-to-release-software-properly/">my article on releasing software</a> for more information.
#### Bug fix PRE and POST tags
When you have created a bug fix branch, you want to mark (tag) the situation of your code before and after the bugfix. This allows you to easily refer to the changes you made when you want to merge them back to your trunk or release branch.
The start-tag is called 'PRE' and the end-tag called 'POST'. Of course, you should add the bug ID number here too to show what bug you are tagging here.
You probably don't check out bug fix tags, but you want to reference them when merging bug fixes with your other code:
https://svn.example.com/svnroot/project/tags/PRE-3391
https://svn.example.com/svnroot/project/tags/POST-3391
Read more on <a href="http://ariejan.net/2006/11/22/svn-how-to-fix-bugs-properly/">fixing bugs wiht subversion</a> in my other article.

View File

@ -0,0 +1,32 @@
+++
date = "2006-11-25"
title = "The Three Corner Stones of Developerhood"
tags = ["General", "Everything", "Blog", "Web Development", "Lists"]
slug = "the-three-corner-stones-of-developerhood"
+++
As a developer, there are just some things you can't do without. I have found that there are three things that I need. Really need. If one of them is missing, I have trouble doing my job properly.
I call them <em>"The Three Corner stones of Developerhood"</em>:
~
<h3>1. Coffee</h3>
Most importantly coffee. I just can't do without it. I don't drink it to stay awake or anything, but it's just a warm beverage that keeps me focused and gives me the energy I need to keep working. I prefer coffee over all those horrible caffeine drinks.
<h3>2. A good text editor</h3>
No matter how good Integrated Developement Environments are, I always prefer my trusty <a href="http://macromates.com/">TextMate</a> to get things done for me.
Syntax highlighting and the huge amount of macro's is just a pleasure to work with. I support PHP, HTML, CSS and most importantly, Ruby on Rails.
If you have a Mac. Buy this now!
<h3>3. Google</h3>
I can't tell you how many problems I've solved by using <a href="http://www.google.com">Google</a> to find the answer.
Of course, you can just insert any search engine here, but Google is really my favourite. With <a href="http://groups.google.com">Google Groups</a> I can find stuff in news groups easily, and as a developer, news groups are a very valuable resource of information.
It's very well possible that you have three other corner stones. Feel free to comment them below and let me know.

View File

@ -0,0 +1,13 @@
+++
date = "2006-11-30"
title = "Rails: Security Check-up"
tags = ["General", "Everything", "RubyOnRails", "Blogroll"]
slug = "rails-security-check-up"
+++
Is your Rails app secure? Really? Maybe you need to perform a major check-up of your Rails application to make sure.
Here's a <a href="http://rubythis.blogspot.com/2006/11/rails-security-checklist.html">comprehensive list</a> that will take you through the most common mistakes and forgotten security risks in your Rails application.
It's a great post. Print it, hang it on your wall and create secure Rails apps from now on.

View File

@ -0,0 +1,196 @@
+++
date = "2006-12-01"
title = "How to setup a Ubuntu development server - Part 1"
tags = ["General", "Everything", "Web Development", "Features", "Ubuntu", "Subversion"]
slug = "how-to-setup-a-ubuntu-development-server-part-1"
+++
Since I'm starting some real work on my final school project, I want to install a Ubuntu development server here at home. I have a Pentium 4 box here that will perform that task.
In this first part I will show you how to install Subversion over WebDAV. All of this will be done in such a way that it's easy to serve multiple projects at once.
In future parts I will tell you more about installing Trac, FastCGI (with Apache) to host Rails applications and how to use Capistrano to deploy your app properly.
For now, let's get cracking at Subversion.
~
First off, I installed Ubuntu 6.10 on my server. Because I don't need a graphical user interface, I have installed Ubuntu in text-only mode.
<h3>Open up to the universe</h3>
The first thing I always do when I install a Ubuntu box is to enable the universe package repositories. This is rather easy.
Edit /etc/apt/sources.list and uncomment all the Universe related lines. Also, comment out your install disk. Here's what my /etc/apt/sources.list looks like:
# deb cdrom:[Ubuntu 6.10 _Edgy Eft_ - Release i386 (20061025)]/ edgy main restricted
deb http://nl.archive.ubuntu.com/ubuntu/ edgy main restricted
deb-src http://nl.archive.ubuntu.com/ubuntu/ edgy main restricted
## Major bug fix updates produced after the final release of the
## distribution.
deb http://nl.archive.ubuntu.com/ubuntu/ edgy-updates main restricted
deb-src http://nl.archive.ubuntu.com/ubuntu/ edgy-updates main restricted
## Uncomment the following two lines to add software from the 'universe'
## repository.
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## universe WILL NOT receive any review or updates from the Ubuntu security
## team.
deb http://nl.archive.ubuntu.com/ubuntu/ edgy universe
deb-src http://nl.archive.ubuntu.com/ubuntu/ edgy universe
## Uncomment the following two lines to add software from the 'backports'
## repository.
## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
# deb http://nl.archive.ubuntu.com/ubuntu/ edgy-backports main restricted universe multiverse
# deb-src http://nl.archive.ubuntu.com/ubuntu/ edgy-backports main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu edgy-security main restricted
deb-src http://security.ubuntu.com/ubuntu edgy-security main restricted
deb http://security.ubuntu.com/ubuntu edgy-security universe
deb-src http://security.ubuntu.com/ubuntu edgy-security universe
The next step is to make sure all software present is up-to-date. There are already a few updates available so run these two commands:
$ sudo apt-get update
$ sudo apt-get dist-upgrade
That's it.
<h3>Getting SSH up and running</h3>
Because I have a MacBook, I'd like to use it to do my work. To do so I need to install the OpenSSH server on my server so I can access it over the network.
$ sudo apt-get install ssh
This will install ssh and the OpenSSH server. It also generates everything you need automatically like RSA keys and all that.
Now, try to login wiht SSH from your desktop machine.
<h3>Apache</h3>
Since I want to use Subversion of WebDAV I will need to install Apache first. I'll grab a vanilla copy of Apache from Ubuntu here.
$ sudo apt-get install apache2
If that's finished you should see a placeholder when you access your server with a browser. Check this now.
<h3>Getting Subversion</h3>
Subversion is also easily installed.
$ sudo apt-get install subversion subversion-tools
Next we should setup a location for our Subversion repositories. I choose to put them in /var/lib/svn. Create this directory now:
$ sudo mkdir -p /var/lib/svn
I also create a repository now and create a basic Subversion structure there. In my case the project is called 'colt'.
$ sudo mkdir -p /var/lib/svn/colt
$ sudo svnadmin create /var/lib/svn/colt
$ sudo svn mkdir file:///var/lib/svn/colt/trunk -m "Trunk"
$ sudo svn mkdir file:///var/lib/svn/colt/tags -m "Tags"
$ sudo svn mkdir file:///var/lib/svn/colt/branches -m "Branches"
Note that you need to sudo the svn commands because only root has write access to your repository currently.
<h3>WebDAV for SVN</h3>
Okay. You are already at revision 3 on your repository. Good work! Now let's make sure that you repositories are accessable over the web. First, we install libapache2-svn. This packages includes WebDAV support for SVN.
$ sudo apt-get install libapache2-svn
Next I open up /etc/apache2/mods-available/dav_svn.conf. This file contains configuration for the WebDAV and SubVersion modules we just installed.
Here I enable basic HTTP authentication, which is good enough for my local network. I also enable DAV by uncommenting "DAV svn".
You need to take special care of the "SVNPath" variable here. We don't host just one repository. We host several and /var/lib/svn is the parent directory of all our repositories. E.g. 'colt' is a sub directory that resides in /var/lib/svn. To make Apache understand this we need to change "SVNPath" to "SVNParentPath". This enables all sub directories to be independent repositories.
Note: The authentication file we use here can be recycled later when we install Trac! Handy-Dandy, isn't it?
I made my configuration look like this:
# dav_svn.conf - Example Subversion/Apache configuration
#
# For details and further options see the Apache user manual and
# the Subversion book.
# <location URL> ... </location>
# URL controls how the repository appears to the outside world.
# In this example clients access the repository as http://hostname/svn/
<location /svn>
# Uncomment this to enable the repository,
DAV svn
# Set this to the path to your repository
SVNParentPath /var/lib/svn
# The following allows for basic http authentication. Basic authentication
# should not be considered secure for any particularly rigorous definition of
# secure.
# to create a passwd file
# # rm -f /etc/apache2/dav_svn.passwd
# # htpasswd2 -c /etc/apache2/dav_svn.passwd dwhedon
# New password:
# Re-type new password:
# Adding password for user dwhedon
# #
# Uncomment the following 3 lines to enable Basic Authentication
AuthType Basic
AuthName "Subversion Repository Access"
AuthUserFile /etc/apache2/dav_svn.passwd
# Uncomment the following line to enable Authz Authentication
# AuthzSVNAccessFile /etc/apache2/dav_svn.authz
# The following three lines allow anonymous read, but make
# committers authenticate themselves.
<limitexcept GET PROPFIND OPTIONS REPORT>
Require valid-user
</limitexcept>
</location>
Now kick Apache to reload and you should be able to access your repository over the web! Try http://example.com/svn/colt.
<h3>Authentication</h3>
Reading of the repository is okay without authentication. But writing needs to be protected. We need to create a password file for this. This is easy and is already explained in /etc/apache2/mods-available/dav_svn.conf:
$ sudo htpasswd2 -c /etc/apache2/dav_svn.passwd ariejan
Go ahead, add as many users as you need.
<h3>Apache, Subversion and the world</h3>
Before you start using Subversion, make sure you make the repositories owned by Apache. Apache is the one who wil access the repositories physically. This is really easy:
$ sudo chown -R www-data.www-data /var/lib/svn
When you access your repository for write actions now, you will recieve the following message:
Authentication realm: <http ://example.com:80> Subversion Repository Access
Password for 'ariejan':
Alright sparky! Subversion access is ready for you now! Next time I'll tell you how to integrate Trac with your hot new Subversion repositories.
<h3>Notes</h3>
All users in you passwd file can write to all repositories. I've not yet found a way to prevent this, since I don't need that functionality right now. If you know more about this, please let me know.
Subversion repositories are always readable by anonymous people. You should remove the LimitExcept block from dav_svn.conf to make sure all users authenticated themselves before accessing your repository.
If you add more repositories, you always have to chown them to your apache's user and group. After that you can use them through WebDAV.

View File

@ -0,0 +1,97 @@
+++
date = "2006-12-02"
title = "How to setup a Ubuntu development server - Part 2"
tags = ["General", "Everything", "Web Development", "Features", "Ubuntu"]
slug = "how-to-setup-a-ubuntu-development-server-part-2"
+++
Also read <a href="http://ariejan.net/2006/12/01/how-to-setup-a-ubuntu-development-server-part-1/">Part 1 - Subversion</a>.
In this part I will tell you how to install <a href="http://trac.edgewall.org/">Trac</a> on top of your Subversion repositories on your Ubuntu development server. Trac offers you a wiki, roadmap, tickets (tracking system) and access to your SubVersion repository. All of this is bundeled in a very sexy web interface.
Well, let's get to work now and get Trac installed. When you're done you will have trac available for all your Subversion repositories.
~
<h3>Install Trac</h3>
First thing to do is install trac. Here I will also install mod_python for your apache webserver and python-setuptools that we'll need later with the webadmin plugin.
$ sudo apt-get install trac libapache2-mod-python python-setuptools
Now, I create a directory where all Trac information will be stored.
$ sudo mkdir -p /var/lib/trac
Common sense dictates that you use the same name here for the trac environment as for the subversion repository.
Change to the trac directory and intitialize the project:
$ cd /var/lib/trac
$ sudo trac-admin colt initenv
You'll need to name the project, choose a database file (default is okay), specify where the subversion repository resides ( /var/lib/svn/colt, in this case) and a template (the default is okay here too).
I recommend you also create an administrator user right now. Make sure you add a user who's already in your /etc/apache2/dav_svn.passwd file.
$ sudo trac-admin colt permission add ariejan TRAC_ADMIN
Well, that's it. Trac has been installed. Now let's make sure we can access trac through the web.
<h3>Configuring Apache</h3>
Configuring apache is rather easy when you know what to do. Add the following code to /etc/apache2/sites-available/default (at the bottom before the end of the virtualhost tag) or put it in a seperate virtual host file if you want to dedicate a special domain to this.
<location /projects>
SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir /var/lib/trac
PythonOption TracUriRoot /projects
</location>
<locationmatch "/projects/[^/]+/login">
AuthType Basic
AuthName "Trac Authentication"
AuthUserFile /etc/apache2/dav_svn.passwd
Require valid-user
</locationmatch>
Notice here, again that we use TracEnvParentDir to show we host multiple instances of Trac. You may change the TracUriRoot to something different.
Again, make sure to chown your Trac installation to www-data:
$ sudo chown -R www-data.www-data /var/lib/trac
Now, access your trac over the web: http://example.com/projects for a complete listing of hosted projects or http://example.com/projects/colt for the COLT project.
You may also login now! As you can see, we use the dav_svn.passwd file here so everyone with subversion access also has access to trac.
<h3>Webadmin</h3>
Normally you would administrate a Trac installation through the command-line interface we used to initialize the environment and add the administrator user. Nowadays there is a webadmin plugin for Trac, which will be included in Trac from version 0.11. Since Ubuntu ships with Trac 0.9.3 we need to add this webadmin ourselves.
First, download the following file to your server: <a href="http://trac.edgewall.org/attachment/wiki/WebAdmin/TracWebAdmin-0.1.2dev_r4240-py2.4.egg.zip?format=raw">http://trac.edgewall.org/attachment/wiki/WebAdmin/TracWebAdmin-0.1.2dev_r4240-py2.4.egg.zip</a>.
Don't unzip this file, just remove the .zip extension.
Because we installed setuptools earlier, we can now use easy_install to install this plugin system-wide, enabling it for all our trac installations.
$ sudo easy_install TracWebAdmin-0.1.2dev_r4240-py2.4.egg
Next we enable webadmin in the global configuration file of track. You may need to create the 'conf' directory in this case:
$ cd /usr/share/trac
$ sudo mkdir conf
$ sudo vi conf/trac.ini[/conf]
Next enter the following in trac.ini
[components]
webadmin.* = enabled
Save the file and off you go. Login as the administrator user you specified earlier and you can make use of the 'admin' button that has appeared in the menu of Trac.
Enjoy your trac! Next time (in Part 3) I will talk about setting up a commit-hook so Trac tickets are updated by posting subversion commit messages (throught commit-hooks).
Also read <a href="http://ariejan.net/2006/12/01/how-to-setup-a-ubuntu-development-server-part-1/">Part 1 - Subversion</a> on how to install Subversion over WebDAV.

View File

@ -0,0 +1,79 @@
+++
date = "2006-12-03"
title = "Installing Rails on Ubuntu Dapper / Edgy"
tags = ["General", "Everything", "RubyOnRails", "Features"]
slug = "installing-rails-on-ubuntu-dapper-edgy"
+++
<em>Update 2010-03-25: Bumped to RubyGems version 1.3.6.</em>
<em>Update 2009-02-19: Bumped to RubyGems version 1.3.1 and MySQL 5 libraries. This guide now works for all recent version of Ubuntu and Debian. Enjoy!</em>
Installing Ruby on Rails on your Ubuntu box is not always as easy as it seems. Here's a comprehensive overview of the steps you need to take. Mostly you'll be using apt-get and gems, so it's not all that hard after all.
This method was tested on both Dapper and Edgy systems. It may work on other Ubuntu releases as well. It's also possible that it works on Debian.
Besides Rails, I'll also be install mysql and sqlite3 support.
<!--more-->
<h3>1. Install Ruby</h3>
Before putting anything on Rails, install Ruby.
$ sudo apt-get install irb1.8 libreadline-ruby1.8 libruby libruby1.8 rdoc1.8 ruby ruby1.8 ruby1.8-dev
You may now check what version of Ruby you have by running `ruby -v`. It's just for your information.
<h3>2. Install Ruby Gems</h3>
Surf to <a href="http://rubyforge.org/frs/?group_id=126">http://rubyforge.org/frs/?group_id=126</a> and download the latest available gems pacakge in tgz format. (You may also use the zip if you feel comfortable.)
$ wget http://rubyforge.org/frs/download.php/69365/rubygems-1.3.6.tgz
$ tar zxf rubygems-1.3.6.tgz
$ cd rubygems-1.3.6
$ sudo ruby setup.rb
$ sudo ln -sf /usr/bin/gem1.8 /usr/bin/gem
<h3>3. Install Rails!</h3>
You may now install Rails now!
$ sudo gem install rails
That's it! Well, almost. You probably want some other things as well.
<h3>4. Install development tools</h3>
Before you continue, stop a moment to install some development tools. These tools are probably needed to compile and install the gems we are going to install next.
$ sudo apt-get install build-essential
<h3>MySQL Support</h3>
You probably want MySQL Ruby support. The MySQL code in Rails sucks (no offence), but the Ruby code is much better. You should install it. Rails will notice that it's available and use it.
First, install MySQL.
$ sudo apt-get install mysql-server mysql-client
Next, install development files for MySQL. We'll need these in order to make Ruby understand.
$ sudo apt-get install libmysqlclient15-dev
Then, you may install the gem
$ sudo gem install mysql
You have to choose what version you want to install. Enter the number corresponding with the latest version that is tagged 'ruby'. Installing win32 stuff on linux is generally not a good thing.
<h3>SQLite 3</h3>
For SQLite 3 you need to install some packages before installing the gem.
$ sudo apt-get install sqlite3 libsqlite3-dev
$ sudo gem install sqlite3-ruby
<h3>If things go wrong</h3>
If things go wrong, make sure you installed all recommended packages mentioned above. Also , check any log files that the error message refers to.

View File

@ -0,0 +1,29 @@
+++
date = "2006-12-06"
title = "Install ruby-mysql on Mac OS X 10.4 Tiger"
tags = ["General", "Everything", "RubyOnRails", "Features", "Mac OS X"]
slug = "install-ruby-mysql-on-mac-os-x-104-tiger"
+++
You probably know that the built-in mysql code in Rails sucks. To rephrase that, the ruby-mysql gem contains better code, so you want that. Rails automatically detects if you have ruby-mysql installed or not, and uses it if you have it.
Most notably, you want to install this gem if you get dropped MySQL connections running your Rails application.
So we do:
<pre lang="bash">$ sudo gem install mysql
...
ERROR: Failed to build gem native extension.</pre>
Normall this would install fine, but not on Mac OS X. This is because Mac OS X keeps its code, headers and libraries in odd places (compared to Linux). But don't panic. There's an easy solution to all this!
<!--more-->
Just compile the gem yourself, and add some special ingredients. Well, not even that. Just compile it again like this:
<pre lang="bash">$ cd /usr/local/lib/ruby/gems/1.8/gems/mysql-2.7
$ sudo ruby extconf.rb --with-mysql-lib=/usr/local/mysql/lib --with-mysql-include=/usr/local/mysql/include
$ sudo make
$ sudo make install</pre>
Now, you have the ruby-mysql gem installed and ready to go! No more dropped MySQL connections for Rails!

View File

@ -0,0 +1,18 @@
+++
date = "2006-12-11"
title = "Announcing “Subversion Kick-Start”"
tags = ["General", "Everything", "Blog", "Subversion", "kickstart"]
slug = "announcing-subversion-kick-start"
+++
With this post I officially announce my first book, "<strong>Subversion Kick-Start</strong>".
Subversion is a popular version control system that's used by many, many developers around the globe. Most developers know how to find their way around Subversion, but quite a lot do not.
SKS is for every software engineer who wants to learn how to put Subverstion to real use for their projects. It's more than just storing code. It's about structuring the way you write code. It's about optimizing the way you work.
Subversion Kick-Start is aimed at getting you and Subversion up and running as quickly as possible with the minimal amount of effort required.
Please subscribe to my <a href="http://ariejan.net/subscribe/">feed newsletter</a> or <a href="http://feeds.feedburner.com/Ariejan">RSS feed</a> and stay up-to-date! You'll be the first to know when the book is available.
<!--more-->

View File

@ -0,0 +1,54 @@
+++
date = "2006-12-13"
title = "Show the current SVN revision in your Rails app"
tags = ["General", "Everything", "RubyOnRails", "Features", "Subversion", "Capistrano"]
slug = "show-the-current-svn-revision-in-your-rails-app"
+++
I'm current developing a Rails application. I deploy this application to a demonstration server using <a href="http://manuals.rubyonrails.com/read/book/17">capistrano</a>.
To streamline feedback and bug reporting I want to show the current revision number of the code that's published on the demo server to show in the footer of every page.
First I looked into Subversion keyword expansion, but this is marked as 'evil' and it doesn't meet my requirements. I want to show the latest revision number of the entire repository and not just that of the current file.
Luckily for me, I use capistrano. Here's how I fixed the problem.
<!--more-->
First of all, I created a partial that contains the revision number and render this in my layout.
app/views/layouts/_revision.rhtml:
<pre lang="bash">
CURRENT
</pre>
This shows CURRENT always when I work with my working copy.
app/views/layouts/mylayout.rhtml
<pre lang="ruby">
< %= render :partial => 'layout/revision' %>
</pre>
Now, I assume you have already setup capistrano for your project and that you have a config/deploy.rb file.
I've added the following helper to my config/deploy.rb file:
<pre lang="ruby">desc "Write current revision to app/layouts/_revision.rhtml"
task :publish_revision do
run "svn info #{release_path} | grep ^Revision > #{release_path}/app/views/layouts/_revision.rhtml"
end</pre>
Next, I added the following hook 'after_update_code'. This will automatically be run after update_code which is called in 'deploy'.
<pre lang="ruby">desc "Run this after update_code"
task :after_update_code do
publish_revision
end</pre>
That's it. When I deploy the application, the current code is checked out and and the layouts/_revision.rhtml file is overwritten with the current revision information.
<h3>Bonus</h3>
You could also leave the layouts/_revision.rhtml files empty and update it for your demonstration server, but not for your production box. This way there won't be a revision added.
Of course, you could also create a deploy_demonstration method in deploy.rb and call publish_revision manually from there.

View File

@ -0,0 +1,35 @@
+++
date = "2006-12-20"
title = "SVN: How often should you commit?"
tags = ["General", "Everything", "Features", "Subversion"]
slug = "svn-how-often-should-you-commit"
+++
I often hear discussion about how often developers should commit their work to the central repository. Some say that you should only commit when you're next 'release' is ready. Others say that you should commit every change you make in your code. There are even people who say you should commit your changes only at the end of the day.
All wrong! There is no such thing as 'the way', but there is a thing called best practice and that's what I want to talk to you about. How often and what should you commit to your Subversion repository.
<!--more-->
Actually, it's quite simple. If you use a tool like Trac or any other ticketing tracking system you have already got a great starting point (given, of course, that you add 'things you need to do' to your tracker).
I split my development activities into small atomic actions. Normally these actions take up a few minutes to an hour of your time. Besides the fact that these atomic actions are managable, they also give you a sense of satisfaction because you can complete quite a few of these smaller actions every day.
All right. You have these atomic actions. I grab my code, perform the atomic actions and when it succeeds, I comment my changes back to Subversion. This always closes a ticket in my Trac system and most of the time refences the 'big picture' ticket.
Here's what I mean.
<strong>Big picture ticket</strong>: <em>"Create an accounting system for users"</em>
<strong>Atomic Action ticket</strong>: <em>"Create and customize the user model and unit tests"</em>
<strong>Atomic Action ticket</strong>: <em>"Install acts_as_authenticated plugin"</em>
So, I start with my code and first I install the acts_as_authenticated plugin. Great. Commit that. This takes a few minutes at the most.
Next, I create and customize the user model and unit tests. When that's done, I commit my changes again. As you can see, I've already closed two tickets (and got that warm satisfactory feeling).
Okay, you get the picture. Why would you work like this? Subversion allows you to keep track of changes in your code, but it doesn't force you on how ofter or when you track changes.
The most logical way of keeping track of changes is atomic actions. If you decide later that you don't want the installed version of the acts_as_authenticated plugin, but a later release. You can see what files were added when you installed the plugin.
By using atomic actions you create atomic changesets in Subversion. This way you can easily jump between different states (revisions) of you code without breaking things. It keeps your code working and it allows you to easily track changes you made and to what purpose.

View File

@ -0,0 +1,30 @@
+++
date = "2006-12-20"
title = "SVN: Merge a branch with your trunk"
tags = ["General", "Everything", "Features", "Subversion"]
slug = "svn-merge-a-branch-with-your-trunk"
+++
When created a TRY-branch a few days back to try some fancy new AJAX technology in my application. Not problems there, so now I want to merge the code in the branch with my trunk.
Since I'm a lone hacker, the trunk has not been touched since I created the branch. I have a checked-out working copy of the branch available.
Here's a handy-dandy guide on how to merge your branch code with your trunk.
<!--more-->
Firstly, make sure you have a working copy of your trunk. I choose to switch my working copy back: (oh, make sure you have all your changes checked in in your branch before you switch!)
<pre lang="bash">$ svn switch http://example.com/svn/myproject/trunk</pre>
This removes, adds and updates all files you have worked on in your branch and creates a working copy of the code in the trunk.
Now, with my trunk in place, I can call 'merge' and apply the changes.
<pre lang="bash">$ svn merge http://example.com/svn/myproject/trunk http://example.com/svn/myproject/branches/TRY-AJAX</pre>
Since the files from the trunk and the beginning of the TRY-branch are still exact copies, I won't get in any trouble. If you do (and you did change your code in your trunk), make sure to resolve merging problems before checking in. When ready, check in your new code!
<pre lang="bash">$ svn ci -m "Merge TRY-AJAX branch with trunk"</pre>
That's it. You have now merged the branch with your trunk. Enjoy!

View File

@ -0,0 +1,90 @@
+++
date = "2006-12-22"
title = "Textmate+Rails: Easy partials for better code"
tags = ["General", "Everything", "RubyOnRails", "Features", "Textmate"]
slug = "textmaterails-easy-partials-for-better-code"
+++
As you may know, I use <a href="http://macromates.com/">TextMate</a> for editing Rails code.
I've just been browsing the Rails bundle today and I came across some very interesting things. Today I'll tell you about partials.
Partials are ERb templates. They are mostly HTML (or RJS or XML or whatever output format you use) and include some embedded Ruby to show actual content. Partials are not linked to a method in a controller, but instead they can be easily rendered through-out your application.
TextMate allows you to refactor your application to use partials with almost no effort!
<!--more-->
First something about partials for those who don't know about it.
Partials are stored in files that start with an _ (underscore) and end in .rthml (or .rjs or .rxml) and you may include them in your ERb like this:
<pre lang="ruby">< %= render :partial => 'userinfo' %></pre>
This will include the partial _userinfo.rhtml for you. This way you can avoid duplication by including the same ERb template (partial) over and over again.
Partials are also useful to keep your views (templates) clean and easy to understand. In large projects this will allow you later to easily change a view without having to spit through 500 lines of ERb.
Let's say you have a profile page where you want to show a users's profile and some options for when the user is viewing his own profile. Also, you want to show a simple message when the users has not yet created a profile, which is a possibility in my application. The show.rhtml template for the profile may look like this
<pre lang="ruby"><h2>Profile for < %=h @profile.user.login %></h2>
< % if @profile.exists? -%>
<div id="membersince">< %= @profile.firstname %> has been a member for < %= distance_of_time_in_words_to_now @profile.user.created_at %></div>
<h3>General information</h3>
<div id="name">Name: < %= @profile.fullname %></div>
<div id="country">Country: < %= @profile.country %></div>
<div id="birthday">Birthday: < %= fmt_date @profile.birthday %></div>
<h3>About < %= @profile.firstname %></h3>
<div id="about">< %= markdown @profile.about %></div>
< % else -%>
<div id="membersince">< %= @profile.user.login %> has been a member for < %= distance_of_time_in_words_to_now @profile.user.created_at %></div>
<h3>Oh my!</h3>
<p>This user has not yet created a profile.</p>
< % end -%>
< % if @profile.user.id == current_user.id -%>
<h3>Options</h3>
<p>This is your profile, so you have some options:</p>
<ul>
<li>< %= link_to "Change password", :controller => 'account', :action => "change_password" %></li>
<li>< %= link_to "Edit your profile", profile_edit_url(:login => current_user.login) %>
</li></ul>
< % end -%></pre>
As you may see, this is chaos. It's not easy to read and you can't easily change something when you need to. Wouldn't it be great to store all three seperate blocks (profile, no profile message and options) in partials?
This is where TextMate does it's magic. Here's a before snaphot:
<img id="image68" src="http://ariejan.net/wp-content/uploads/2006/12/before.png" alt="before.png" />
Now, select the part between the if and else statements. This is where a normal profile is shown. Next, use TextMate: <strong>SHIFT-CTRL-H</strong>. You'll get a pop-up asking you how you'd like to name the partial. In this case I choose 'profile'.
<img id="image69" src="http://ariejan.net/wp-content/uploads/2006/12/during.png" alt="during.png" />
After you click OK, the partial will be created containing the code you selected and an appropriate render method is placed instead. This is what the code looks like after:
<img id="image70" src="http://ariejan.net/wp-content/uploads/2006/12/after.png" alt="after.png" />
After all this the same ERb template looks like this:
<pre lang="ruby"><h2>Profile for < %=h @profile.user.login %></h2>
< % if @profile.exists? -%>
< %= render :partial => 'profile' %>
< % else -%>
< %= render :partial => 'noprofile' %>
< % end -%>
< % if @profile.user.id == current_user.id -%>
< %= render :partial => 'options' %>
< % end -%></pre>
Now, isn't that more readable? Even, if you want to change a profile, you can just edit _profile.rhtml and you're done.

View File

@ -0,0 +1,59 @@
+++
date = "2007-01-12"
title = "Rails: Group results by week (using group_by)"
tags = ["General", "Everything", "RubyOnRails", "Features"]
slug = "rails-group-results-by-week-using-group_by"
+++
The Enumerable class in Rails contains a method named 'group_by'. This method is pure magic for a developer's point of view. I'll give you a simple example that shows the power of group_by.
Let's say you have a table 'posts' containing blog posts. Now, you normally show these chronologically a few at a time. Nothing special there. For some special overview page, you want to group your posts by week.
With normal ActiveRecord operations this would be quite an elaborate task. But with group_by from Enumerable, it becomes child's play.
First of all, in the controller, just get all the posts you need. In this case, all of them:
Controller:
def list
@posts = Post.find :all
end
As you can see, I perform no ordering or whatsoever here.
Now, in your view you normally would iterate over all posts like this:
<%= render :partial => 'post', :collection => @posts %>
But, as I said, we want to group the posts by week. To make life easy, I add a method to the Post class that returns the week number in which a post was written:
Model Post:
def week
self.created_at.strftime('%W')
end
Now, the magic will happen in our view:
<% @posts.group_by(&:week).each do |week, posts| %>
<div id="week">
<h2>Week < %= week %></h2>
< %= render :partial => 'post', :collection => @posts %>
</div>
<% end %>
Let me explain the above. We specify that we want to call group_by for @posts. But we need to say how we want to group these posts. By specifying &:week we tell group_by that we want to group by the result of the week attribute of every post. This is the attribute we specified earlier in the model.
Well, when the grouping is done we create a block that will handle every group of items. We extract 'week' and 'posts' here. 'week' contains the week number and 'posts' all the posts for that week.
As normal, we can now show the week number and iterate over the posts.
## Sorting groups
The result of group_by is not guaranteed to be ordered in any way. Simply call 'sort' before each and you're set:
@posts.group_by(&:week).sort.each do |week, posts|
Mostly, you'll find that the posts for every group are not sorted either. With the example above I think it's easy to figure out how to do that now. (hint: .sort)

View File

@ -0,0 +1,40 @@
+++
date = "2007-01-19"
title = "“Print this page” with Ruby on Rails"
tags = ["General", "Everything", "RubyOnRails", "Features"]
slug = "print-this-page-with-ruby-on-rails"
+++
You have put a lot of effort into creating a sexy overview of whatever data your application stores and allow your users to manipulate that data through AJAX controls. But, some people just want to print their data.
How to go about that? Just printing the page with data is generally not a good idea because it has been optimized for display on a screen. The first step we need to take is adapting our page for printing. Stylesheets are very handy tools for this. Check the following part of the header of my layout:
<!--more-->
<pre lang="ruby">stylesheet_link_tag('default', :media => :screen)
stylesheet_link_tag('print', :media => :print)</pre>
This will generate HTML code that includes two stylesheets. However, only the 'default' stylesheet is used on screen. When the users prints a particular page, the print stylesheet is used instead. So, what do you want to change in the print stylesheet?
<ul>
<li>Fonts should be serif (not sans-serif) for printing</li>
<li>Hide images as much as possible</li>
<li>Hide ads</li>
<li>Display printable ads that are hidden on screen</li>
<li>Hide navigational elements</li>
<li>Use a black-on-white colour scheme</li>
<li>Underline links and colour them blue for easy recognition</li>
<li>Add the actual URL to your links (see below)</li>
</ul>
To add the actual URL in the href-part of your link to the name of your link add the following to you print stylesheet:
<pre lang='css'>a:after { content:' [' attr(href) '] '}</pre>
Now, with all this in place, load your page with data. Print your page or watch a preview and be amazed at what stylesheets can do for you!
The final touch is adding a "Print this page" link to your navigation on screen. Here you can use link_to_function:
<pre lang="ruby">link_to_function("Print this Page", "javascript:print()")</pre>
That's it. Just hit the Print this Page button and your browsers print dialog will pop up and use your fancy new print stylesheet.

View File

@ -0,0 +1,11 @@
+++
date = "2007-01-19"
title = "Why Ruby Rocks - Convince your fellow developers"
tags = ["General", "Everything", "Blog", "Ruby"]
slug = "why-ruby-rocks-convince-your-fellow-developers"
+++
I often hear questions from my Java and PHP oriented friends about what makes Ruby so great and easy to use. Until today I've shown them some of my Rails feats (AJAX Scaffold always amazes people). Now, I came across this <a href="http://www.ruby-lang.org/en/documentation/quickstart/">20 minute Ruby introduction</a>. Starting with the basic "Hello World" item, this article show step by step improvements to end up with blocks, objects and all that makes Ruby really worth while.
So, if you need to show developers what Ruby (and not so much Rails) can do, show 'em this! It impresses the shit out of 'em.

View File

@ -0,0 +1,30 @@
+++
date = "2007-01-23"
title = "New in Rails: Resource Scaffold Generator"
tags = ["General", "RubyOnRails", "Features"]
slug = "new-in-rails-resource-scaffold-generator"
+++
Oh boy! Rails 1.2 is all about resources. A product entry in your application is not just a rendered HTML page, but it "is" data. Rails 1.2 allows you to add a .xml extension to your url to retrieve the same product information in XML format!
Now, this all sounds hard. Two ways of rendering the same action depending on an extension. Generating XML code for every model in your database. No way you want to spend time developing all that stuff.
Well, Rails wouldn't be Rails if there weren't a generator for it!
<!--more-->
This example is really easy. I want to create products in my database and expose them as HTML and XML to my users. Just do the following:
<pre lang="bash">$ ./script/generate scaffold_resource Product title:string description:text</pre>
A migration is generated automatically so update that if you want to before running
<pre lang="bash">$ rake db:migrate</pre>
As you can see in config/routes.rb, Rails has automatically generated routes for this resource!
<pre lang="ruby">map.resource :products</pre>
Now you can start up your Rails app and access http://localhost:8000/products. Add some products if you like. Now if you got to http://localhost:8000/products/1 you a nice HTML scaffold. If you add .xml: http://localhost:8000/products/1.xml you'll get nice XML!
Well, writing a seperate desktop application that retrieves informatin from your web application just got 100x easier!

View File

@ -0,0 +1,99 @@
+++
date = "2007-01-23"
title = "Rails: Nested resource scaffold"
tags = ["General", "Everything", "Features"]
slug = "rails-nested-resource-scaffold"
+++
In my <a href="http://ariejan.net/2007/01/23/new-in-rails-resource-scaffold-generator/">previous post</a> I told you about the resource scaffold. What you'll be doing a lot is nesting these resources. Ingredients in recipes, comments on posts, options for products. You name it, you nest it!
Since Rails does not automatically nest resources for you, you should do this yourself. This is, with some minor tweaks, really easy to accomplish. In this example I'll create recipes that have multiple ingredients.
I assume you have Rails 1.2.1 installed for this tutorial to work properly.
<!--more-->
First, I create an new rails project named 'cookbook'. I use an SQLite3 database because it's easy to do so. You may use any Rails compatible database for this example.
<pre lang="bash">$ mkdir cookbook
rails --database sqlite3 cookbook
cd cookbook</pre>
First I create resource scaffolds for both the Recipe and Ingredient models:
<pre lang="bash">$ ./script/generate scaffold_resource Recipe title:string instructions:text
./script/generate scaffold_resource Ingredient name:string quantity:string</pre>
As you can see I did not add a recipe_id to the ingredient model because of the has_many relationship. Add this column to the migration file. You should now be able to migrate your database:
<pre lang="bash">$ rake db:migrate</pre>
If you add the recipe_id to the generate script the view for your ingredients will include a field for the recipe_id and that's not what you want.
Next, make the has_many relationship in your models.
app/models/recipe.rb:
<pre lang="ruby">class Recipe < ActiveRecord::Base
has_many :ingredients
end</pre>
app/models/ingredient.rb
</pre><pre lang="ruby">class Ingredient < ActiveRecord::Base
belongs_to :recipe
end</pre>
So far, nothing new. Next we check out config/routes.rb:
<pre lang="ruby">map.resources :ingredients
map.resources :recipes</pre>
What we want is to map ingredients as a resource to recipes. Replace these two lines with:
<pre lang="ruby">map.resources :recipes do |recipes|
recipes.resources :ingredients
end</pre>
This will give you urls like /recipes/123/ingredients/321
Now we need to make some changes to the ingredients controller. Every ingredient belongs to a recipe. First add the filter:
<pre lang="ruby">before_filter(:get_recipe)
private
def get_recipe
@recipe = Recipe.find(params[:recipe_id])
end</pre>
This will make sure that every ingredient knows what recipe it belongs to.
In the index method of the ingredient controller, make sure you have this:
<pre lang="ruby">@ingredients = @recipe.ingredients.find(:all)</pre>
This makes sure you only show ingredients for this recipe, and not all ingredients in the database.
Because we changed the route for ingredients, we need to update all ingredient_url() and ingredient_path() calls in our controller and views. Change all occurrences of
<pre lang="ruby">ingredient_url(@ingredient)</pre>
and
<pre lang="ruby">ingredient_path(@ingredient)</pre>
to
<pre lang="ruby">ingredient_url(@recipe, @ingredient)</pre>
and
<pre lang="ruby">ingredient_path(@recipe, @ingredient)</pre>
<em>Note: Make sure that you don't replace 'ingredient' with '@ingredient' in your views!
Add a link to the ingredients to your recipe's index.rhtml view.
<pre lang="ruby">link_to 'Ingredients', ingredients_path(recipe)</pre>
And, at last, make sure the create method of your ingredients controller attaches the ingredient to the right recipe. Make sure the first two lines look like this:
<pre lang="ruby">def create
@ingredient = @recipe.ingredients.new(params[:ingredient])</pre>
You may now start your webserver and check out http://localhost:8000/recipes . Create some recipes and click 'ingredients'. You can now add ingredients for this recipe!
The next step will be customizing each method to suit your own needs.</em></pre>

View File

@ -0,0 +1,14 @@
+++
date = "2007-01-23"
title = "Updates: Wordpress 2.1, Themes and Social"
tags = ["General", "Everything", "Wordpress", "Ariejan.net", "Blog"]
slug = "updates-wordpress-21-themes-and-social"
+++
You can't really see it, but Ariejan.net has been upgraded to <a href="http://wordpress.org">Wordpress 2.1</a>. I've been running 2.1 beta's on a private server for some time now, so there weren't any surprises during the upgrade.
I've also updated the theme to something more stylish and sober. Google Ads are less annoying now and merge nicely with the content. I've also re-enabled the social bookmark links so you can quickly bookmark articles on Del.icio.us or Digg.
Hope you like the new style. Some minor tweaks will be applied the following days where needed. Please let me know your thoughts on ariejan.net!
<!--more-->

View File

@ -0,0 +1,23 @@
+++
date = "2007-01-28"
title = "Ruby: Sort an array of objects by an attribute"
tags = ["General", "Features", "Ruby"]
slug = "ruby-sort-an-array-of-objects-by-an-attribute"
+++
In this example I'll show you how easy it is to sort an array of (the same kind of) objects by an attribute. Let's say you have an array of User objects that have the attributes 'name' and 'login_count'. First, find all users.
@users = User.find(:all)
Now, we have to sort this array by 'name'. Since we don't know if any user used capitals in his name or not, we use 'downcase' to sort without case sensitivity.
A small not. 'sort' returns a new array and leaves the original unchanged. You may want to just reorder the @users array, so use the 'sort!' method. The '!' indicates it's a destructive method. It will overwrite the current @users array with the new sorting.
@users.sort! { |a,b| a.name.downcase <=> b.name.downcase }
That's all! Since strings are comparable, this will sort you user objects alphabetically by name. Want to sort on login_count instead?
@users.sort! { |a,b| a.login_count <=> b.login_count }
So, now you can easily sort any object in an array just like you want it too!

View File

@ -0,0 +1,18 @@
+++
date = "2007-01-29"
title = "Hobo - And you thought Rails made life easy!"
tags = ["General", "Blog", "RubyOnRails"]
slug = "hobo-and-you-thought-rails-made-life-easy"
+++
If you've seen anything of <a href="http://www.rubyonrails.org">Ruby on Rails</a>, you know it makes your life really easy with all its generators and plugins. Well, check out <a href="http://hobocentral.net/blog/">Hobo</a>!
Hobo is a Rails plugin that adds tons of extra features that make your live even easier. Here's a quote from their site:
<blockquote>
Hobo is an Open-Source project that makes development with Rails even faster than it already is. It features:
<ul>
<li>A template engine that extends Rails' standard ERB templates with user-defined tags</li>
<li>A powerful library of pre-defined tags for knocking up ajaxified data-driven sites in a snap
(lots still to do

View File

@ -0,0 +1,26 @@
+++
date = "2007-02-09"
title = "My photos on Flickr"
tags = ["General", "Everything", "Blog"]
slug = "my-photos-on-flickr"
+++
<style type="text/css">
.flickr-photo { border: solid 2px #000000; }
.flickr-yourcomment { }
.flickr-frame { text-align: left; padding: 3px; }
.flickr-caption { font-size: 0.8em; margin-top: 0px; }
</style>
<div class="flickr-frame">
<a href="http://www.flickr.com/photos/ariejan/384590943/" title="photo sharing"><img src="http://farm1.static.flickr.com/182/384590943_e794781bf0.jpg" class="flickr-photo" alt="" /></a>
<br />
<span class="flickr-caption"><a href="http://www.flickr.com/photos/ariejan/384590943/">Near Camden Lock Market, London, UK</a>, originally uploaded by <a href="http://www.flickr.com/people/ariejan/">ariejan</a>.</span>
</div>
<p class="flickr-yourcomment">
In an idle moment I decided to up all my photo's to Flickr. Normally I burn my photo's to disk or zip them up on an external harddisk. But then, I never look at them again and there a few nice pictures there. <br />
<br />
Feel free to check out <a href="http://www.flickr.com/photos/ariejan/">my photo's</a> now. Oh, keep track of more new stuff there. I'm planning on making some very nice pictures this weekend.
</p>

View File

@ -0,0 +1,26 @@
+++
date = "2007-02-17"
title = "Goals in the Park"
tags = ["General", "Everything", "Blog"]
slug = "goals-in-the-park"
+++
<style type="text/css">
.flickr-photo { border: solid 2px #000000; }
.flickr-yourcomment { }
.flickr-frame { text-align: left; padding: 3px; }
.flickr-caption { font-size: 0.8em; margin-top: 0px; }
</style>
<div class="flickr-frame">
<a href="http://www.flickr.com/photos/ariejan/392983564/" title="photo sharing"><img src="http://farm1.static.flickr.com/147/392983564_a222b6b741.jpg" class="flickr-photo" alt="" /></a>
<br />
<span class="flickr-caption"><a href="http://www.flickr.com/photos/ariejan/392983564/">Goals in the Park</a>, originally uploaded by <a href="http://www.flickr.com/people/ariejan/">ariejan</a>.</span>
</div>
<p class="flickr-yourcomment">
My new hobby is photography, if you didn't know already. Today I was strolling the park and I took this picture. Actually, I took three pictures and created a HDR (<a href="http://en.wikipedia.org/wiki/High_dynamic_range_imaging">High Dynamic Range</a>) image of them.<br />
<br />
Hope you enjoy the view and let me know if you want more information on this subjejct!
</p>

View File

@ -0,0 +1,52 @@
+++
date = "2007-02-21"
title = "RoR: link_to_remote with a text_field value as an argument"
tags = ["General", "RubyOnRails", "Features"]
slug = "ror-link_to_remote-with-a-text_field-value-as-an-argument"
+++
Forms are very well supported in Ruby on Rails. But in some cases you want to get information about a value a user has entered in a form, but without submitting the entire form. A good example of this is the sign up procedure at Yahoo. You enter your desired username, click "check availability" and you know if the name is available to you.
In my case I want to add locations to my database and use geocoding to get latituden/longitude values. So, I want users to enter an address and click "check" to verify that geocoding is successful. When successful, the full address and lat/lng values are automatically filled out in the form.
This article shows you how to update those text fields and most importantly, it shows how to add a text_field value as a paramater to your link_to_remote tag.
<!--more-->
This last part is easy with RJS:
<pre lang="ruby">render :update do |page|
page[:location_address].value = gecode.full_address
page[:location_lat].value = geocode.lat
page[:location_lng].value = geocode.lng
end</pre>
But now the tricky part! How to include the value of a text_field in a link_to_remote tag?? A normal link_to_remote tag might look like this:
<pre lang="ruby">link_to_remote "Check address",
:url {
:controller => 'locations',
:action => 'check_address',
:address => @location.address
},
:method => :get</pre>
The problem here is that we're at the 'new' form, so @location doesn't contain anything yet. Erb isn't going to help us either because it's already rendered and cannot change something 'onClick'.
You got it, JavaScript is your friend! You could now write a JS function that retrieves the value of the text_field and add it to the link_to_remote request. Well, you could. But there is an easier way!
Prototype is the answer! It comes default with Rails and if you already use the javascript defaults, it's already at your diposal. If not, include prototype in your layout first:
<pre lang="ruby">< %= javascript_include_tag 'prototype' %></pre>
Now, we can use Form.element.getValue to get the text_field value. Since Prototype is very nice, there's a shortcut available: $F(element).
The next question is how to integrate this with our link_to_remote tag. The :with paramater offers help!
<pre lang="ruby">link_to_remote "Check address",
:url {
:controller => 'locations',
:action => 'check_address',
:address => @location.address
},
:with => "'address='+encodeURIComponent($F(

View File

@ -0,0 +1,33 @@
+++
date = "2007-02-23"
title = "Subversion Cheat Sheet 1.0!"
tags = ["General", "Features", "Subversion"]
slug = "subversion-cheat-sheet-10"
+++
I've noticed a huge interest in my <a href="/tags/subversion?phpMyAdmin=umjo2KeaY3NOkOP-0%2Czc9FZ9J96">Subversion articles</a> lately and I thought to create a nice cheat sheet for all you.
The cheat sheets includes common commands that you'll use when using Subversion on a daily basis. I didn't include every option or command that subversion supports, nor did I include any administration stuff. This sheet is aimed at developers who use Subversion on a daily basis.
<!--more-->
You can find the Subversion Cheat Sheet and future updates at:
<blockquote><a href="http://ariejan.net/svncheatsheet">http://ariejan.net/svncheatsheet</a></blockquote>
<strong>Please link to the url above from your blog to spread the word! Thanks.</strong>
Topics covered in this cheat sheet are:
<ul>
<li>Subversion Status codes</li>
<li>Daily usage commands</li>
<li>Bug fixing</li>
<li>Branching and tagging</li>
<li>File Magic</li>
<li>Locking</li>
<li>Properties</li>
<li>Experimenting</li>
</ul>
Please let me know if anything's missing.

View File

@ -0,0 +1,30 @@
+++
date = "2007-02-26"
title = "4 Unusual uses for Subversion"
tags = ["General", "Features", "Subversion"]
slug = "4-unusual-uses-for-subversion"
+++
The most common use of Subversion is to keep source code of applications versioned and secure. However, there are quite a few other options that are not so common at all.
Quickly read on and find out if maybe you can put Subversion to use in quite a few ways you didn't expect.
<!--more-->
<strong>1. CMS</strong>
Maybe CMS is a bit strong, but it's very easy to develop a static website locally and store it in Subversion. You just checkout your website on your production server and you're good to go. You can easily jump back to previous content and you always have a backup around.
<strong>2. Todo list / Notes</strong>
You can version a list of text files as todo items or notes. You can check it out anywhere you want and keep track of all your past notes and items. You will have to establish some sort of formatting convention for yourself as how you name files and all that.
<strong>3. Backups</strong>
Put your entire home directory in Subversion. You'll always have a backup handy and you can easily jump back in time! Maybe it's not as sophisticated as <a href="http://www.apple.com/macosx/leopard/timemachine.html">Mac OS X Leopard's Time Machine</a>, but it serves its purpose.
<strong>4. Community Story Writing</strong>
It's a bit like coding. You could use Subversion to write a story (or manuscript or book or ...) as a community. It's a bit like a wiki, but you can all use your favourite editors. You'll have to agree on an ASCII based file format, though.
Maybe you know some very cool way to use Subversion as well? Please comment below!

View File

@ -0,0 +1,17 @@
+++
date = "2007-03-06"
title = "Subversion Cheat Sheet Update: 1.0.1"
tags = ["General", "Blog", "Subversion"]
slug = "subversion-cheat-sheet-update-101"
+++
I've just uploaded version 1.0.1 of the <a href="http://ariejan.net/svncheatsheet">Subversion Cheat Sheet</a> to Ariejan.net.
Please download this new version and get the following change:
<ul>
<li>Fixed typo. Thanks to Gregory Gerard.</li>
</ul>
Head to the <a href="http://ariejan.net/svncheatsheet">Subversion Cheat Sheet</a> page now and download the new version.

View File

@ -0,0 +1,53 @@
+++
date = "2007-03-07"
title = "Wordpress Plugin: AutoFlickr 1.0"
tags = ["General", "Wordpress", "Features", "AutoFlickr"]
slug = "wordpress-plugin-autoflickr-10"
+++
This post announces my first Wordpress Plugin: AutoFlickr.
<h3>What does it do?</h3>
When enabled, AutoFlickr will automatically find and insert one ore more photos that are related to the content of your post. Photos are found and hosted on <a href="http://www.flickr.com">Flickr</a>.
<h3>Features</h3>
<ul>
<li>Automatically insert one or more photos</li>
<li>Customizable (photo size, number of photos and type of search).</li>
<li>Option to select what pages to automatically show photos.</li>
</ul>
<!--more-->
<h3>Installation</h3>
<ol>
<li>Download the latest version here: <a href="http://ariejan.net/upload/autoflickr/autoflickr-10.zip">AutoFlickr 1.0</a>.</li>
<li>Unzip the downloaded file and put the entire 'autoflickr' directory in /wp-content/plugins</li>
<li>Activate the plugin under Plugins</li>
<li>Go to Options -> AutoFlickr to customize the settings. </li>
</ol>
That's it. Optionally you may want to adapt autoflickr.css to change the way the images are aligned and styled.
If you want to include images in another place than the default, you may disable AutoFlickr for all pages and include the following PHP code in your template. Note that this code must be used within "The Loop".
<pre lang="php"><?php echo autoflickr_html(); ?></pre>
<h3>Demo</h3>
This plugin was developed for <a href="http://citytrippers.net">CityTrippers.net</a>. You can see the plugin in action when reading a single story.
<h3>Support</h3>
Please leave a comment or <a href="http://ariejan.net/contact">contact me</a> directly if you have any questions regarding this plugin.
<h3>New versions?</h3>
Please subscribe to my <a href="http://feeds.feedburner.com/Ariejan">RSS Feed</a> (or use <a href="http://www.feedburner.com/fb/a/emailverifySubmit?feedId=411105">e-mail subscription</a>) to get automatic updates about Ariejan.net and this plugin.

View File

@ -0,0 +1,54 @@
+++
date = "2007-03-20"
title = "8 Great ways to use Google for your start-up"
tags = ["General", "Blog", "Google"]
slug = "8-great-ways-to-use-google-for-your-start-up"
+++
<a href="http://www.google.com">Google</a> is more than a search engine or an advertising company. Of course, it's their core business, but Google has more to offer. In this article I'll describe how you can put Google to work for your start-up (or existing business!). Oh, did I mention you can do all of this for free?
The most commonly known service Google provides besides search and advertising is <a href="http://mail.google.com">Gmail</a>. Nowadays Gmail is a common concept in the field of e-mail services. When the services started you got a 1Gb inbox. Today you can store up to around 2.8Gb of emails and Google Talk chat transcripts! Wouldn't it be great to use this for you company for free?
Well you can! And a lot more!
<!--more-->
Most people may have heard about <a href="http://www.google.com/a/">Google Apps</a>.
So, what is Google Apps and how can I put it to use for my start-up?
When you visit Google Apps you can sign up for the "free" edition which will give you the following
<ol>
<li>Gmail with 2Gb inbox per user - You know how it works. Just for @yourdomain.com</li>
<li>Google Talk - Allow your users to chat easily with Google Talk</li>
<li>Google Calendar - Shared and personal calendars for free!</li>
<li>Docs & Spreadsheets - Write documents and spreadsheets easily online and collaborate with co-workers.</li>
<li>Page Creator - Creating a web site has never been easier!</li>
<li>Start Page - Know <a href="http://www.google.com/ig">Google Personal Homepage</a>? Same stuff but for yourdomain.com!</li>
<li>Easy administration panel to manager services and users</li>
<li>Unlimited number of users and online support</li>
</ol>
So, if you already own a domain name, or register one for a few bucks (or for $10 at Google), you can run email, instant messenging, calendar services, online office (docs & spreadsheets), page creator and a custom start page for your users for free!
This will cost you $10 bucks a year (for the domain name when registered with Google). All you need is a computer, Internet connecton and a decent browser.
How's that for an initial investment in your start-up company? Oh, don't forget that you can access all the above everywhere as long as you have an Internet connection! You can always (and easily) access your documents and e-mail or check your calendar. You can even do that with your mobile phone!
Personally I think Google Apps are a great investment in your start-up company. I'll give you the pro's and cons one more time:
<strong>Pro</strong>
<ul>
<li>It's free (except for the domainname)</li>
<li>Quality service you expect from Google</li>
<li>You have it all under one roof ready to go.</li>
<li>Access to your stuff everywhere in the world!</li>
</ul>
<strong>Con</strong>
<ul>
<li>Nothing really.</li>
</ul>
Let me know if you have any experience with Google Apps. Did I miss some feature? Please let me know!

View File

@ -0,0 +1,54 @@
+++
date = "2007-03-20"
title = "How I made 6 figures with Google Adsense in 10 days"
tags = ["General", "Blog", "Google", "AdSense", "Sarcasm"]
slug = "how-i-made-6-figures-with-google-adsense-in-10-days"
+++
There has been a lot of talk about making money with Google Adsense. There are claims of people earning over $10.000 every month by just putting a few ads up on their site.
I say they are amateurs! I'll show you how to make a 6-figure earning within 10 days after you put up ads on your site! Just follow these easy steps and you can quit your day job after just ten days of work. It' what I did.
<!--more-->
<h3>Decide on a topic for your site</h3>
First you must decide on what the topic of your site is. Try a <a href="http://uv.bidtool.overture.com/d/search/tools/bidtool/?mkt=uk">keyword bid searching tool</a> to find out which keywords and topics will generate the most.
It's not important if you don't have any knowledge on the topic you will be writing about. It's just about making money.
<h3>Register a domain</h3>
Next you must register a domain and get your hosting setup. You can do this for a few bucks. This is the only investment you have to do here! For the $10 investment in hosting and domain registration you'll get a ROI of more than 100.000%.
When choosing a domain, make sure it's catchy. Something like "earn-money-with-adsense-for-free.com" or "imearningsixfigureswithadsensesucker.com". It doesn't need to be readable it just needs to contain a lot of keywords for you site.
Don't bother with quality hosting. Just find the cheapest reseller you can find. Make sure you get at least 5Tb of bandwidth, though. You'll need it.
<h3>Setup your site</h3>
Open up Frontpage and write an article. It only needs to be a few paragraphs. Make sure to include lots of keywords so Google can attach the right, high paying, ads.
<h3>Add the ads!</h3>
With your site in order now, add the maximum amount of ads allowed. For optimal results use the biggest ad format available and make sure a visitor sees the ads even before they reach the content of your site. This ensure the maximum clich-thru rate possible.
Also include a link-block. This will lure visitors to a page with only ads from Google! This is a real gold mine!
The third thing Google offers are referrals. Plaster some big images at the bottom. Claim how much you make with your site and have users sign-up for adsense too. This will make you $200 almost instantly!
Don't forget the obligatory "Use Firefox" referral!
<h3>Publish your site</h3>
Now it's time to publish your site and start making the big bucks! It's almost time to quit your day job.
Surf around and post a link to your site everywhere you can. Comment on any blog you see and put your link there. Roam forums and randomly insert links to your site there too.
If you're feeling adventurous you may also setup an Adwords campaign yourself and pay for visitors. Since you have many high-paying ads on your site you can make money at a 1:10 ratio ($1 spend on adwords is $10 earned in Adsense)
<h3>And now... you wait</h3>
Now you wait ten days and then quit your job (you have a two weeks notice anyway). After those ten days you'll have made a nice 6 figures in hard currency. Just wait for the check to arrive and you're done!
Oh, don't forget to ***** my *** since I gave you this very valuable information and I still need to reach my 6 figures for this month. Thank you.

View File

@ -0,0 +1,52 @@
+++
date = "2007-03-21"
title = "26 Things you can do with an old PC"
tags = ["General", "Blog", "Fun"]
slug = "26-things-you-can-do-with-an-old-pc"
+++
We've all been there. Your old trusty PC dies. First thing you do is buy a new one. After you're done playing with all the new bells and whistles your old PC didn't have, it's time to thing what to do with the old fella.
Here are some tips!
<!--more-->
The whole system can be used like this:
<ol>
<li>Give it away to friends or family who can use the "upgrade"</li>
<li>Take it apart and see what comes out</li>
<li>Create route/firewall for your network</li>
<li>Creata a file server</li>
<li>Install and try Linux</li>
<li>Create a jukebox / media player</li>
<li>Sell it</li>
<li>Trash it / Recycle it</li>
<li>Ceremonially set it on fire</li>
<li>See what happens when you shoot it</li>
<li>Symbolically throw it out of the window</li>
</ol>
If you only have the casing, this can be put to great use!
<ol start="12">
<li>Take everthing out and turn it into a barbeque</li>
<li>See what happens when you don't cool your processor</li>
<li>Strip it and sell the working parts</li>
<li>Blow it up</li>
</ol>
You an also strip the insides of your case and put another device in it:
<ol start="16">
<li>Coffee maker</li>
<li>Aquarium (with plexi glass plating, of course)</li>
<li>Webcam</li>
<li>Paper shredder</li>
<li>Use it as a trash can</li>
<li>Make it a mailbox</li>
<li>Build a can dispenser (hit 'reset' to obtain a beverage of your choice)</li>
</ol>
The monitor (CRT) can be used for various purposes as well:
<ol start="23">
<li>This can also be converted into an aquarium</li>
<li>Remove the tube and create a cage for small animals</li>
<li>Ash tray</li>
<li>CD / DVD Rack</li>
</ol>
Got your own personal favourite? Please post a comment and share it with us all!

View File

@ -0,0 +1,23 @@
+++
date = "2007-03-22"
title = "Rails Tip Snippet: Logging informational messages to your log"
tags = ["General", "RubyOnRails", "Features", "TipSnippets"]
slug = "rails-tip-snippet-logging-informational-messages-to-your-log"
+++
This "Rails Tip Snippet" is one in a series of small blocks of code that will make your life developing Rails applications a bit easier.
This first snippet shows you how you can log informational message to your log file so you can track any important actions that happened. As an example you may want to log all user accounts that get deleted:
<!--more-->
<pre lang="ruby">def destroy
@user = User.find(params[:id])
@user.destroy!
logger.info("User account '#{@user.login}' deleted by user #{current_user.login})
...
end</pre>
Line 4 will put a string like "User account 'johnlocke" delete by user ariejan" in your log file. Use that information any way you want.
You may also use the logger to inspect variables:
<pre lang="ruby">logger.info("article inspection: #{@article.inspect}")</pre>
Until next time! Any tips are welcome at <a href="mailto:tips@ariejan.net">tips@ariejan.net</a>.

View File

@ -0,0 +1,88 @@
+++
date = "2007-03-23"
title = "Be productive! 37 things you can do on the toilet"
tags = ["General", "Blog", "Features", "Lists", "Fun", "Productivity"]
slug = "be-productive-37-things-you-can-do-on-the-toilet"
+++
We all have to go. Most of us once a day. Others have to do it more often. However, we can be much more productive while doing or daily duty at the toilet.
Besides the old "joke book" and "newspaper" what can you do on the toilet to kill the time? I've found 37 things that might be a good option for you next number 2.
<!--more-->
<strong>1. Newspaper</strong> - The age old classic of reading the newspaper. Nothing strage about that, right?
<strong>2. Joke book</strong> - Some loos feature a book with jokes for you to read. Nice, but mostly the jokes are of a very low quality.
<strong>3. Puzzle </strong>- Bring your sudoku book (any other type of puzzle will do) and start puzzling.
<strong>4. Novels</strong> - If you find it hard make time to read that novel everyone has been talking about, read it on the toilet. It'll take a bit longer than usual, but you'll get there.
<strong>5. Brainstorm</strong> - It's quiet out there. Use your time to brainstorm and get some new ideas for whatever you need new ideas for. A pen and paper are handy to write it all down. Otherwise you may flush your ideas with the rest.
<strong>6. Redo your makeup</strong> - This one is for women only, but this is a nice place to redo your makeup with that travel-makeup-kit-thingy you always carry around.
<strong>7. Poke your nose</strong> - This is also a classic one. Nobody pokes his nose in public (well, most of us don't) but if you like to clean it out, the toilet a good place to do it. No one sees you and you'll get to wash your hands afterwards.
<strong>8. Listen to music</strong> - iPods are portable. Carry them with you at all times and listen to some tunes while sitting there. Other music devices such as mobile phones or mp3 players can be used as well.
<strong>9. Listen to podcasts</strong> - If you subscribe to podcasts, this is the time to listen to a few of them.
<strong>10. Watch some video</strong> - Have an iPod video or another portable video device such as the Playstation Portable? Make sure to set a clock, some movies run longer than 2 hours.
<strong>11. Play a game</strong> - You can play games on mobile phones, PDAs, iPods and portable gaming devices such as the Playstation Portable or a GameBoy. This is the time to finally beat the machine or set a new high score.
<strong>12. Learn stuff</strong> - Want to learn how to play Texas Hold'em poker? How to build your own kite? How to ... You get it. Print out an article or two, bring a book or even your laptop and read more on these subjects.
<strong>13. Watch movie trailers</strong> - Don't have time to watch trailers? Put 'em on your iPod and watch while waiting.
<strong>14. Chat</strong> - A lot of mobile devices have chat services. A laptop is the easiest way of chatting on the loo. If you want to talk, go ahead.
<strong>15. Read your mail</strong> - Use you mobile phone, PDA or laptop to check your (personal) email.
<strong>16. Check your stock</strong> - If you have stock feel free to check how much it's worth now.
<strong>17. Blog</strong> - Want to write a blog post? Write it on the loo. If you don't have wireless access (you should get that right now!) you can submit the post when you come back.
<strong>18. Tune your phone</strong> - This is more of a one time thing, but you may want to change your phones theme, background or ringtone every so often.
<strong>19. Read news</strong> - If you don't have a newspaper feel free to read the news now on your laptop or PDA.
<strong>20. Organise your schedule</strong> - While you have the time, plan all the activities you need to plan and mark any problems in your schedule so you can fix them later (or fix them right now!).
<strong>21. Check Adsense</strong> - It's always a good time to check up on Adsense and todays earnings.
<strong>22. Check your site statistics</strong> - Login to Analytics or view your logfiles and see if anything new is developing.
<strong>23. Decide on dinner</strong> - Don't know what to eat after work? This is a time to decide on that.
<strong>24. Install/update software</strong> - Are new updates for your favourite programs waiting, take a bit of time and install them now.
<strong>25. Organise your to-do list</strong> - Check off items you have finished and add new ones you just thought off.
<strong>26. See what movies are running</strong> - Feel like going to a movie? Check online what's running tonight.
<strong>27. Ping your coffee machine</strong> - If you're a real geek, ping your coffee machine and brew a fresh pot for when you're finished here.
<strong>28. Browse YouTube</strong> - Find a few movies you like and watch them. Laptop required.
<strong>29. Uninstall software</strong> - Uninstall all applications you don't use to free up more space for your iTunes library.
<strong>30. Organise your documents</strong> - Organise all your files. Put them in neat folders and rename them properly.
<strong>31. SEO your site</strong> - Apply some quick patches to your site to improve SEO.
<strong>32. Link!</strong> - Post a speedlinking post or add links to your blogroll for sites your recently visisted.
<strong>33. Check free sites</strong> - Check those sites that collect free offers. Maybe something interesting has come up.
<strong>34. Hack the wireless routes</strong> - Try hack the wireless router your currently using. Make sure you don't get fired over it!
<strong>35. Plan your trip home</strong> - Use an online planner to plan your trip home.
<strong>36. Work!</strong> - Need to finish a document fast? Continue working!
<strong>37. Do nothing</strong> - Old fashioned Number 2. Just sit there, do your thing and go!
Do you know other tasks you may perform while doing a number 2? Please continue the list in the comments. Thanksk for sharing!

View File

@ -0,0 +1,40 @@
+++
date = "2007-03-25"
title = "Speedlinking: Top 28 startup resources"
tags = ["General", "Blog", "Links"]
slug = "speedlinking-top-28-startup-resources"
+++
I've been reading a lot about startups this weekend. Here is a quick post with all the articles I came across this weekend and found worth mentioning:
<ol>
<li><a href="http://www.startupping.com/">Startupping</a> <strong>TIP</strong></li>
<li><a href="http://www.paulgraham.com/start.html">How to start a startup</a></li>
<li><a href="http://evhead.com/2005/11/ten-rules-for-web-startups.asp">Ten rules for web startups</a></li>
<li><a href="http://money.cnn.com/magazines/business2/startups/index.html">Business 2.0: How to build a bulletproof startup</a></li>
<li><a href="http://paulgraham.com/startupmistakes.html">The 18 Mistakes that kill Startups</a></li>
<li><a href="http://www.paulgraham.com/startuplessons.html">The Hardest Lessons for Startups to Learn</a></li>
<li><a href="http://www.paulgraham.com/startupfunding.html">How to fund a startup</a></li>
<li><a href="http://particletree.com/features/5-reasons-to-create-your-first-startup-now/">5 Reasons to create your first startup</a></li>
<li><a href="http://dottactics.blogspot.com/2006/02/9-must-reads-before-you-launch-startup.html">9 Must reads before you start a startup</a></li>
<li><a href="http://www.avivadirectory.com/branding/?p=1">Little Known Ways to Brand on the Cheap: 99 Tips for Poor Web Startups</a></li>
<li><a href="http://www.readwriteweb.com/archives/6_startup_lessons_2007.php">6 Startup Lessons For The Year 2007</a></li>
<li><a href="http://philip.greenspun.com/business/startup-tips/">Tips for startup companies</a></li>
<li><a href="http://paulgraham.com/ideas.html">Ideas for startups</a></li>
<li><a href="http://www.scoreboard-media.com/internet-startup-traffic/">8 Simple Steps to Build Traffic For Your Internet Startup</a></li>
<li><a href="http://www.folksonomy.org/2006/10/7_tips_for_naming_your_startup/">7 Tips for naming your Web 2.0 startup</a></li>
<li><a href="http://www.downloadsquad.com/2006/12/01/seven-rules-for-web-2-0-startups/">7 Rules for Web 2.0 Startups</a></li>
<li><a href="http://onstartups.com/home/tabid/3339/bid/193/Startup-Websites-That-Work.aspx">Startup Website That Work</a></li>
<li><a href="http://onstartups.com/home/tabid/3339/bid/115/Hindsight-2-0-Lessons-From-A-Failed-Web-2-0-Startup.aspx">Hindsight 2.0: Lessons From A Failed Web 2.0 Startup</a></li>
<li><a href="http://www.stevepavlina.com/blog/2006/04/10-stupid-mistakes-made-by-the-newly-self-employed/">10 Stupid Mistakes Made by the Newly Self-Employed</a></li>
<li><a href="http://startupspark.com/the-5-most-common-mistakes-made-by-startups/">The 5 Most common mistakes made by startups</a></li>
<li><a href="http://paulgraham.com/mit.html">A Student's guide to startups</a></li>
<li><a href="http://www.thisisgoingtobebig.com/2005/08/10_steps_to_a_h.html">10 Steps to a Hugely Successful Web 2.0 Company</a> <strong>TIP</strong></li>
<li><a href="http://onstartups.com/home/tabid/3339/bid/68/Startup-Success-The-Phenomenal-Force-Of-Focus.aspx">Startup Success: The Phenomenal Force Of Focus</a></li>
<li><a href="http://www.monthlydollar.com/startup/">Web 2.0 Startup: The Business Model</a> <strong>TIP</strong></li>
<li><a href="http://37signals.com/svn/archives2/small_biz_101_how_to_get_started.php">Small Biz 101: How to Get Started</a> <strong>TIP</strong></li>
<li><a href="http://money.cnn.com/magazines/business2/business2_archive/2006/05/01/8375910/index.htm">5 ways to start a company (without quitting your day job)</a></li>
<li><a href="http://onstartups.com/home/tabid/3339/bid/69/Startup-Suicide-Five-Ways-To-Kill-Your-Startup-Which-Will-You-Pick.aspx">Startup Suicide: Five Ways To Kill Your Startup, Which Will You Pick?</a></li>
<li><a href="http://www.miketaber.net/articles/StartupsForTheRestOfUs.aspx">Startups for the rest of us</a></li>
</ol>
Got any articles that are not on the list? Please add a comment to let me know!

View File

@ -0,0 +1,15 @@
+++
date = "2007-03-27"
title = "Rails Tip Snippet: Create a comma-seperate list"
tags = ["General", "RubyOnRails", "Features", "TipSnippets"]
slug = "rails-tip-snippet-create-a-comma-seperate-list"
+++
Do you have the need to create a list of roles a certain user belongs to? Enumerate the users attached to a company? All you want is a simple list with the names seperated by commas.
Users: John, Dick, Harry
With Ruby on Rails this is really easy. You probably have a collection of user objects. All you want is a list of names:
<pre lang="ruby">@users.collect{|u| u.name}.join(', ')</pre>
Read more <a href="http://ariejan.net/tags/tipsnippets/">Tip Snippets</a>?

View File

@ -0,0 +1,12 @@
+++
date = "2007-03-27"
title = "Subversion: How to revert to a previous revision"
tags = ["General", "Features", "Subversion"]
slug = "subversion-how-to-revert-to-a-previous-revision"
+++
You've been there. You have been developing in your trunk for a while and at revision 127 you get the feeling you've done it all wrong! The production server is humming away at revision 123 and that's where you want to start out again. But how can you start again from revision 123? Easy as this with Subversion:
svn merge -rHEAD:123 .
This will see what changes you've made since r123 up until now (r127 in your case) and 'undo' them. Next you check in the code and you've go a sweet r128 that is exactly the same as r123. You can start over now!

View File

@ -0,0 +1,23 @@
+++
date = "2007-03-29"
title = "5 Reasons why PC OEMs should offer Linux"
tags = ["General", "Blog", "Linux", "Opinion"]
slug = "5-reasons-why-pc-oems-should-offer-linux"
+++
DELL currently offers Linux as an option for certain laptop and desktop models. Talk is that this service may be expanded to all models. This is a good thing, of course. Results of a <a href="http://www.dell.com/content/topics/global.aspx/ideastorm/ideasinaction?c=us&l=en&s=gen">recent survey by DELL</a> show that more than 70% of over 100.000 respondents want to use Linux for home and office! What has been keeping companies like DELL away from this?
I've found five good reasons why OEMs should offer Linux as at least an option:
<strong>1. Freedom of Choice</strong> You pay for your hardware. Its' yours. You should be able to use that hardware any way you want. The OEM should not force you to use anything else than what you want.
<strong>2. It saves customers money.</strong> If a customer doesn't want to use Microsoft Windows? Why charge him for a license anyway?
<strong>3. It's an unserved market.</strong> There are no mayor OEMs out there offering Linux as a default option. You get Microsoft Windows. In some cases you don't have to buy Windows and get a clean hard drive instead. People want to use Linux, but they don't want to go through the download-install-configure process. This is a big oppertunity, if you ask me.
<strong>4. Your hardware gets more popular.</strong> We've seen this with Nvidia already. May Linux users buy Nvidia cards because nvidia offers superb Linux drivers. Plug in the cards, install the drivers and off you go. If a player like DELL would support their hardware like that, people would be willing to buy DELL instead of <em>Brand X</em>. Once the word gets out that Linux 'just works' on a DELL, you'll know that more customers will come your way.
<strong>5. Current support options are sufficient.</strong> A majority of respondents to the Linux survey at DELL indicated that the current community support forums would suffice their needs. Besides that, there's a big Linux community out there willing to help new Linux users.
This space is reserved for linking to a list of why Linux should be the default OS for OEMs and Windows an option. (<a href="/contact?phpMyAdmin=umjo2KeaY3NOkOP-0%2Czc9FZ9J96">Contact me</a> if you want to post that list a a guest blogger to Ariejan.net).

View File

@ -0,0 +1,15 @@
+++
date = "2007-04-02"
title = "What do you want for AutoFlickr?"
tags = ["General", "Blog", "AutoFlickr"]
slug = "what-do-you-want-for-autoflickr"
+++
Almost a month ago I published my <a href="http://www.wordpress.org">WordPress</a> plugin <a href="http://ariejan.net/2007/03/07/wordpress-plugin-autoflickr-10/">AutoFlickr</a>, which shows one or more related photos from the popular Flickr site in your post.
Now I'm wondering what new features AutoFlickr users want. What parts of the current plugin are superfluous. Also, I'd like to know how is using AutoFlickr?
Please post a comment with your wishes for AutoFlickr 1.1. People using AutoFlickr may <a href="/contact?phpMyAdmin=umjo2KeaY3NOkOP-0%2Czc9FZ9J96">contact me</a> to let me know about their site. I will include a list of the ten most beautiful (my pick) sites that use AutoFlickr with the announcement of AutoFlickr 1.1.
I hope for a lot of feedback to make this plugin even better. Thank you.

View File

@ -0,0 +1,48 @@
+++
date = "2007-04-03"
title = "TipSnippet: Create a RSS feed"
tags = ["General", "RubyOnRails", "Features", "TipSnippets"]
slug = "tipsnippet-create-a-rss-feed"
+++
RSS is hot! So, you want to fit your new Rails app with one too! That's easy, of course, but you just need to know what to do.
This snippet will show you how to create an RSS feed form your RESTful articles. I'll assume you know how to generate a resource named 'article' with a title, body and the default created_at and updated_at attributes.
<!--more-->
You'll first need to add a new collection to your resource in config/routes.rb
<pre lang="ruby">map.resources :articles, :collections => {:rss => :get}</pre>
This will expose your RSS feed as http://localhost:3000/articles;rss
Create a corresponding action in the articles controller in app/controllers/articles_controller.rb. This method fetches the ten latest articles.
<pre lang="ruby">def rss
@articles = Article.find(:all, :limit => 10, :order => 'created_at DESC')
render :layout => false
end</pre>
I assume you render your articles in a layout. The render method here prevents your layout from rendering to create a plain XML file (which is what an RSS feed is).
Next we create a view. This is not the regular RHTML you're used to but RXML. This enables the XML generator which we'll use to generate the RSS feed. Create app/views/articles/rss.rxml
<pre lang="ruby">xml.instruct! :xml, :version=>"1.0"
xml.rss(:version=>"2.0"){
xml.channel{
xml.title("My Great Blog")
xml.link("http://www.example.com/")
xml.description("My great blog about very interesting stuff!")
xml.language('en-uk')
for article in @articles
xml.item do
xml.title(article.title)
xml.description(article.body)
xml.author("support@example.com")
xml.pubDate(article.created_at.strftime("%a, %d %b %Y %H:%M:%S %z"))
xml.link(article_url(article))
xml.guid(article_url(article))
end
end
}
}</pre>
Well, that's it. You now have a working RSS feed!
If you want to enable auto discovery, you should add the following line to the header of your layout. (Auto discovery enables that little RSS icon in the address bar of your browser.)
<pre lang="ruby">< %= auto_discovery_link_tag(:rss, :controller => 'articles', :action => 'rss') %></pre>
Share and enjoy! Thank you.

View File

@ -0,0 +1,65 @@
+++
date = "2007-04-12"
title = "Rails, Resources and Permalinks"
tags = ["General", "RubyOnRails", "Features"]
slug = "rails-resources-and-permalinks"
+++
There has been quite a bit of discussion about creating permalinks with a rails resource. In this article I will show you how to create permalinks for a resource named 'pages' without giving up on any of the resource goodness!
<!--more-->
Before I start I'll presume you have a page scaffold_resource setup in your rails application. Make sure you have at least the following fields in your page model:
<pre lang="ruby">t.column :title, :string
t.column :permalink, :string
t.column :content, :text</pre>
Okay, what you want is the permalink_fu plugin. This plugin greatly simplifies the act of generating a permalink from a title. Install it first:
<pre lang="bash">$ cd railsapp
$ ./script/plugin install http://svn.techno-weenie.net/projects/plugins/permalink_fu/</pre>
In your Page model you may now add the following line. This line will generate a permalink in the permalink attribute automatically, so you don't have to show the permalink field in any forms.
<pre lang="ruby">has_permalink :title</pre>
That's it for generating the appropriate permalink string in your database.
Rails goodness has already provided you with the basic RESTful routes:
<ul>
<li>/pages</li>
<li>/pages/123</li>
<li>/pages/new</li>
<li>/pages/123;edit</li>
</ul>
But what you really want, is something like:
<ul>
<li>/pages/perma-link-here</li>
</ul>
Notice that the permalink url is only a GET request and should not be used for editing or updating the page in question.
Since using any other identifier than :id in a resource is madness, I create two new routes that will allow me to access permalinked pages. Not only that, but I do maintain the format option. Basically this means that you get three routes:
<ul>
<li>/page/perma-link-here</li>
<li>/page/perma-link-here.html</li>
<li>/page/perma-link-here.xml</li>
</ul>
Notice that I removed the 's' from 'pages' here. This is to avoid confusion with the resource 'pages'. But more on that later.
Now in config/routes.rb add the following two lines:
<pre lang="ruby">map.permalink 'page/:permalink', :controller => 'pages', :action => 'permalink'
map.connect 'page/:permalink.:format', :controller => 'pages', :action => 'permalink', :format => nil</pre>
The first line adds a named route to an action named 'permalink' in your PagesController. This gives you the ability to add peralink links easily:
<pre lang="ruby">permalink_url(@page.permalink)</pre>
The second link is unnamed, and allows you to specify a format like HTML or XML.
The permalink action looks like this:
<pre lang="ruby"># GET /page/perma-link
# GET /page/permal-link.xml
def permalink
@page = Page.find_by_permalink(params[:permalink])
respond_to do |format|
format.html { render :action => 'show' }
format.xml { render :xml => @page.to_xml }
end
end</pre>
This special permalink action uses the same 'show' view as your resource.
If you want to maintain the 'pages' part of the URL, that's possible. You'll have to write a condition that makes sure that the :permalink parameter is a string an not an integer (ID). This article does not cover this.
You may now use permalinks for your pages! Congratulations.

View File

@ -0,0 +1,19 @@
+++
date = "2007-04-29"
title = "Ariejan.net server move"
tags = ["General", "Ariejan.net", "Blog"]
slug = "ariejannet-server-move"
+++
Just a note to let you know that Ariejan.net has just been moved to a new server! Well, I've moved from shared hosting with <a href="http://www.delta9.nl/">Delta9 Internet</a> to a VPS solution.
Why on earth would I do such a thing? I'm very happy with the service I've recieved from Delta9 in the past. However, I wanted more control over my hosting. I'm a web developer and I have special needs. Such needs include Subversion and Ruby on Rails hosting, state-of-the art PHP and MySQL installations. PostgreSQL support and some other things. Concluding that for Ariejan.net, shared hosting was no longer an option.
I could have taken a big step and buy myself a shiny new server all for my self, but that just doesn't fit into my budget at this time. When the time comes to host a dedicated server I will come back to Delta9 Internet.
So, Ariejan.net has moved to a VPS solution for the time being. Other sites I run are still hosted at Delta9, so I don't abandon them all together.
If you are looking for quality hosting with a personal touch, give <a href="http://www.delta9.nl/">Delta9 Internet</a> a try! Tell 'em I send you :)
I want to thank <a href="http://www.delta9.nl/">Delta9 Internet</a> for hosting Ariejan.net for such a long time, and when the time's right... I'll be back!

View File

@ -0,0 +1,18 @@
+++
date = "2007-05-09"
title = "Rails Snippet: Write like Orwell with to_sentence"
tags = ["General", "RubyOnRails", "Features"]
slug = "rails-snippet-write-like-orwell-with-to_sentence"
+++
A few weeks ago I posted <a href="http://ariejan.net/2007/03/27/rails-tip-snippet-create-a-comma-seperate-list/">an article</a> that explained how to create a comma separated list from a hash of objects. When I was browsing the <a href="http://api.rubyonrails.com">Rails API documentation</a> I came across a method named <a href="http://api.rubyonrails.com/classes/ActiveSupport/CoreExtensions/Array/Conversions.html#M000372">to_sentence</a>.
What this little bugger does is create a human readable, comma separated list of items in an array or hash. But the big difference here is that you can specify what the last separator must be. By default this is set to 'and'. See the following example.
<pre lang="ruby">@users = User.find(:all)
@users.collect {|u| u.firstname}.to_sentence
=> "Tom, Dick, and Harry"</pre>
Of you course, you can specify the last separator, called the connector. Also it's possible to not show the last comma.
<pre lang="ruby">@users.collect {|u| u.firstname}.to_sentence(:connector => "and of course,", :skip_last_comma => true)
=> "tom, Dick and of course, Harry"</pre>
I bet this will greatly simplify the way you list names, tags, categories or whatever else you want summed up in a comma separated list with a human touch.

View File

@ -0,0 +1,11 @@
+++
date = "2007-05-18"
title = "FeedBurner acquired by Google!"
tags = ["General", "Blog", "Google"]
slug = "feedburner-acquired-by-google"
+++
It looks like <a href="http://google.com">Google</a> is about to acquire <a href="http://feedburner.com">FeedBurner</a>. Just a note to all of you to let you know. If you have a blog or RSS enabled website, burn your feed now and get your AdSense account ready! Soon you'll be able to put targeted ads in your RSS feed and add another source of income to your list! Great news!
Please digg and share! Thank you!

View File

@ -0,0 +1,18 @@
+++
date = "2007-05-21"
title = "MERGE request failed on /path/to/file"
tags = ["General", "Features", "Subversion", "Trac"]
slug = "merge-request-failed-on-pathtofile"
+++
After upgrading my Subversion server to Ubuntu Feisty, I noticed that when committing I got the following error:
<pre lang="text">svn: MERGE request failed on '/svn/repository/trunk'
svn: MERGE of '/svn/repository/trunk': 200 OK (http://svn.myserver.com)</pre>
Although the messages says that the commit failed, it has not. A simple 'svn update' will merge the changes you made to the repository to your working copy again and you're good to go.
So, what is the problem here? Are you by any chance running Trac? Did you install the post-commit hook to integrate Subversion with Trac? Right, so did I.
The problem here is that the trac-post-commit-hook script needs a few updates in order to include the proper modules. Take a look at the <a href="http://trac.edgewall.org/browser/branches/0.10-stable/contrib/trac-post-commit-hook">most recent 0.10.x version</a>.
After updating the trac-post-commit-hook script, commits worked fine again. Such an easy fix for such a nasty problem.

View File

@ -0,0 +1,13 @@
+++
date = "2007-05-28"
title = "BAT - TER - Y"
tags = ["General", "Blog", "Fun"]
slug = "bat-ter-y"
+++
You all know the word: <em>"Battery"</em>. Like most words, it has several meanings. This site greatly explains the meaning of the word battery, and adds a little lyric-sugar to it!
Come on boys and girls! Sing along to <a href="http://bat-ter-y.com">BAT • TER • Y</a>.
(Please digg the site or post a link to it. Thanks!)

View File

@ -0,0 +1,63 @@
+++
date = "2007-05-29"
title = "Installing RMagick Ruby Gem on Mac OS X 10.4.9"
tags = ["General", "RubyOnRails", "Features", "Mac OS X", "Ruby"]
slug = "installing-rmagick-ruby-gem-on-mac-os-x-1049"
+++
When you want to manipulate images with Ruby (or your Rails application) you'll probably want RMagick installed. This is no easy feat on Mac OS X.
The official guide suggests installing X11 and using darwinports to install everything. This guide shows you how to easily install RMagick on you Mac OS X system. In this case I use Mac OS X 10.4.9.
<!--more-->
Before you jump in, make sure you have <a href="http://developer.apple.com/tools/xcode/">Xcode</a> installed. You can get it for free from Apple.
I'll also assume you have Ruby and rubygems installed and working already.
You will need to download, compile and install several graphics libraries that RMagick needs. Let's do this now.
<pre lang="bash">curl -O http://download.savannah.gnu.org/releases/freetype/freetype-2.1.10.tar.gz
tar xzvf freetype-2.1.10.tar.gz
cd freetype-2.1.10
./configure --prefix=/usr/local
make
sudo make install
cd ..
curl -O http://superb-west.dl.sourceforge.net/sourceforge/libpng/libpng-1.2.10.tar.bz2
bzip2 -dc libpng-1.2.10.tar.bz2 | tar xv
cd libpng-1.2.10
./configure --prefix=/usr/local
make
sudo make install
cd ..
curl -O ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz
tar xzvf jpegsrc.v6b.tar.gz
cd jpeg-6b
ln -s `which glibtool` ./libtool
export MACOSX_DEPLOYMENT_TARGET=10.4
./configure --enable-shared --prefix=/usr/local
make
sudo make install
cd ..
curl -O ftp://ftp.remotesensing.org/libtiff/tiff-3.8.2.tar.gz
tar xzvf tiff-3.8.2.tar.gz
cd tiff-3.8.2
./configure --prefix=/usr/local
make
sudo make install
cd ..</pre>
Next we install ImageMagick:
<pre lang="bash">curl -O http://easynews.dl.sourceforge.net/sourceforge/imagemagick/ImageMagick-6.3.0-0.tar.gz
tar xzvf ImageMagick-6.3.0-0.tar.gz
cd ImageMagick-6.3.0
./configure --prefix=/usr/local
make
sudo make install
cd ..</pre>
And now, ladies and gentlemen, what you've all been waiting for: RMagick:
<pre lang="bash">sudo gem install --no-rdoc --no-ri RMagick</pre>
In my case the generation of the documentation fails, so I tell rubygems not to compile the docs.
You now have RMagick installed on you Mac OS X 10.4.9 machine! Congratulations!

View File

@ -0,0 +1,15 @@
+++
date = "2007-05-29"
title = "Slow connections with ProFTPD"
tags = ["General", "Features", "Linux", "Ubuntu"]
slug = "slow-connections-with-proftpd"
+++
My shiny new VPS, which is running Ubuntu Linux, uses ProFTPD for FTP access. Today I noticed that setting up the connection takes about 5 to 10 seconds. This is really annoying when editing files through FTP.
So, I investigated and found that by default ProFTPD tries to revolve the hostname of the client in order to put that in the logs instead of a plain IP address. This lookup can take quite some time, let's say 5 to 10 seconds, especially when the look up fails and you have to wait on a time-out.
It's easy to stop ProFTPD from behaving like this by adding the following line to your proftpd.conf in /etc/proftpd:
<pre lang="text">IdentLookups off</pre>
Restart ProFTPD and you'll have a fast FTP connection to enjoy!

View File

@ -0,0 +1,50 @@
+++
date = "2007-05-30"
title = "Trac, WebAdmin plugin and global configuration"
tags = ["General", "Features", "Linux", "Ubuntu", "Trac"]
slug = "trac-webadmin-plugin-and-global-configuration"
+++
As you may know I manage quite a few <a href="http://trac.edgewall.org/">trac</a> installations. A few days ago I upgrade my server from Ubuntu "Dapper Drake" 6.06 to Ubuntu "Feisty Fawn" 7.04. This also upgrade trac 0.9.x to 0.10.3.
I was happy, since trac 0.10.3 has many improvements over 0.9.x, but there was one thing I was not so happy about. After the upgrade, I upgraded all my trac installations and everything seemed to be okay, except for the <a href="http://trac.edgewall.org/wiki/WebAdmin">WebAdmin plugin</a>. Apparently it was not installed anymore.
What happened? After upgrading the trac package, the plugins directory was emptied. Well, just re-install the WebAdmin plugin for 0.10.x.
<!--more-->
<pre lang="bash">cd /usr/share/trac/plugins
sudo svn co http://svn.edgewall.org/repos/trac/sandbox/webadmin/
cd webadmin
sudo python setup.py bdist_egg
cd dist
sudo easy_install-2.4 TracWebAdmin-0.1.2dev_r4429-py2.4.egg</pre>
That was easy, next I wanted to enable the plugin for all my trac installations by adding the proper configuration to /usr/share/trac/conf/trac.ini, the global trac configuration file that is used by all trac installs.
<pre lang="text">[components]
webadmin.* = enabled</pre>
After restarting Apache (this is needed for some reason to get trac to read the new configuration file), no admin button showed up in any of the projects.
What went wrong is that Ubuntu (or Debian?) maintainers have changed the location of the global configuration file for trac. There are three solutions to this, all of them work fine, although I recommend you use the first one.
<strong>1. Move your global configuration</strong>
The best way to tackle this problem is to move your global configuration file to the new location: /etc/trac/trac.ini
<pre lang="bash">sudo mv /usr/share/trac/conf/trac.ini /etc/trac/trac.ini</pre>
This way you're configuration is safe from new upgrades and confirms to the defaults the package maintainer has set.
<strong>2. Symlink the configuration</strong>
If for some reason you don't want to actually move your /usr/share/trac/conf/trac.ini file, you can create a symlink to the new location:
<pre lang="bash">sudo ln -sf /usr/share/trac/conf/trac.ini /etc/trac/trac.ini</pre>
<pre>
This leaves your original configuration file in tact, but it may be removed by new upgrades.
<strong>3. Change Trac</strong>
You may also change the location where trac looks for the configuration file. Open up /var/lib/python-support/python2.5/trac/siteconfig.py and change the following:</pre>
<pre lang="python">< __default_conf_dir__ = '/etc/trac'
> __default_conf_dir__ = '/usr/share/trac/conf'[/pre]
(Note: the > and < symbols mark what is removed and what is added to the file.)
In any case, reboot your web server and you should be good to go again.</pre>

View File

@ -0,0 +1,17 @@
+++
date = "2007-06-07"
title = "Coming up: Ubuntu Development Server Guide"
tags = ["General", "Blog", "Web Development", "Linux", "Ubuntu", "Subversion"]
slug = "coming-up-ubuntu-development-server-guide"
+++
My articles about setting up a Ubuntu Development Server (<a href="http://ariejan.net/2006/12/01/how-to-setup-a-ubuntu-development-server-part-1/">part 1</a> and part 2) have been very successful.
I'm considering writing a new guide with more up-to-date information on how to setup a development server that allows you (and your team) to develop software, manage source code, track tickets and all that stuff.
What should, according to you, be included in this guide? Please let me know! Just leave a comment and I'll pick it up.
<strong>Thank you for your input!</strong>
<em>Update: Estimated release of the "Ubuntu Develpment Server Guide is mid july</em>

View File

@ -0,0 +1,15 @@
+++
date = "2007-06-10"
title = "Find and Replace with a MySQL Query"
tags = ["General", "Databases", "Features", "MySQL"]
slug = "find-and-replace-with-a-mysql-query"
+++
There are times when you have a lot of data in a database (let's say wp_posts for a Wordpress blog like Ariejan.net). When you need to find and replace certain strings, this can be a very tedious task. Find all posts containing the "needle" string and manually replace all these occurrences with "chocolate". With about 200 posts, you can imagine how long this would take to do manually.
But, as I always say: <em>"You're a programmer! You should script the hell out of everything!"</em>
So, I found this: MySQL has built-in support to find and replace! Just a simple query will do:
<pre lang="sql">UPDATE wp_posts set post_body = replace(post_body, 'needle', 'chocolate');</pre>
That's it. The entire table 'wp_posts' is searched and all occurrences of "needle" are replaced with "chocolate". The query only took about a split second.

View File

@ -0,0 +1,38 @@
+++
date = "2007-06-10"
title = "Send mail with a BASH Shell Script"
tags = ["General", "Features", "BASH", "Shell Scripts"]
slug = "send-mail-with-a-bash-shell-script"
+++
Like any good programmer, I try to automate the crap out of everything. If you have to do it more than once, I try to write a script for it.
This time I want to show you how you can easily send an e-mail from a BASH script. The idea is that you want the script to send out an email to notify a user that something has happened.
<!--more-->
We're going to use the GNU Mail utility here. The basic syntax to send an email is like this:
<pre lang="bash">/usr/bin/mail -s "Subject" someone@example.org < message.txt</pre>
The trick when using this in a shell script is creating and using the message.txt file correctly.
Let's setup the basis first:
<pre lang="bash">#!/bin/bash
SUBJECT="Automated Security Alert"
TO="alarms@ariejan.net"
MESSAGE="/tmp/message.txt"
/usr/bin/mail -s "$SUBJECT" "$TO" < $MESSAGE</pre>
All we need to do now is create the message. In this example we're going to notify the receiver that something happened at a certain time. We can use the append (>>) operator to add text to the message file. Afterwards, we must remove the temporary message file, of course. The complete script now becomes:
<pre lang="bash">#!/bin/bash
SUBJECT="Automated Security Alert"
TO="alarms@ariejan.net"
MESSAGE="/tmp/message.txt"
echo "Security breached!" >> $MESSAGE
echo "Time: `date`" >> $MESSAGE
/usr/bin/mail -s "$SUBJECT" "$TO" < $MESSAGE
rm $MESSAGE</pre>
The email will contain the a timestamp from when the mail was sent.
This method is great for letting an administrator now if something happened. Maybe you need to check if your webserver is up and running. This script can an administrator about the issue.

View File

@ -0,0 +1,44 @@
+++
date = "2007-06-10"
title = "Ultimate List of Ruby Resources"
tags = ["General", "Web Development", "RubyOnRails", "Features", "Lists", "Ruby"]
slug = "ultimate-list-of-ruby-resources"
+++
This is the first post, named "Ruby", in a series of "Ultimate List of ... Resources". I'm going to compose several lists for different topics I encounter during my development work. To start, I begin with Ruby. Later, I will add "Ultimate Lists" about Ruby on Rails, Subversion, AJAX and some other topics.
Feel free to <a href="/contact">let me know</a> if I missed an important resource. I'm also open to suggestions about other "Ultimate Lists".
For now, you'll have to settle for the "Ultimate List of Ruby Resources".
<!--more-->
<strong>Books</strong>
<ol>
<li><a href="http://www.amazon.com/gp/redirect.html%3FASIN=0974514055%26tag=ariejannet-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0974514055%253FSubscriptionId=02ZH6J1W0649DTNS6002">"Programming Ruby: The Pragmatic Programmers' Guide, Second Edition"</a> by Dave Thomas, Chad Fowler and Andy Hunt</li>
<li><a href="http://www.amazon.com/gp/redirect.html%3FASIN=0672328844%26tag=ariejannet-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0672328844%253FSubscriptionId=02ZH6J1W0649DTNS6002">"The Ruby Way, Second Edition: Solutions and Techniques in Ruby Programming"</a> by Hal Fulton</li>
<li><a href="http://www.amazon.com/gp/redirect.html%3FASIN=0596523696%26tag=ariejannet-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0596523696%253FSubscriptionId=02ZH6J1W0649DTNS6002">"Ruby Cookbook"</a> by Lucas Carlson, Leonard Richardson</li>
<li><a href="http://www.amazon.com/gp/redirect.html%3FASIN=0977616614%26tag=ariejannet-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0977616614%253FSubscriptionId=02ZH6J1W0649DTNS6002">"Everyday Scripting with Ruby: For Teams, Testers, and You" by Brian Marick</a></li>
<li><a href="http://www.amazon.com/gp/redirect.html%3FASIN=1590597664%26tag=ariejannet-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/1590597664%253FSubscriptionId=02ZH6J1W0649DTNS6002">"Beginning Ruby: From Novice to Professional"</a> by Peter Cooper</li>
<li><a href="http://www.amazon.com/gp/redirect.html%3FASIN=0596002149%26tag=ariejannet-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0596002149%253FSubscriptionId=02ZH6J1W0649DTNS6002">"Ruby In A Nutshell"</a> by Yukihiro Matsumoto</li>
<li><a href="http://www.amazon.com/gp/redirect.html%3FASIN=0976694069%26tag=ariejannet-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0976694069%253FSubscriptionId=02ZH6J1W0649DTNS6002">"Enterprise Integration with Ruby"</a> by Maik Schmidt</li>
</ol>
<strong>Online manuals and API's</strong>
<ol start="8">
<li><a href="http://www.noobkit.com/">Noobkit</a> — Easily searchable Ruby API</li>
<li><a href="http://www.ruby-doc.org/core">Core API documentation</a></li>
<li><a href="http://www.ruby-doc.org/stdlib/">Ruby Standard Library</a></li>
</ol>
<strong>Groups, chat, forums, wiki and other community websites</strong>
<ol start="11">
<li><a href="http://www.ruby-forum.com/forum/4">Ruby Forum: Ruby</a></li>
<li><a href="http://www.ruby-forum.com/forum/14">Ruby Forum: Ruby Core</a></li>
<li><a href="http://groups.google.com/group/comp.lang.ruby/topics?lnk=srg">comp.lang.ruby</a> — Newsgroup</li>
<li><a href="http://groups.google.com/group/ruby-talk-google">Ruby-talk-google</a> — Google Group</li>
</ol>
<strong>Ruby Blogs</strong> (is yours listed yet? — <a href="/contact">Let me know!</a>)
<ol start="15">
<li><a href="http://www.oreillynet.com/ruby/">O'Reilly Ruby Blog</a></li>
<li><a href="http://www.rubyinside.com/">Ruby Inside</a></li>
<li><a href="http://www.rubycorner.com/">RubyCorner</a></li>
</ol>

View File

@ -0,0 +1,59 @@
+++
date = "2007-06-11"
title = "ActiveScaffold, Acts_as_taggable_on_steroids"
tags = ["General", "RubyOnRails", "Features", "ActiveScaffold"]
slug = "activescaffold-acts_as_taggable_on_steroids"
+++
<em>Update: also read <a href="http://ariejan.net/2007/07/01/activescaffold-acts_as_taggable-auto-complete/">Active Scaffold + Acts_as_taggable + Auto Completion</a>.</em>
This is kind of an advanced topic, but I think it may be useful to a lot of people.
<a href="http://www.activescaffold.com/">ActiveScaffold</a> is a great plugin to start building a user interface. The great thing about AS is, that is automatically recognizes associated models. When editing a model, you can easily add or select another model that you want to associate with is.
The best example of this is an Article, where you can select the author (the associated User model) with a drop down box.
There is only one point where I ran into trouble with ActiveScaffold: acts_as_taggable_on_steroids.
Acts_as_taggable_on_steroids allows you to easily attach tags to models and do all kinds of crazy stuff with them. But, if you want to integrate in into AcitveScaffold, you're in for a tough ride.
<!--more-->
ActiveScaffold supports has_many :through associations, but not in a way that is compatible with acts_as_taggable_on_steroids. Let me show you.
In your ArticlesController you specify which columns to show. "tag_list" is a stringified version of the tags associated with the Article, which is great for showing to a user.
However, if you want to edit it an article (or create one), I don't want a text field where I have to enter tags manually, all I want are a bunch of check boxes, so I can check which tags apply to this article.
Showing the check boxes is easy with AS. By default I show 'tags', only in the list view do I use 'tag_list' instead. Also, make sure to set the ui_type for the tags column to :select. This will show you check boxes, instead of a sub form that allows you to create tags manually.
<pre lang="ruby">active_scaffold :article do |config|
config.columns = [:title, :body, :tags, :author, :created_at]
config.list.columns = [:title, :author, :tag_list, :created_at]
config.columns[:tags].ui_type = :select
end</pre>
Well, very nice, right. You can now happily select the tags you want, and save your article. Not.
As you may have noticed, the tags are not saved. Why? Acts_as_taggable adds a 'tags' attribute to the model, however, when the Article model is saved, the tags attribute is overwritten by the tags specified in the "tags_list" attribute.
The only way to solve this is to convert the tags selected in AS and store them as the tags_list attribute for the Article.
First, let's add a private method in the ArticleController class:
<pre lang="ruby">private
def new_tag_list(tag_ids)
tag_ids.map {|k,h| h['id']}.collect {|i| Tag.find(i)}.map do |tag|
tag.name.include?(Tag.delimiter) ? "\"#{tag.name}\"" : tag.name
end.join(Tag.delimiter.ends_with?(" ") ? Tag.delimiter : "#{Tag.delimiter} ")
end</pre>
And add two protected methods that extend the functionality of ActiveScaffold:
<pre lang="ruby">protected
def before_create_save(record)
record.tag_list = new_tag_list(params[:record][:tags])
end
def before_update_save(record)
record.tag_list = new_tag_list(params[:record][:tags])
end</pre>
This will take the actual form values from AS and create a tags_list. This new tags_list is then assigned to the article (named 'record' here). The two protected methods process the tags every time an Article is created or updated.
With this in place, you can happily assign tags to your articles! Please let me know if it worked for you, or if you have made any improvements to this solution.

View File

@ -0,0 +1,68 @@
+++
date = "2007-06-12"
title = "BASH your SVN and Trac installation!"
tags = ["General", "Features", "BASH"]
slug = "bash-your-svn-and-trac-installation"
+++
I've already discussed how to install <a href="http://ariejan.net/?s=subversion">Subversion</a> and <a href="http://ariejan.net/?s=trac">Trac</a> on your <a href="http://ariejan.net/?s=ubuntu">Ubuntu server</a>. In my case I have a server that manages different SVN and Trac installations for a group of developers.
Creating a new SVN repository and Trac installation every time is quite boring and <em>"if you need to do it more than once, you should automate it"</em>. So, that's what I did.
<!--more-->
The result is the following BASH script. It takes one argument, the name of the project you want to create. E.g if you wanted to create a SVN repository and trac installation for "My Project" you would run the following command:
<pre>$ ./create_dev_env my_project</pre>
The script it self looks like this:
<pre lang="bash">#!/bin/sh
echo == Creating Subversion and Trac installation for $1
echo = Creating SVN Repository...
# Subversion
cd /var/lib/svn
mkdir -p /var/lib/svn/$1
svnadmin create /var/lib/svn/$1
sed s/EXAMPLE/$1/g /usr/share/trac/contrib/post-commit > /var/lib/svn/$1/hooks/post-commit
chmod +x /var/lib/svn/$1/hooks/post-commit
chown -R www-data:www-data /var/lib/svn/$1
# Trac
echo = Creating Trac install...
cd /var/lib/trac
mkdir -p /var/lib/trac/$1
echo - Creating files
trac-admin /var/lib/trac/$1 initenv $1 sqlite:db/trac.db svn \
/var/lib/svn/$1 /usr/share/trac/templates
echo - Removing anonymous permissions
trac-admin /var/lib/trac/$1 permission remove anonymous BROWSER_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous CHANGESET_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous FILE_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous LOG_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous MILESTONE_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous REPORT_SQL_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous REPORT_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous ROADMAP_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous SEARCH_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous TICKET_CREATE
trac-admin /var/lib/trac/$1 permission remove anonymous TICKET_MODIFY
trac-admin /var/lib/trac/$1 permission remove anonymous TICKET_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous TIMELINE_VIEW
trac-admin /var/lib/trac/$1 permission remove anonymous WIKI_CREATE
trac-admin /var/lib/trac/$1 permission remove anonymous WIKI_MODIFY
trac-admin /var/lib/trac/$1 permission remove anonymous WIKI_VIEW
echo - Creating Trac admins
trac-admin /var/lib/trac/$1 permission add ariejan TRAC_ADMIN
chown -R www-data:www-data /var/lib/trac/$1
echo
echo == Done.</pre>
First it creates the SVN directory in /var/lib/svn/my_project and creates repository and adds the trac post-commit hook for trac integration.
Next, it creates the trac installation in /var/lib/trac/my_project and removes all the persmission the anonymous users has. (You may want to remove these lines for open source or public projects.)
And, finally, I'm added as an administrator to the project. Make sure to replace this with you own username.
Hope you find this script useful. Any improvements are welcome, please let me know.

View File

@ -0,0 +1,13 @@
+++
date = "2007-06-14"
title = "Buy it now! Mac OS X 10.5 Leopard"
tags = ["General", "Blog", "Mac OS X"]
slug = "buy-it-now-mac-os-x-105-leopard"
+++
It appears that Amazon is accepting pre-orders for <a href="http://www.amazon.com/gp/product/B000FK88JK?ie=UTF8&tag=ariejannet-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B000FK88JK">Apple Mac OS X Version 10.5 Leopard</a><img src="http://www.assoc-amazon.com/e/ir?t=ariejannet-20&l=as2&o=1&a=B000FK88JK" style="border: medium none ! important; margin: 0px ! important" border="0" height="1" width="1" />, which is scheduled for release in October 2007.
There are, as usual two version available, <a href="http://www.amazon.com/gp/product/B000FK88JK?ie=UTF8&tag=ariejannet-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B000FK88JK">Apple Mac OS X Version 10.5 Leopard</a><img src="http://www.assoc-amazon.com/e/ir?t=ariejannet-20&l=as2&o=1&a=B000FK88JK" style="border: medium none ! important; margin: 0px ! important" border="0" height="1" width="1" /> at $129 for a single license and the <a href="http://www.amazon.com/gp/product/B000BR0NPO?ie=UTF8&tag=ariejannet-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B000BR0NPO">Apple Mac OS X Version 10.5 Leopard Family Pack</a><img src="http://www.assoc-amazon.com/e/ir?t=ariejannet-20&l=as2&o=1&a=B000BR0NPO" style="border: medium none ! important; margin: 0px ! important" border="0" height="1" width="1" /> for $199, which includes licenses for up to five Macs in your home.
If you want to be sure you have the latest version of <a href="http://www.amazon.com/gp/product/B000FK88JK?ie=UTF8&tag=ariejannet-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B000FK88JK"></a><img src="http://www.assoc-amazon.com/e/ir?t=ariejannet-20&l=as2&o=1&a=B000FK88JK" style="border: medium none ! important; margin: 0px ! important" border="0" height="1" width="1" /> when it arrives: <a href="http://www.amazon.com/gp/product/B000FK88JK?ie=UTF8&tag=ariejannet-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B000FK88JK">pre-order now!</a><img src="http://www.assoc-amazon.com/e/ir?t=ariejannet-20&l=as2&o=1&a=B000FK88JK" style="border: medium none ! important; margin: 0px ! important" border="0" height="1" width="1" />

View File

@ -0,0 +1,36 @@
+++
date = "2007-06-19"
title = "Geslaagd! / Passed my final exams!"
tags = ["General", "Ariejan.net", "Blog"]
slug = "geslaagd-passed-my-final-exams"
+++
<em>Please scroll down for the English version.</em>
Bij wijze van hoge uitzondering, een post in het Nederlands op mijn weblog! Ik ben vandaag geslaagd voor mijn opleiding Hogere Informatica (aan Fontys Hogeschool ICT, Eindhoven) en mag mezelf nu gediplomeerd Software Engineer noemen!
Ik ben op drie punten beoordeeld:
<ul>
<li>Eindrapport: 7,5 Ik ben er gewoon niet goed in, maar het is toch nog wat redelijks geworden.</li>
<li>Eindpresentatie: 8 Het ging gewoon lekker</li>
<li>Resultaat: 9 Dit slaat op het werk dat ik heb afgeleverd, mijn inzet, zelfstandigheid etc.</li>
</ul>
Samen komt dit uit op een eindcijfer <strong>8</strong>. Natuurlijk ben ik hier heel trots op, en ga het in ieder geval de rest van de dag vieren!
Feliciteren kan in 'n commentaartje :P
<em>Read more for the English version</em>
<!--more-->
<hr /> Today I passed my final exams for my degree in Software Engineering. I've been working on a Ruby on Rails project called "Course Builder" for the past few months. Today, I had to defend my work for a jury.In the Netherlands students are judged on 1 to 10 scale, where 10 is 'total perfection', 6 is 'seems okay' and 1 is total nonsense.
I've been judged on three subjects:
<ul>
<li>Final report: 7.5 I'm not very good at writing reports, but it's above average, still.</li>
<li>Presentation: 8 It went very well. I'm so happy with my MacBook and KeyNote</li>
<li>Results: 9 The results of my work and how I approached the project as a whole</li>
</ul>
The final grade is an <strong>8</strong>. I'm very happy with the over-all result and I'll be celebrating the rest of the day.
You may congratulate me in a comment :P

View File

@ -0,0 +1,21 @@
+++
date = "2007-06-20"
title = "Action Mailer: All mail comes from MAILER DAEMON"
tags = ["General", "RubyOnRails", "Features", "Ruby"]
slug = "action-mailer-all-mail-comes-from-mailer-daemon"
+++
Today I was trying to send mail from my Rails application through Action Mailer. This is quite simple, but I wanted to use a custom from-address. So, I create a setup_email method in my UserNotifier class that sets some defaults for every email sent out:
<pre lang="ruby">class UserNotifier < ActionMailer::Base
protected
def setup_email(user)
@recipients = "#{user.email}"
@from = "My Application <no-reply@example.com">
end
end</no-reply@example.com"></pre>
May you spotted the problem already, but I didn't. All the mail sent came from "MAILER DAEMON".
<pre>From: MAILER DAEMON</pre>
The problem was that @from didn't contain a properly formated from-address. It is missing the closing >, and so my email server ignores it.
If you have this issue, double check the from address, and make sure it's valid! Cheers.

View File

@ -0,0 +1,210 @@
+++
date = "2007-06-20"
title = "Rails production server setup and deployment on Ubuntu/Debian"
tags = ["General", "RubyOnRails", "Features", "Linux", "Ubuntu"]
slug = "rails-production-server-setup-and-deployment-on-ubuntudebian"
+++
<em>Please digg this story to spread the word! Thanks!</em>
Okay, this is a big one! This article will show you (and explain to you) how to setup a Ruby on Rails production server with Ubuntu 7.04 or Debian 4.0 and how to deploy your Rails application there.
First, what's getting installed:
<ul>
<li>Ruby 1.8.5</li>
<li>Ruby on Rails 1.2.3</li>
<li>Subversion 1.4</li>
<li>MySQL 5.x Server</li>
<li>Apache 2.2.x</li>
<li>Mongrel Cluster</li>
</ul>
I assume that you have just installed a fresh system with Ubuntu Linux 7.04 or Debian 4.0. If you haven't, do so now! You don't need to install the "DNS" or "LAMP" server in Ubuntu. Just a minimal system is enough for this tutorial.
I'll be deploy an imaginary Rails application named "myapp" which uses MySQL and is stored in Subversion. More on that later on.
Well, let's get going and get that Ruby on Rails server ready.
<!--more-->
<h3>Update your system</h3>
Before you do anything, use apt-get to update your system to the latest possible version.
<pre lang="bash">sudo apt-get update
sudo apt-get dist-upgrade</pre>
This probably installs a new kernel (linux-kernel) so a reboot may be in order for optimal performance.
<h3>Enable SSH</h3>
Most people will want to have SSH on their server to login remotely. In this case I install both the server and client so you can SSH out if you need to:
<pre lang="bash">$ sudo apt-get install openssh-server openssh-client</pre>
You will now be able to login remotely wiht SSH.
<em>You'll need SSH later if you want to use Capistrano to deploy your Ruby on Rails application. In any case, SSH is a good thing to have around.</em>
<h3>Subversion</h3>
If you are serious about your Ruby on Rails server, you want to have Subversion around. Most deployment scripts pull the latest revision of your code from subversion. No configuration needed here.
<pre lang="bash">$ sudo apt-get install subversion</pre>
We only need the client on the production server. We're not going to host Subversion repositories here.
<h3>Install MySQL Server</h3>
This is the first serious step you'll have to take. Both Ubuntu 7.04 and Debian 4.0 come with MySQL 5.0.x.
<pre lang="bash">$ sudo apt-get install mysql-server mysql-client libmysqlclient15-dev</pre>
Be sure to set a password for the root MySQL user. Failing to do so will leave your database open for anyone who wishes to see.
<pre lang="bash">$ mysqladmin -u root -h localhost password 'secret'
$ mysqladmin -u root -h myhostname password 'secret'</pre>
Make sure to replace <em>secret</em> with your actual password.
Try logging in to MySQL with your new password to make sure everything works okay.
<pre lang="bash">$ mysql -u root -p
Enter password:
mysql></pre>
MySQL is in place now, so let's get cracking at Ruby and Rails now.
<h3>Ruby, Gems, Rails</h3>
Installing Ruby is quite easy:
<pre lang="bash">$ sudo apt-get install ruby</pre>
You'll now have Ruby 1.8.5. You will also need to install some other develoment package to help you build native Ruby Gems.
<pre lang="bash">$ sudo apt-get install make autoconf gcc ruby1.8-dev build-essentials</pre>
I'll install ruby gems the conventional way (so I'm not going to use Ubuntu's packages here). Download the <a href="http://rubyforge.org/frs/?group_id=126">latest Gems .tgz here</a>.
<pre lang="bash">$ wget http://rubyforge.org/frs/download.php/17190/rubygems-0.9.2.tgz
$ tar xvf rubygems-0.9.2.tgz
$ cd rubygems-0.9.2/
$ sudo ruby setup.rb
$ gem -v</pre>
That's it for the gems. Now, install Rails an all it's dependencies:
<pre lang="bash">$ sudo gem install rails --include-dependencies</pre>
If you get an error message complaining that the 'rails' gem cannot be found include the --remote option.
<h3>Oh no! More gems!</h3>
Next, let's install some essential Ruby Gems that will make your life quite a bit easier. Here we'll install the following gems:
<ul>
<li>mysql - For good MySQL connectivity</li>
<li>capistrano - Just to have it handy when needed</li>
<li>mongrel - Rails server</li>
<li>mongrel-cluster - To operate mongrel clusters</li>
</ul>
<pre lang="bash">$ sudo gem install mysql capistrano mongrel mongrel-cluster --include-dependencies</pre>
You'll be asked several times to choose a version for different gems. Always choose the latest available version for 'ruby'. (Don't choose win32. I don't need to explain why.)
<h3>Test Rails and MySQL operability</h3>
Before you continue you may want to take some time to test Rails and MySQL. It's not essential, but I recommend it because it will save you a lot of trouble later on.
Create a new Rails application in your homedir and a create the corresponding MySQL database. Also edit config/database.yml to reflect your root password!
<pre lang="bash">$ mysqladmin -u root -p create testapp_development
$ mkdir testapp
$ rails testapp
$ cd testapp
$ vi config/database.yml
$ rake db:migrate</pre>
If you get any errors from that last command, check the previous steps. Normally, all should be fine and you can continue safely.
Most people configure a 'socket' in their config/database.yml for MySQL. Note that this socket is in different places for different distribution. Ubuntu and Debian keep it in: /var/run/mysqld/mysqld.sock. You may need to update your configuration in order to connect to the database.
<h3>Apache 2.2</h3>
The good thing about Ubuntu/Debian is that they both include Apache 2.2.x now. This branch of Apache includes the a balancing proxy, which allows you to distribute your workload over several Mongrel servers (in your mongrel cluster). I'll come back to that later.
<pre lang="bash">$ sudo apt-get install apache2</pre>
Before you continue, enable several modules which we'll be using later on.
<pre lang="bash">$ sudo a2enmod proxy_balancer
$ sudo a2enmod proxy_ftp
$ sudo a2enmod proxy_http
$ sudo a2enmod proxy_connect
$ sudo a2enmod rewrite</pre>
That's it for now on Apache. Let's move along.
<h3>Prepping the Rails application</h3>
Okay, let's prepare the Rails application 'myapp' for deployment now, shall we?
First, create a production database on your server, and configure it in config/database.yml:
<pre lang="bash">$ mysql -u root -p
> create database myapp_production;
> grant all privileges on myapp_production.* to 'myapp'@'localhost'
identified by 'secret_password'</pre>
The next step is to install capistrano. You can install it on your development machine as a gem, as demonstrated above. Next, apply capistrano to your application:
<pre lang="bash">$ sudo gem install capistrano
$ cap --apply-to myapp</pre>
Take a look at myapp/config/deploy.rb. This file contains the configuration for the deployment of your application. Take special care of the following, here's an example for 'myapp':
<pre lang="ruby">require 'mongrel_cluster/recipes'
set :application, "myapp"
set :repository, "http://svn.myhost.com/svn/#{application}/trunk"
# We only have one host
role :web, "myapp.com"
role :app, "myapp.com"
role :db, "myapp.com", :primary => true
# Don't forget to change this
set :deploy_to, "/home/ariejan/apps/#{application}"
set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml"</pre>
As you can see, I've already included several lines that enable the use of mongrel, we'll get to that next.
Make sure you adapt this file to your own needs. myapp.com is the address of the server you're going to deploy your application to. the mongrel_cluster.yml file will be created in a moment.
On the server, make sure you create the 'apps' directory. You can now setup a basic file structure for the deployment:
<pre lang="bash">$ cd myapp
$ cap setup</pre>
On your server, you'll notice that the /home/ariejan/apps/myapp directory was created, including some subdirectories.
If you are annoyed with entering your SSH password every time, create and upload your public SSH key to automate this. (I'll write something up about that later on.)
Now, configure mongrel. For a normal setup, with moderate traffic, you can handle all traffic with two mongrel instances. The mongrel servers will only be accessable through 'localhost' on the server on non-default ports. Apache will do the rest later.
In your rails app, run the following command:
<pre lang="bash">$ mongrel_rails cluster::configure -e production -p 9000 \
-a 127.0.0.1 -N 2 -c /home/ariejan/apps/myapp/current</pre>
The configuration file we saw earlier has been created. Check-in all new files in to subversion now, and cold deloy your application!
<pre lang="bash">$ cap cold_deploy</pre>
The deployment will checkout the most recent code from Subversion and start the mongrel servers.
After the deployment, migrate your production database and restart the mongrel cluster:
<pre lang="bash">$ cap migrate
$ cap restart</pre>
To check that your application is running, issue the following command on your server. It should return you the HTML code from your app:
<pre lang="bash">$ curl -L http://127.0.0.1:9000</pre>
<h3>Configure Apache and the Balacing Proxy</h3>
You have two mongrel servers running, ready to handle incoming requests. But, you want your visitors to use 'myapp.com' and not an IP address with different port numbers. This is where apache comes in.
Create a new file in /etc/apache2/sites-availbale named 'myapp' and add the following:
<pre lang="apache">
<proxy>
BalancerMember http://127.0.0.1:9000
BalancerMember http://127.0.0.1:9001
</proxy>
<virtualhost>
ServerName myapp.com
ServerAlias www.myapp.com
DocumentRoot /home/ariejan/apps/myapp/current/public
<directory>
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</directory>
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]
RewriteRule ^/$ /index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://myapps_mongrel_cluster%{REQUEST_URI} [P,QSA,L]
ErrorLog /home/ariejan/apps/myapps/shared/log/tankfactions_errors_log
CustomLog /home/ariejan/apps/myapps/shared/log/tankfactions_log combined
</virtualhost></pre>
Now enable this new site in apache:
<pre lang="bash">$ sudo a2ensite myapp
$ /etc/init.d/apache2 force-reload</pre>
In some cases you may need to make a small change to /etc/apache2/mods-enabled/proxy.conf and swap
<pre>Order deny,allow
Deny from all</pre>
for
<pre>Order allow,deny
Allow from all</pre>
That's all, you can now access your app on myapp.com!
<h3>Maintaining your application</h3>
Now, happily develop your application and make update (you check them in to Subversion). To update your web server run:
<pre lang="bash">$ cap deploy</pre>
If you made changes in the database, you may want to run a long_deploy:
<pre lang="bash">$ cap long_deploy</pre>
And if for some reason, your mongrel cluster dies, just restart it.
<pre lang="bash">$ cap restart</pre>
That's it! Happy hacking :)
<strong><a href="http://digg.com/programming/Rails_production_server_setup_and_deployment_on_Ubuntu_Debian">Please digg this story</a> to help spread the word! Thanks a lot!</strong>
<em>Comments can be posted here or in my new and shiny <a href="http://groups.google.com/group/ariejannet">Google Group</a>!</em>

View File

@ -0,0 +1,13 @@
+++
date = "2007-06-21"
title = "AJAX Rules! 80 JavaScript Solutions for professional coding"
tags = ["General", "Blog", "Web Development", "Links"]
slug = "ajax-rules-80-javascript-solutions-for-professional-coding"
+++
Smashing Magazine has put together a very comprehensive list of <a href="http://www.smashingmagazine.com/2007/06/20/ajax-javascript-solutions-for-professional-coding/">80 AJAX JavaScript solutions for professional coding</a>. How great is that?!
The list includes solutions for auto-completion, inline editing, menus, tabs, calendars, all sorts of interactive stuff and tables, charts, graphs, forms, grids, lightboxes, galleries, showcases, visual effects and also, some basic JavaScripts that everybody should know about.
Check out <a href="http://www.smashingmagazine.com/2007/06/20/ajax-javascript-solutions-for-professional-coding/">the list</a> now!

View File

@ -0,0 +1,81 @@
+++
date = "2007-07-01"
title = "ActiveScaffold + acts_as_taggable + Auto Complete"
tags = ["General", "RubyOnRails", "Features"]
slug = "activescaffold-acts_as_taggable-auto-complete"
+++
I've talked before on how to use <a href="http://ariejan.net/2007/06/11/activescaffold-acts_as_taggable_on_steroids/">ActiveScaffold with acts_as_taggable_on_steroids</a>.
The problem with that solution was that, although the checkboxes for every tag are very nice, you couldn't easily add new tags. For some people, this may be fine, for others, it is not.
Together with a colleague (who wishes not to be named), I found a solution that is quite elegant. Instead of using check boxes, and creating all kinds of subforms in ActiveScaffold, we opted for an auto_completing, comma-separated list of tags.
This article descripes the solution we found. I think you'll like it very much!
<!--more-->
When you try to use acts_as_taggable with ActiveScaffold, you might use something like this in your BooksController.
<pre lang="ruby">active_scaffold :books do |config|
config.columns = [:title, :body, :tags]
config.list.columns = [:title, :tag_list]
config.columns[:tags].ui_type = :select
# ...
end</pre>
This is not so useful when you want the flexibility of creating new tags instantly. Therefore, it's better to use the tag_list:
<pre lang="ruby">active_scaffold :books do |config|
config.columns = [:title, :body, :tag_list]
config.list.columns = [:title, :tag_list]
# ...
end</pre>
You get a text_field for writing down the tags (comma-separated). The problem of this is that the user has to keep all the tags in mind and is not allowed to make any typos in the tag. To help our users out, I use Rails' auto_complete feature.
In your BooksController:
<pre lang="ruby">auto_complete_for :book, :tag_list
def autocomplete_tag_list
@all_tags = Tag.find(:all, :order => 'name ASC')
re = Regexp.new("^#{params[:record][:tag_list]}", "i")
@tags = @all_tags.find_all do |t|
t.name.match re
end
render :layout => false
end</pre>
We can now create the template for the results which are found.
In app/views/books/autocomplete_tag_list.rhtml:
<pre lang="html">
<ul class="autocomplete_list">
<% @tags.each do |t| %>
<li class="autocomplete_item"><%= t %></li>
<% end %></ul>
</pre>
Now comes the difficult part, integration of the auto_complete widget within ActiveScaffold.
ActiveScaffold has the possibility to change the way every attribute is displayed on the create and edit page. I want to change the form for the attribute 'tag_list'. To do this, I create create a file named app/views/books/_tag_list_form_column.rhtml:
<pre lang="html">
<dl>
<dt>
<label for="record_tag_list">AutoCompleted Tag List</label>
</dt>
<dd>
<%= text_field_tag 'record[tag_list]', @record.tag_list %>
<p class="auto_complete" id="record_tag_list_<%=@record[:id]%>_auto_complete">
style="{height: 80px;}">
<script type="text/javascript">
//<![CDATA[
var record_tag_list_<%= @record[:id].to_s %>_auto_completer =
new Ajax.Autocompleter(
\'record[tag_list]\',
\'record_tag_list_<%=@record[:id]%>_auto_complete\',
\'/articles/autocomplete_tag_list\', {tokens: \',\'});
//]]>
</script>
</dd>
</dl></pre>
This shows a text field and generates a div that contains the available tags that we can show to the user. To populate the list of tags we use Ajax.Autocompler, which requires three arguments: the id of the text_field; the id of the div where you want to show possible tags to the user; and third, the URL of the action we created before, that returns the proper tags.
The 'tokens' part of the last argument indicates that the user can seperate multiple tags with a comma. So, if you've entered one tag, added a comma and start typing a new tag, the auto complete feature will only lookup that second tag you're typing!
That's it. Just spice things up a bit with some Style, and you're done. Enjoy!

View File

@ -0,0 +1,33 @@
+++
date = "2007-07-02"
title = "How to force data to be downloaded as a file from your Rails app"
tags = ["General", "RubyOnRails", "Features"]
slug = "how-to-force-data-to-be-downloaded-as-a-file-from-your-rails-app"
+++
In the essence of every application is data. One way or another your application manages data and at some point, you need to get that data out. Either you want to synchronize the data with another application or device. Or you want to move your data to another system all together. Either way, you'll need to gather your data and send it from your application to the client... as a file.
Downloading files is not the hardest thing around. But the problem is that some formats, like XML, are automatically parsed by the browser and this makes it harder for users to download files like that.
So, what you want to do is, ignore the browser and offer your data (in XML or whatever format you want) as a file that can be downloaded directly. The solution is rather easy, as always with Rails.
<!--more-->
Okay, in this example I have an action that renders current 'entries' as XML and offers this to the user:
<pre lang="ruby">def export_to_xml
@entries = Entry.find(:all)
render :xml => @entries.to_xml
end</pre>
This works as you'd expect it to. When calling this action, the user receives a XML file containing all entries. But really, do you want that in your browser? Especially when the XML file is rather large, this can be very annoying, because your browser will want to load it all in!
What you want here is offer the users a file named 'entries.xml' for download. In this case we use Rails' send_data method. The previous action now looks like this:
<pre lang="ruby">def export_to_xml
@entries = Entry.find(:all)
send_data @entries.to_xml,
:type => 'text/xml; charset=UTF-8;',
:disposition => "attachment; filename=entries.xml"
end</pre>
It's clear that we send the XML data to the client. I specify the type and charset of the data with the 'type' paramater. This way the browser knows what is being send and allows the user to choose an application that can use the data. In this case an XML reader, for example.
The disposition parameter tells the browser this should be downloaded as a file (or attachment). It also specifies what the name of the attachment is, 'entries.xml'.
Now, link to this method and the user will be presented with a downloadable XML file.

View File

@ -0,0 +1,21 @@
+++
date = "2007-07-03"
title = "Got updates?"
tags = ["General", "Ariejan.net", "Blog"]
slug = "got-updates"
+++
Do you want to stay up-to-date about what's happening at Ariejan.net? That's real easy!
You can subscribe to my <a href="http://feeds.feedburner.com/Ariejan">RSS Feed</a> and receive updates as they happen in your favourite RSS reader.
If you don't have an RSS reader (or don't want one), you can subscribe to my e-mail service. This service will gather up all the posts of the previous day (if any) and send them to you between 7am and 9am (CET).
Interested? Sign-up now!
<form style="border: 1px solid #cccccc; padding: 3px; text-align: center" action="http://www.feedburner.com/fb/a/emailverify" method="post" target="popupwindow" onsubmit="window.open('http://www.feedburner.com', 'popupwindow', 'scrollbars=yes,width=550,height=520');return true">Enter your email address:
<input style="width: 340px" name="email" type="text" /> <input value="http://feeds.feedburner.com/~e?ffid=411105" name="url" type="hidden" /> <input value="Ariejan.net" name="title" type="hidden" /> <input name="loc" value="en_US" type="hidden" /> <input value="Subscribe" type="submit" />Delivered by <a href="http://www.feedburner.com" target="_blank">FeedBurner</a>
</form>Or grab the <a href="http://feeds.feedburner.com/Ariejan">RSS Feed</a>.

View File

@ -0,0 +1,41 @@
+++
date = "2007-07-03"
title = "How to create and apply a patch with Subversion"
tags = ["General", "Features", "Subversion"]
slug = "how-to-create-and-apply-a-patch-with-subversion"
+++
It's been a while since I posted something new on the use of Subversion. I've been working with the tool a lot, and I've found that patches are a great way to communicate code changes.
For those of you who are still learning, let me first explain what a patch is. A patch is a text file that contains the alteration that were made to a specific file. It includes the lines that have been removed and the lines that have been added. In short, if you have a ruby script and edited it, you could create a patch file, containing the changes you've made.
Why is this useful? You could check in your changes to your repository directly. True, but there are cases that you don't have write access to the repository. For example, if you wanted to contribute code changes to <a href="http://trac.ariejan.net/rails-plugins/wiki/ActsAsExportable">Acts As Exportable</a>, you should create a new ticket and attach a patch file. I will then review your changes before I apply them to the code and commit them to the repository.
So, how do you go about creating a patch file and how do you later apply it to your source?
~
### Creating a patch file
Creating a patch file is really easy. First, check out the most recent version of the code from Subversion using the 'checkout' command.
Make your changes.
Then, in the root the project run the following command. It will store the patch file in your home directory. Make sure to give it meaningful filename.
svn diff > ~/fix_ugly_bug.diff
The file has the .diff extention, which stands for <em>diff</em>erences. This extension is recognized by many text editors and enables 'syntax highlighting' automatically. (Give it a try with TextMate and you'll know what I mean.)
You can send the diff-file to the author of the project by email, or you can create a ticket in Trac and add it as an attachment. The author will review the changes you made and possibly apply them to the source.
### Applying a patch
You should never apply patches from any person other than your development team without first reading through the changes, apply them locally and test your application and then commit them. Patches can not only include bug fixes, but also alterations to create back doors or add other exploits to your code.
<strong>Always read through a patch before applying it!</strong>
When you are sure the patch will bring no harm to you, your application or your customers, go ahead an apply it to your working copy. Here, I assume that you downloaded the patch file we previously generated, and placed it in your home directory. In the root of your application now run:
patch -p0 -i ~/fix_ugly_bug.diff
This will apply all the changes in the patch to your source. The -p0 option makes sure that all files can be found correctly (this has to do with something called 'zero directories', I won't get into that right now). The -i option tells 'patch' what to use as input, in this case the 'fix_ugly_bug.diff' file in your home directory.
With the code changes in place, run your tests and make sure everything works as expected. If it does, commit your changes and celebrate with a cup of coffee.

View File

@ -0,0 +1,91 @@
+++
date = "2007-07-04"
title = "How to resolve Subversion Conflicts"
tags = ["Subversion", "conflicts"]
slug = "how-to-resolve-subversion-conflicts"
+++
If there's more than one person working on a project, chances are (although slim) that at some point two developers work on the same piece of code and check it in. To clarify, let me give you an example.
The repository is currently at revision 5 and contains a file named 'README'. Revision 5 of that file contains a single line: 'This is a README file'.
Now, both you and your colleague check out r5 and edit README. Your colleague changes the line to 'This is a documentation file' and commits it back to the repository, which is bumped to revision 6.
You're an island, and have no clue about the new revision being created. You just happily write away and change the README file to: 'This is fun stuff!'.
When you commit your changes, you'll get an error message:
$ svn commit -m "Updated README"
Sending README
Transmitting file data .svn: Commit failed (details follow):
svn: Out of date: '/myproject/README'
~
This is good. Subversion has detected that the file you want to commit has changed since you last updated it. Update the file to get it up-to-date again.
$ svn update
C README
Updated to revision 6.
The 'C' indicates there is a conflict with the README file, and Subversion does not know how to solve this. You are called in to help.
If you now take a look at README, you'll notice that there are several markers that indicate what parts of the code are conflicting. You can easily see what you changed, and what has changed in the repository:
<<<<<<< .mine
This is fun stuff!
=======
This is a documentation file
>>>>>>> .r6
<h3>What are your options?</h3>
You have three options for resolving the conflict. Whatever you choose, make sure you confer with your colleague on the matter.
<em>1. Scrap your changes, and go with the current work from your colleague.</em>
This is the easiest solution. All you have to do is revert the changes you made, and update your working copy:
$ svn revert README
Reverted 'README'
$ svn update README
At revision 6.
<em>2. Keep your changes, and dump whatever your colleague did.</em>
Performing a simple 'ls' will show you that there are four files related to this conflict:
<ul>
<li>README the original with markers</li>
<li>README.mine your version</li>
<li>README.r5 the original your worked with</li>
<li>README.r6 the most update version from your colleague</li>
</ul>
To check in your changes, copy your version over the original and tell Subversion you have resolved the conflict.
$ cp README.mine README
$ svn resolved README
Resolved conflicted state of 'README'
The 'resolved' command will clean up all the special files that were generated.
<em>3. Merge both version to a new version</em>
If you choose this option, you will have to manually edit README. Remove the markers and add whatever you need to add here.
Subversion won't let you commit this file, so you'll have to mark it as 'resolved' as we saw during option 2:
$ svn resolved README
Resolved conflicted state of 'README'
<em>Before you rush ahead</em>
With option 1, you're done. With options 2 and 3 there is some more work to do, because you didn't commit your changes yet. Because we're dealing with conflicts here, I recommend you don't just commit to your repository, but follow a slightly different route.
First, update your working copy (again) to make sure you have all the latest, and are not trying to check in any more conflicting code. If any conflicts pop-up, fix these first.
Now, run your tests to make sure everything is working as it should.
When all is clear, commit your changes to your repository as you normally would.
Done. Problem solved.

View File

@ -0,0 +1,187 @@
+++
date = "2007-07-06"
title = "How to write a Rails Plugin (for controllers)"
tags = ["General", "RubyOnRails", "Features"]
slug = "how-to-write-a-rails-plugin-for-controllers"
+++
A few days back I posted my very first Rails plugin, <a href="http://ariejan.net/2007/07/03/rails-plugin-acts-as-exportable/">Acts As Exportable</a>. Although writing a plugin is rather easy, you must know a few tricks on how to get things going.
This article will show you how to develop a plugin that adds functionality to a <em>controller</em> (other plugins, e.g. for models) will follow later. In fact, I'll explain to you how I developed my Acts As Exportable plugin.
Let's take a basic Rails application for starters. You have setup a model with some attributes and a scaffolded controller that allows you to CRUD your items. In this tutorial I'll be working with books. The model is named 'Book' and the controller 'BooksController'. Start your web server now and add some random data to play with.
Before you dive into writing a plugin for the controller to export data to XML you should have some basic functionality in your controller first. I've found it easier to develop my code in the controller first, and then port it to a plugin.
<!--more-->
So, add a new method to your BooksController that'll export books to XML. This looks quite easy:
<pre lang="ruby">def export_to_xml
books = Book.find(:all, :order => 'title')
send_data books.to_xml,
:type => 'text/xml; charset=UTF-8;',
:disposition => "attachment; filename=books.xml"
end</pre>
Now, call /books/export_to_xml and you download a real XML file containing all your books! To make things a bit more complicated, we want to be able to feed this method some conditions to select books. A nice solution is to add a special method for this that defines these conditions. (You could also use them in listing books, for example.) I add a new method to the BooksController:
<pre lang="ruby">def conditions_for_collection
['title = ?', 'some title!']
end</pre>
The condition is of the same format you can feed to <em>find</em>. Here you could, for example, select only the books belonging to the currently logged in user.
Next, update the export_to_xml method to use these conditions
<pre lang="ruby">def export_to_xml
books = Book.find(:all, :order => 'title', :conditions => conditions_for_collection)
send_data books.to_xml,
:type => 'text/xml; charset=UTF-8;',
:disposition => "attachment; filename=books.xml"
end</pre>
Nice that's it. Now, you like what you've made so far, and want to stuff it into a plugin and put it on your weblog. Here's how to go about that.
<h3>Creating the plugin</h3>
First, generate the basic code for a plugin:
<pre>./script/generate plugin acts_as_exportable</pre>
This will create a new directory in vendor/plugins containing all the basic files you need. First, we'll take a look at vendor/plugins/acts_as_exportable/lib/acts_as_exportable.rb. This is where all the magic happens.
What we want is to is add a method to ActionControllerBase that allows you to easily enable the plugin in a certain controller. So, how do you want to activate the plugin? Right, you just call 'acts_as_exportable' from the controller, or optionally, you add the name of the model you want to use.
<pre lang="ruby">acts_as_exportable
acts_as_exportable :book</pre>
The vendor/plugins/acts_as_exportable/lib/acts_as_exportable.rb contains a module that's named after our plugin:
<pre lang="ruby">module ActsAsExportable
end</pre>
Next, we add a module named 'ClassMethods'. These class methods will be added to ActionController::Base when the plugin is loaded (we'll take care of that in a moment), and enable the functionality described above.
<pre lang="ruby">module ActsAsExportable
def self.included(base)
base.extend(ClassMethods)
end
class Config
attr_reader :model
attr_reader :model_id
def initialize(model_id)
@model_id = model_id
@model = model_id.to_s.camelize.constantize
end
def model_name
@model_id.to_s
end
end
module ClassMethods
def acts_as_exportable(model_id = nil)
# converts Foo::BarController to 'bar' and FooBarsController
# to 'foo_bar' and AddressController to 'address'
model_id = self.to_s.split('::').last.sub(/Controller$/, '').\
pluralize.singularize.underscore unless model_id
@acts_as_exportable_config = ActsAsExportable::Config.\
new(model_id)
include ActsAsExportable::InstanceMethods
end
# Make the @acts_as_exportable_config class variable easily
# accessable from the instance methods.
def acts_as_exportable_config
@acts_as_exportable_config || self.superclass.\
instance_variable_get('@acts_as_exportable_config')
end
end
end</pre>
So, what happened? The first method you see extends the current class (that's every one of your controllers with the methods from the ClassMethods module).
Every class now has the 'acts_as_exportable' method available. What does it do? The plugin automatically grabs the name of the model associated (by convention) with the controller you use, unless you specify something else.
Next, we create a new configuration object that contains information about the model we're working with. Later on this can contain more detailed information like what attributes to include or exclude from the export.
Finally we include the module InstanceMethods, which we still have to define. The instance methods are only included when we enable the plugin. In our case, the instance methods include the 'export_to_xml' and 'conditions_for_collection' methods. We can simply copy/paste them into your plugin.
<pre lang="ruby">module InstanceMethods
def export_to_xml
data = Book.find(:all, :order => 'title', :conditions => conditions_for_collection)
send_data data.to_xml,
:type => 'text/xml; charset=UTF-8;',
:disposition => "attachment; filename=books.xml"
end
# Empty conditions. You can override this in your controller
def conditions_for_collection
end
end</pre>
Take note that we don't want to define any default conditions, because we don't know what model we're using here. By adding an empty method, the method is available and no conditions are used. Another developer can define 'conditions_for_collection' in his controller to override the one we write here.
In the 'export_to_xml' there are a few changes as well. First of all, I generalized 'books' to 'data'.
The most important step is yet to come. We have still application specific code in your plugin, namely the Book model. This is where the Config class and @acts_as_exportable_config come in.
We have added a class variable to the controller named @acts_as_exportable_config. By default, this variable is not accessable by instance methods, so we need a little work around:
<pre lang="ruby">self.class.acts_as_exportable_config</pre>
This will call the class method 'acts_as_exportable_config' we defined in ClassMethods and return the value of @acts_as_exportable_config.
Note that we store the configuration in each seperate controller. This allows acts_as_exportable to be used with more than one controller at the same time.
With the model name made application independent, the whole plugin code looks like:
<pre lang="ruby">module ActsAsExportable
def self.included(base)
base.extend(ClassMethods)
end
class Config
attr_reader :model
attr_reader :model_id
def initialize(model_id)
@model_id = model_id
@model = model_id.to_s.camelize.constantize
end
def model_name
@model_id.to_s
end
end
module ClassMethods
def acts_as_exportable(model_id = nil)
# converts Foo::BarController to 'bar' and FooBarsController to 'foo_bar'
# and AddressController to 'address'
model_id = self.to_s.split('::').last.sub(/Controller$/, '').\
pluralize.singularize.underscore unless model_id
@acts_as_exportable_config = ActsAsExportable::Config.new(model_id)
include ActsAsExportable::InstanceMethods
end
# Make the @acts_as_exportable_config class variable easily
# accessable from the instance methods.
def acts_as_exportable_config
@acts_as_exportable_config || self.superclass.\
instance_variable_get('@acts_as_exportable_config')
end
end
module InstanceMethods
def export_to_xml
data = self.class.acts_as_exportable_config.model.find(:all,
:order => 'title',
:conditions => conditions_for_collection)
send_data data.to_xml,
:type => 'text/xml; charset=UTF-8;',
:disposition => "attachment; filename=\
#{self.class.acts_as_exportable_config.model_name.pluralize}.xml"
end
# Empty conditions. You can override this in your controller
def conditions_for_collection
end
end
end</pre>
Add the following line to your BooksController and restart your web server. (Oh, and make sure to remove the export_to_xml method from the controller as well)
<pre lang="rails">acts_as_exportable</pre>
Done! Or not?
<h3>Enabling the plugin by default</h3>
We have a very nice plugin now, but it is not loaded by default! If you take a look at your plugin directory, you'll find a file named 'init.rb'. This file is executed when you (re)start your web server. This is the perfect place to add our class methods to the ActionController::Base. Just add the following three lines of code to 'init.rb':
<pre lang="ruby">ActionController::Base.class_eval do
include ActsAsExportable
end</pre>
When we include our module, the 'self.included' method is called, and the ClassMethods module is added, thus enabling the acts_as_exportable method.
That's all! Happy plugin writing!
Feel free to comment on this post and write about any of your own plugin (for controllers) experiences.

View File

@ -0,0 +1,13 @@
+++
date = "2007-07-06"
title = "Some DNS problems with Ariejan.net"
tags = ["General", "Ariejan.net", "Blog"]
slug = "some-dns-problems-with-ariejannet"
+++
This is just a quick note to let you know there are currently some issues with DNS for Ariejan.net. This basically means that Trac and SVN are currently not available. I've made the appropriate changes and things should be working again in a few hours.
I'm very sorry for the inconvenience.
<strong>Update: It appears that things are working again. If you have any issues with <a href="http://trac.ariejan.net/rails-plugins">Trac</a>, please let me know.</strong>

View File

@ -0,0 +1,27 @@
+++
date = "2007-07-07"
title = "Clear DNS Cache on your router"
tags = ["General", "Features", "Linux"]
slug = "clear-dns-cache-on-your-router"
+++
I currently have a Linksys router at home that has the <a href="http://www.dd-wrt.com/dd-wrtv2/index.php">DD-WRT Firmware</a> on it. I've been using it for quite some time now, and I'm very happy with it.
In my previous post I mentioned there was some trouble with DNS for Ariejan.net. I've changed nameservers and there's always something that goes wrong.
Anyway, my router runs DNSMasq, a caching nameserver for my local network. (What this does is, it stores DNS queries and when the same request is made later on, the response is already here (on my network), and my ISP's nameservers don't have to be queried. This makes for a great speed optimalization!)
The problem was, that my router was caching parts from the old and parts from the new nameservers for Ariejan.net. I could have waited 24-48 hours to let DNSMasq figure it all out by itself, but I'm not that patient. What I needed to was reset the cache DNSMasq had built.
<!--more-->
What you need to do is login to the admin panel of your router and enable SSH access (for your own network, not for the outside world!).
You SSH to your route, probably as the 'root' or 'admin' user. In this case the IP is your routers IP address.
<pre lang="bash">$ ssh -l admin 10.0.0.1</pre>
Once you're in, you can issue the killall command to issue the 'HUP' signal to DNSMasq. This does not kill your DNSMasq, but tells it to flush the cache an reread its configuration, thus starting over with a clean slate.
The 'HUP' signal has the number '1' so you can run the following command once logged in:
<pre lang="bash">$ killall -1 dnsmasq</pre>
Now you can logout, and notice that your cache was indeed cleared.
This method should work on every Linux based router that uses DNSMasq and support SSH logins.

View File

@ -0,0 +1,34 @@
+++
date = "2007-07-16"
title = "Ariejan.net - Whats next?"
tags = ["General", "Ariejan.net", "Blog"]
slug = "ariejannet-whats-next"
+++
<strong><a href="#whatsnext">Vote now! What's Next for Ariejan.net? Your opinion counts!</a></strong>
After a few days (or were it weeks?) of silence, an update on Ariejan.net. What's been happening?
First of all, I <a href="http://ariejan.net/2007/06/19/geslaagd-passed-my-final-exams/">recently graduated</a> and am now officially a Bachelor of ICT. Since my current employer didn't have the same views regarding my future as I did, I decided to go "shopping" for a new job.
I found that new job with a small business named <a href="http://www.kabisa.nl">Kabisa ICT</a>. The people at Kabisa and I found common ground very quickly with Ruby on Rails and Agile Development. This, to my surprise, resulted in a job offer very quickly... and I accepted.
The next two weeks I've got a holiday planned to the French Alps with Laura. We hope to get some rest there while enjoying the beautiful scenery.
When I get back from France, I start my new job at Kabisa. I hope to learn a lot of new stuff while working there. Hopefully I'll be able to share that experience with your here, at Ariejan.net, which leads me to the following question.
<strong>What's Next?</strong>
What's next for Ariejan.net? Since all the Web 2.0 buzz is all about communities and all that, I want your opinion on what to do with Ariejan.net.
<em>Please vote in the poll below and let me know what your thoughts are. When I get back from my (well earned) vacation, I'll check back here and see what you, my guests, really want.</em>
<em>You have the option of adding new stuff. Use it wisely, please!</em>
<a title="whatsnext" name="whatsnext"></a>
<div>{democracy:1}</div>
<!--more-->
<strong>Thanks for voting! It's greatly appreciated!</strong>

View File

@ -0,0 +1,19 @@
+++
date = "2007-08-01"
title = "Im Back!"
tags = ["General", "Ariejan.net", "Blog"]
slug = "im-back"
+++
All right, I'm back!
Yes, my holiday was nice. Thanks for asking. Now, I've been looking at the poll in my previous post and I've made up my mind.
1. I'm going to look into writing a blogging system in Ruby on Rails. I don't want to copy typo or Mephisto or anything, but just put my own thoughts together, add a bit of spice you guys (and girls?) have to offer and release it some time.
Just to be clear (and prevent myself from getting a lot of mail about this): I'm going to see if I can make time to work on a project like this. That's all. If I can, I'll let you know. If I can't.. well too bad, I guess :)
2. I'm going to, as I did before, write a lot of articles about Subversion and Ruby on Rails. Maybe I'll add some new topics too, but those will pop up when they do. Just keep an eye out for news here at Ariejan.net (tip: <a href="http://feeds.feedburner.com/Ariejan">grab my RSS Feed</a>).
<em>Also, I'm now available to do Ruby on Rails projects for real! Just <a href="/contact">contact me</a> and we can discuss details at your leisure.</em>

Some files were not shown because too many files have changed in this diff Show More