diff --git a/content/posts/2006-10-13-migrate-sqlite3-to-mysql-easily.md b/content/posts/2006-10-13-migrate-sqlite3-to-mysql-easily.md index 5d9f5c0..5b6e52f 100644 --- a/content/posts/2006-10-13-migrate-sqlite3-to-mysql-easily.md +++ b/content/posts/2006-10-13-migrate-sqlite3-to-mysql-easily.md @@ -9,15 +9,16 @@ I've been using a simple Rails application locally with a SQlite 3 database for 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] +``` shell +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. diff --git a/content/posts/2006-10-13-tagging-in-ajax_scaffold.md b/content/posts/2006-10-13-tagging-in-ajax_scaffold.md index 0d897a3..4cba283 100644 --- a/content/posts/2006-10-13-tagging-in-ajax_scaffold.md +++ b/content/posts/2006-10-13-tagging-in-ajax_scaffold.md @@ -4,31 +4,35 @@ title = "Tagging in ajax_scaffold" tags = ["General", "Everything", "Web Development", "RubyOnRails", "Features"] slug = "tagging-in-ajax_scaffold" +++ + I've been using the Ajax Scaffold for quite some time now. It's a great piece of software by Mr. Richard White for Ruby on Rails. 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 acts_as_taggable. 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 +``` ruby +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 +``` ruby +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 + @@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. @@ -38,22 +42,26 @@ Great! I now can see tags on disks! But, we also need to add those tags and that 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: +`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 +``` ruby +class Disk < ActiveRecord::Base + acts_as_taggable - validates_presence_of :name, :number + validates_presence_of :name, :number - def tag_list=(new_tags) - tag_with new_tags - end + 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. - - <%= text_field 'disk', 'tag_list' %> +``` erb + +<%= 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. diff --git a/content/posts/2006-10-31-wordpressmu-dont-allow-new-blogs.md b/content/posts/2006-10-31-wordpressmu-dont-allow-new-blogs.md index 66c4641..1584c37 100644 --- a/content/posts/2006-10-31-wordpressmu-dont-allow-new-blogs.md +++ b/content/posts/2006-10-31-wordpressmu-dont-allow-new-blogs.md @@ -4,20 +4,23 @@ title = "WordpressMu: Don’t allow new blogs" tags = ["General", "Everything", "Features", "WordPressMu"] slug = "wordpressmu-dont-allow-new-blogs" +++ + If you're using WordpressMu, the blog hosting tool used on Wordpress.com, 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(); - } +``` php +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. diff --git a/content/posts/2006-11-13-cups-426-upgrade-required.md b/content/posts/2006-11-13-cups-426-upgrade-required.md index 2361aac..9ccb961 100644 --- a/content/posts/2006-11-13-cups-426-upgrade-required.md +++ b/content/posts/2006-11-13-cups-426-upgrade-required.md @@ -7,19 +7,20 @@ 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** +> 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: -
DefaultEncryption Never
+``` text
+DefaultEncryption Never
+```
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
+``` shell
+/etc/init.d/cupsys restart
+```
and you're good to go.
-
-
-
diff --git a/content/posts/2006-11-15-ubuntu-610-live-dvd-on-the-apple-macbook.md b/content/posts/2006-11-15-ubuntu-610-live-dvd-on-the-apple-macbook.md
index ccc27b8..5cf0feb 100644
--- a/content/posts/2006-11-15-ubuntu-610-live-dvd-on-the-apple-macbook.md
+++ b/content/posts/2006-11-15-ubuntu-610-live-dvd-on-the-apple-macbook.md
@@ -30,7 +30,9 @@ 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
+``` shell
+sudo passwd ubuntu
+```
Now enter something that you'll remember easily, twice.
@@ -38,26 +40,30 @@ In order to get Ubuntu to recognize the native screen resolution automatically,
So, we now need to change /etc/apt/sources.list 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
+``` text
+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
+## 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
+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
+``` shell
+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.
diff --git a/content/posts/2006-11-21-svn-how-to-release-software-properly.md b/content/posts/2006-11-21-svn-how-to-release-software-properly.md
index 57f9356..f529101 100644
--- a/content/posts/2006-11-21-svn-how-to-release-software-properly.md
+++ b/content/posts/2006-11-21-svn-how-to-release-software-properly.md
@@ -9,13 +9,15 @@ Many projects use SubVersion nowadays to store their project code. I do this als
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.
+``` shell
+$ 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 Release Branch. 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.
@@ -23,8 +25,10 @@ Creating the release branch is really easy. Let's say I want to release version
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.
+``` shell
+$ 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 http://cse-tool.svn.sourceforge.net/viewvc/cse-tool/branches/ that the new release branch (RB-1.1.0) was created as a directory containing a copy of the current develoment code.
@@ -32,11 +36,15 @@ I can now do two things. Either I checkout a seperate working copy of the releas
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
+``` shell
+$ 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
+``` shell
+$ 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.
@@ -44,19 +52,22 @@ When you commit changes, they will be applied to the release branch only, render :update do |page|
+``` 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
+end
+```
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:
-link_to_remote "Check address",
+``` ruby
+link_to_remote "Check address",
:url {
:controller => 'locations',
:action => 'check_address',
:address => @location.address
},
- :method => :get
+ :method => :get
+```
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'.
@@ -36,17 +39,20 @@ You got it, JavaScript is your friend! You could now write a JS function that re
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:
-< %= javascript_include_tag 'prototype' %>
+``` erb
+<%= javascript_include_tag 'prototype' %>
+```
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!
-link_to_remote "Check address",
+``` ruby
+link_to_remote "Check address",
:url {
:controller => 'locations',
:action => 'check_address',
:address => @location.address
},
:with => "'address='+encodeURIComponent($F(
-
+```
diff --git a/content/posts/2007-03-27-subversion-how-to-revert-to-a-previous-revision.md b/content/posts/2007-03-27-subversion-how-to-revert-to-a-previous-revision.md
index 9ea2fc5..24a19ed 100644
--- a/content/posts/2007-03-27-subversion-how-to-revert-to-a-previous-revision.md
+++ b/content/posts/2007-03-27-subversion-how-to-revert-to-a-previous-revision.md
@@ -6,7 +6,9 @@ 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 .
+``` shell
+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!
diff --git a/content/posts/2007-04-03-tipsnippet-create-a-rss-feed.md b/content/posts/2007-04-03-tipsnippet-create-a-rss-feed.md
index 283ad74..2a2b2e0 100644
--- a/content/posts/2007-04-03-tipsnippet-create-a-rss-feed.md
+++ b/content/posts/2007-04-03-tipsnippet-create-a-rss-feed.md
@@ -8,20 +8,30 @@ 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.
-
+
You'll first need to add a new collection to your resource in config/routes.rb
-map.resources :articles, :collections => {:rss => :get}
+
+``` ruby
+map.resources :articles, :collections => {:rss => :get}
+```
+
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.
-def rss
+
+``` ruby
+def rss
@articles = Article.find(:all, :limit => 10, :order => 'created_at DESC')
render :layout => false
-end
+end
+```
+
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
-xml.instruct! :xml, :version=>"1.0"
+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`
+
+``` text
+xml.instruct! :xml, :version=>"1.0"
xml.rss(:version=>"2.0"){
xml.channel{
xml.title("My Great Blog")
@@ -39,10 +49,16 @@ xml.rss(:version=>"2.0"){
end
end
}
-}
+}
+```
+
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.)
-< %= auto_discovery_link_tag(:rss, :controller => 'articles', :action => 'rss') %>
+
+``` erb
+<%= auto_discovery_link_tag(:rss, :controller => 'articles', :action => 'rss') %>
+```
+
Share and enjoy! Thank you.
diff --git a/content/posts/2007-04-12-rails-resources-and-permalinks.md b/content/posts/2007-04-12-rails-resources-and-permalinks.md
index b998722..0550235 100644
--- a/content/posts/2007-04-12-rails-resources-and-permalinks.md
+++ b/content/posts/2007-04-12-rails-resources-and-permalinks.md
@@ -6,48 +6,76 @@ 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!
-
+
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:
-t.column :title, :string
+
+``` ruby
+t.column :title, :string
t.column :permalink, :string
-t.column :content, :text
+t.column :content, :text
+```
+
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:
-$ cd railsapp
-$ ./script/plugin install http://svn.techno-weenie.net/projects/plugins/permalink_fu/
+
+``` shell
+cd railsapp
+./script/plugin install http://svn.techno-weenie.net/projects/plugins/permalink_fu/
+```
+
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.
-has_permalink :title
+
+``` ruby
+has_permalink :title
+```
+
That's it for generating the appropriate permalink string in your database.
Rails goodness has already provided you with the basic RESTful routes:
+
map.permalink 'page/:permalink', :controller => 'pages', :action => 'permalink'
-map.connect 'page/:permalink.:format', :controller => 'pages', :action => 'permalink', :format => nil
+
+``` ruby
+map.permalink 'page/:permalink', :controller => 'pages', :action => 'permalink'
+map.connect 'page/:permalink.:format', :controller => 'pages', :action => 'permalink', :format => nil
+```
+
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:
-permalink_url(@page.permalink)
+
+``` ruby
+permalink_url(@page.permalink)
+```
+
The second link is unnamed, and allows you to specify a format like HTML or XML.
The permalink action looks like this:
-# GET /page/perma-link
+
+``` ruby
+# GET /page/perma-link
# GET /page/permal-link.xml
def permalink
@page = Page.find_by_permalink(params[:permalink])
@@ -56,7 +84,9 @@ def permalink
format.html { render :action => 'show' }
format.xml { render :xml => @page.to_xml }
end
-end
+end
+```
+
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.
diff --git a/content/posts/2007-06-11-activescaffold-acts_as_taggable_on_steroids.md b/content/posts/2007-06-11-activescaffold-acts_as_taggable_on_steroids.md
index fa2fb5c..fb10a45 100644
--- a/content/posts/2007-06-11-activescaffold-acts_as_taggable_on_steroids.md
+++ b/content/posts/2007-06-11-activescaffold-acts_as_taggable_on_steroids.md
@@ -16,7 +16,7 @@ The best example of this is an Article, where you can select the author (the ass
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.
-
+
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.
@@ -24,11 +24,15 @@ In your ArticlesController you specify which columns to show. "tag_list" is a st
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.
-active_scaffold :article do |config|
+
+``` 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
+end
+```
+
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.
@@ -36,23 +40,31 @@ As you may have noticed, the tags are not saved. Why? Acts_as_taggable adds a 't
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:
-private
+
+``` 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
+end
+```
+
And add two protected methods that extend the functionality of ActiveScaffold:
-protected
+
+``` ruby
+protected
def before_create_save(record)
- record.tag_list = new_tag_list(params[:record][:tags])
+ 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
+ record.tag_list = new_tag_list(params[:record][:tags])
+end
+```
+
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.
diff --git a/content/posts/2007-06-20-action-mailer-all-mail-comes-from-mailer-daemon.md b/content/posts/2007-06-20-action-mailer-all-mail-comes-from-mailer-daemon.md
index 581dfa1..c372d89 100644
--- a/content/posts/2007-06-20-action-mailer-all-mail-comes-from-mailer-daemon.md
+++ b/content/posts/2007-06-20-action-mailer-all-mail-comes-from-mailer-daemon.md
@@ -5,16 +5,26 @@ 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:
-class UserNotifier < ActionMailer::Base
+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:
+
+``` ruby
+class UserNotifier < ActionMailer::Base
protected
def setup_email(user)
@recipients = "#{user.email}"
- @from = "My Application
+ @from = "My Application ">
end
-end
+end
+```
+
May you spotted the problem already, but I didn't. All the mail sent came from "MAILER DAEMON".
-From: MAILER DAEMON+ +``` text +From: MAILER DAEMON +``` + 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. diff --git a/content/posts/2007-06-20-rails-production-server-setup-and-deployment-on-ubuntudebian.md b/content/posts/2007-06-20-rails-production-server-setup-and-deployment-on-ubuntudebian.md index 7d31bd2..d5d73dc 100644 --- a/content/posts/2007-06-20-rails-production-server-setup-and-deployment-on-ubuntudebian.md +++ b/content/posts/2007-06-20-rails-production-server-setup-and-deployment-on-ubuntudebian.md @@ -23,95 +23,182 @@ I assume that you have just installed a fresh system with Ubuntu Linux 7.04 or D 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. - +
sudo apt-get update
-sudo apt-get dist-upgrade
+
+``` shell
+sudo apt-get update
+sudo apt-get dist-upgrade
+```
+
This probably installs a new kernel (linux-kernel) so a reboot may be in order for optimal performance.
+
$ sudo apt-get install openssh-server openssh-client
+
+``` shell
+sudo apt-get install openssh-server openssh-client
+```
+
You will now be able to login remotely wiht SSH.
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.
+
$ sudo apt-get install subversion
+
+``` shell
+sudo apt-get install subversion
+```
+
We only need the client on the production server. We're not going to host Subversion repositories here.
+
$ sudo apt-get install mysql-server mysql-client libmysqlclient15-dev
+
+``` shell
+sudo apt-get install mysql-server mysql-client libmysqlclient15-dev
+```
+
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.
-$ mysqladmin -u root -h localhost password 'secret'
-$ mysqladmin -u root -h myhostname password 'secret'
+
+``` shell
+mysqladmin -u root -h localhost password 'secret'
+mysqladmin -u root -h myhostname password 'secret'
+```
+
Make sure to replace secret with your actual password.
Try logging in to MySQL with your new password to make sure everything works okay.
-$ mysql -u root -p
+
+``` shell
+mysql -u root -p
Enter password:
-mysql>
+mysql>
+```
+
MySQL is in place now, so let's get cracking at Ruby and Rails now.
+
$ sudo apt-get install ruby
+
+``` shell
+sudo apt-get install ruby
+```
+
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.
-$ sudo apt-get install make autoconf gcc ruby1.8-dev build-essentials
+
+``` shell
+sudo apt-get install make autoconf gcc ruby1.8-dev build-essentials
+```
+
I'll install ruby gems the conventional way (so I'm not going to use Ubuntu's packages here). Download the latest Gems .tgz here.
-$ wget http://rubyforge.org/frs/download.php/17190/rubygems-0.9.2.tgz
+
+``` shell
+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
+$ gem -v
+```
+
That's it for the gems. Now, install Rails an all it's dependencies:
-$ sudo gem install rails --include-dependencies
+
+``` shell
+sudo gem install rails --include-dependencies
+```
+
If you get an error message complaining that the 'rails' gem cannot be found include the --remote option.
+
$ sudo gem install mysql capistrano mongrel mongrel-cluster --include-dependencies
+
+``` shell
+sudo gem install mysql capistrano mongrel mongrel-cluster --include-dependencies
+```
+
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.)
+
$ mysqladmin -u root -p create testapp_development
+
+``` shell
+mysqladmin -u root -p create testapp_development
$ mkdir testapp
$ rails testapp
$ cd testapp
$ vi config/database.yml
-$ rake db:migrate
+$ rake db:migrate
+```
+
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.
+
$ sudo apt-get install apache2
+
+``` shell
+sudo apt-get install apache2
+```
+
Before you continue, enable several modules which we'll be using later on.
-$ sudo a2enmod proxy_balancer
-$ sudo a2enmod proxy_ftp
-$ sudo a2enmod proxy_http
-$ sudo a2enmod proxy_connect
-$ sudo a2enmod rewrite
+
+``` shell
+sudo a2enmod proxy_balancer
+sudo a2enmod proxy_ftp
+sudo a2enmod proxy_http
+sudo a2enmod proxy_connect
+sudo a2enmod rewrite
+```
+
That's it for now on Apache. Let's move along.
+
$ mysql -u root -p
-> create database myapp_production;
-> grant all privileges on myapp_production.* to 'myapp'@'localhost'
-identified by 'secret_password'
+
+``` shell
+mysql -u root -p
+```
+
+``` sql
+create database myapp_production;
+grant all privileges on myapp_production.* to 'myapp'@'localhost'
+identified by 'secret_password';
+```
+
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:
-$ sudo gem install capistrano
-$ cap --apply-to myapp
+
+``` shell
+sudo gem install capistrano
+cap --apply-to myapp
+```
+
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':
-require 'mongrel_cluster/recipes'
+
+``` ruby
+require 'mongrel_cluster/recipes'
set :application, "myapp"
set :repository, "http://svn.myhost.com/svn/#{application}/trunk"
# We only have one host
@@ -120,14 +207,20 @@ 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"
+set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml"
+```
+
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:
-$ cd myapp
-$ cap setup
+
+``` shell
+cd myapp
+cap setup
+```
+
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.)
@@ -135,22 +228,39 @@ If you are annoyed with entering your SSH password every time, create and upload
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:
-$ mongrel_rails cluster::configure -e production -p 9000 \
--a 127.0.0.1 -N 2 -c /home/ariejan/apps/myapp/current
+
+``` shell
+mongrel_rails cluster::configure -e production -p 9000 \
+-a 127.0.0.1 -N 2 -c /home/ariejan/apps/myapp/current
+```
+
The configuration file we saw earlier has been created. Check-in all new files in to subversion now, and cold deloy your application!
-$ cap cold_deploy
+
+``` shell
+cap cold_deploy
+```
+
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:
-$ cap migrate
-$ cap restart
+
+``` shell
+cap migrate
+cap restart
+```
+
To check that your application is running, issue the following command on your server. It should return you the HTML code from your app:
-$ curl -L http://127.0.0.1:9000
+
+``` shell
+curl -L http://127.0.0.1:9000
+```
+
+``` apache
BalancerMember http://127.0.0.1:9000
BalancerMember http://127.0.0.1:9001
@@ -184,24 +294,52 @@ Create a new file in /etc/apache2/sites-availbale named 'myapp' and add the foll
ErrorLog /home/ariejan/apps/myapps/shared/log/tankfactions_errors_log
CustomLog /home/ariejan/apps/myapps/shared/log/tankfactions_log combined
-
+
+```
+
Now enable this new site in apache:
-$ sudo a2ensite myapp
-$ /etc/init.d/apache2 force-reload
+
+``` shell
+sudo a2ensite myapp
+/etc/init.d/apache2 force-reload
+```
+
In some cases you may need to make a small change to /etc/apache2/mods-enabled/proxy.conf and swap
-Order deny,allow -Deny from all+ +``` apache +Order deny,allow +Deny from all +``` + for -
Order allow,deny -Allow from all+ +``` apache +Order allow,deny +Allow from all +``` + That's all, you can now access your app on myapp.com! +
$ cap deploy
+
+``` shell
+cap deploy
+```
+
If you made changes in the database, you may want to run a long_deploy:
-$ cap long_deploy
+
+``` shell
+cap long_deploy
+```
+
And if for some reason, your mongrel cluster dies, just restart it.
-$ cap restart
+
+``` shell
+cap restart
+```
+
That's it! Happy hacking :)
Please digg this story to help spread the word! Thanks a lot!
diff --git a/content/posts/2007-07-01-activescaffold-acts_as_taggable-auto-complete.md b/content/posts/2007-07-01-activescaffold-acts_as_taggable-auto-complete.md
index 96c6d34..d0d13c6 100644
--- a/content/posts/2007-07-01-activescaffold-acts_as_taggable-auto-complete.md
+++ b/content/posts/2007-07-01-activescaffold-acts_as_taggable-auto-complete.md
@@ -12,24 +12,34 @@ The problem with that solution was that, although the checkboxes for every tag a
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!
-
+
When you try to use acts_as_taggable with ActiveScaffold, you might use something like this in your BooksController.
-active_scaffold :books do |config|
+
+``` ruby
+active_scaffold :books do |config|
config.columns = [:title, :body, :tags]
config.list.columns = [:title, :tag_list]
config.columns[:tags].ui_type = :select
# ...
-end
+end
+```
+
This is not so useful when you want the flexibility of creating new tags instantly. Therefore, it's better to use the tag_list:
-active_scaffold :books do |config|
+
+``` ruby
+active_scaffold :books do |config|
config.columns = [:title, :body, :tag_list]
config.list.columns = [:title, :tag_list]
# ...
-end
+end
+```
+
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:
-auto_complete_for :book, :tag_list
+
+``` ruby
+auto_complete_for :book, :tag_list
def autocomplete_tag_list
@all_tags = Tag.find(:all, :order => 'name ASC')
@@ -40,19 +50,24 @@ def autocomplete_tag_list
end
render :layout => false
-end
+end
+```
+
We can now create the template for the results which are found.
In app/views/books/autocomplete_tag_list.rhtml:
-
+
+``` erb
+
+``` erb
def export_to_xml
+
+``` ruby
+def export_to_xml
@entries = Entry.find(:all)
render :xml => @entries.to_xml
-end
+end
+```
+
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:
-def export_to_xml
+
+``` 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
+end
+```
+
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'.
diff --git a/content/posts/2007-07-04-how-to-resolve-subversion-conflicts.md b/content/posts/2007-07-04-how-to-resolve-subversion-conflicts.md
index 1f7353a..e18c82f 100644
--- a/content/posts/2007-07-04-how-to-resolve-subversion-conflicts.md
+++ b/content/posts/2007-07-04-how-to-resolve-subversion-conflicts.md
@@ -14,39 +14,47 @@ You're an island, and have no clue about the new revision being created. You jus
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'
+``` shell
+$ 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.
+``` shell
+$ 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
+``` shell
+<<<<<<< .mine
+This is fun stuff!
+=======
+This is a documentation file
+>>>>>>> .r6
+```
+
+## What are your options?
-def export_to_xml
+
+``` 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
+end
+```
+
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:
-def conditions_for_collection
+
+``` ruby
+def conditions_for_collection
['title = ?', 'some title!']
-end
+end
+```
+
The condition is of the same format you can feed to find. 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
-def export_to_xml
+
+``` 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
+end
+```
+
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.
-./script/generate plugin acts_as_exportable+ +``` shell +./script/generate plugin acts_as_exportable +``` + 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. -
acts_as_exportable
-acts_as_exportable :book
+
+``` ruby
+acts_as_exportable
+acts_as_exportable :book
+```
+
The vendor/plugins/acts_as_exportable/lib/acts_as_exportable.rb contains a module that's named after our plugin:
-module ActsAsExportable
-end
+
+``` ruby
+module ActsAsExportable
+end
+```
+
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.
-module ActsAsExportable
+
+``` ruby
+module ActsAsExportable
def self.included(base)
base.extend(ClassMethods)
end
@@ -84,7 +112,9 @@ Next, we add a module named 'ClassMethods'. These class methods will be added to
instance_variable_get('@acts_as_exportable_config')
end
end
-end
+end
+```
+
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.
@@ -92,7 +122,9 @@ Every class now has the 'acts_as_exportable' method available. What does it do?
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.
-module InstanceMethods
+
+``` ruby
+module InstanceMethods
def export_to_xml
data = Book.find(:all, :order => 'title', :conditions => conditions_for_collection)
send_data data.to_xml,
@@ -103,7 +135,9 @@ Finally we include the module InstanceMethods, which we still have to define. Th
# Empty conditions. You can override this in your controller
def conditions_for_collection
end
-end
+end
+```
+
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'.
@@ -111,13 +145,19 @@ In the 'export_to_xml' there are a few changes as well. First of all, I generali
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:
-self.class.acts_as_exportable_config
+
+``` ruby
+self.class.acts_as_exportable_config
+```
+
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:
-module ActsAsExportable
+
+``` ruby
+module ActsAsExportable
def self.included(base)
base.extend(ClassMethods)
end
@@ -170,15 +210,27 @@ With the model name made application independent, the whole plugin code looks li
def conditions_for_collection
end
end
-end
+end
+```
+
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)
-acts_as_exportable
+
+``` ruby
+acts_as_exportable
+```
+
Done! – Or not?
-ActionController::Base.class_eval do
+
+``` ruby
+ActionController::Base.class_eval do
include ActsAsExportable
-end
+end
+```
+
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!
diff --git a/content/posts/2007-08-21-using-iconv-to-convert-utf-8-to-ascii-on-linux.md b/content/posts/2007-08-21-using-iconv-to-convert-utf-8-to-ascii-on-linux.md
index dd7a3df..f47600c 100644
--- a/content/posts/2007-08-21-using-iconv-to-convert-utf-8-to-ascii-on-linux.md
+++ b/content/posts/2007-08-21-using-iconv-to-convert-utf-8-to-ascii-on-linux.md
@@ -5,28 +5,42 @@ tags = ["General", "RubyOnRails", "Features", "Ruby"]
slug = "using-iconv-to-convert-utf-8-to-ascii-on-linux"
+++
-There are situations where you want to remove all the UTF-8 goodness from a string (mostly because of legacy systems you're working with). Now, this is rather easy to do. I'll give you an example:
-çéß-Should be converted to -
cess-On my mac, I can simply use the following snippet to convert the string: -
s = "çéß"
+There are situations where you want to remove all the UTF-8 goodness from a string
+(mostly because of legacy systems you're working with). Now, this is rather easy to do.
+I'll give you an example: `çéß`
+
+Should be converted to `cess`. On my mac, I can simply use the following snippet to convert
+the string:
+
+``` ruby
+s = "çéß"
s = Iconv.iconv('ascii//translit', 'utf-8', s).to_s # returns "c'ess"
-s.gsub(/\W/, '') # return "cess"
-Very nice and all, but when I deploy to my Debian 4.0 linux system, the I get an error that tells me that invalid characters were present. Why? Because the Mac has unicode goodness built-in. Linux does not (in most cases).
+s.gsub(/\W/, '') # return "cess"
+```
+
+Very nice and all, but when I deploy to my Debian 4.0 linux system, the I get an error that
+tells me that invalid characters were present. Why? Because the Mac has unicode goodness built-in.
+Linux does not (in most cases).
So, how do you go about solving this? Easy! Get unicode support!
-sudo apt-get install unicode+ +``` shell +sudo apt-get install unicode +``` + Now, try again. -Bonus +## Bonus If you want to convert a sentence (or anything else with spaces in it), you'll notice that spaces are removed by the gsub command. I solve this by splitting up the string first into words. Convert the words and then joining the words together again. -
words = s.split(" ")
-words = words.collect do |word|
- word = Iconv.iconv('ascii//translit', 'utf-8', word).to_s
- word = word.gsub(/\W/,'')
-end
-words.join(" ")
-Like this? Why not write a mix-in for String?
+``` ruby
+words = s.split(" ")
+words = words.collect do |word|
+ word = Iconv.iconv('ascii//translit', 'utf-8', word).to_s
+ word = word.gsub(/\W/,'')
+end
+words.join(" ")
+```
+
+Like this? Why not write a mix-in for String?
diff --git a/content/posts/2007-08-24-super-simple-authentication-plugin-and-generator.md b/content/posts/2007-08-24-super-simple-authentication-plugin-and-generator.md
index c7dc800..7215446 100644
--- a/content/posts/2007-08-24-super-simple-authentication-plugin-and-generator.md
+++ b/content/posts/2007-08-24-super-simple-authentication-plugin-and-generator.md
@@ -10,29 +10,52 @@ I hereby proudly announce my Super Simple Authentication plugin and gen
All right, what does it do? Sometimes you need to protect your actions and controllers, but you don't want to go about installing restful_authentication or anything like that. Adding a simple password for certain actions would suffice. So, I wrote a little plugin that can generate some code for you that allows you to easily protect your app with a simple password.
To get started, you must first install the plugin in your rails application:
-script/plugin install http://svn.ariejan.net/plugins/super_simple_authentication
+
+``` shell
+script/plugin install http://svn.ariejan.net/plugins/super_simple_authentication
+```
+
When the plugin is installed, you may generate your SSA controller. This controller verifies your password and makes sure you stay authenticated for the duration of your visit.
-script/generate super_simple_authentication sessions
+``` shell
+script/generate super_simple_authentication sessions
+```
+
Your password is located in config/super_simple_authentication.yml. Change it.
In the SessionsController, you'll find an include statement. Move this include to your application controller:
-include SuperSimpleAuthenticationSystem
+
+``` ruby
+include SuperSimpleAuthenticationSystem
+```
+
The generator automatically added routes to your config/routes.rb file. If you want easy access to login and logout functionality, add these two lines to your config/routes.rb file as well:
-map.login '/login', :controller => 'sessions', :action => 'new'
-map.logout '/logout', :controller => 'sessions', :action => 'destroy', :method => :delete
+
+``` ruby
+map.login '/login', :controller => 'sessions', :action => 'new'
+map.logout '/logout', :controller => 'sessions', :action => 'destroy', :method => :delete
+```
+
You can now protect you actions and controllers with a before_filter:
-# Protect all actions in the controller
+
+``` ruby
+# Protect all actions in the controller
before_filter :authorization_required
# Protect all actions, except :index and :recent
before_filter :authorization_required, :except => [:index, :recent]
# Protect only :destroy
-before_filter :authorization_required, :only => :destroy
+before_filter :authorization_required, :only => :destroy
+```
+
In your views, you can check if you are authorized or not with authorized? E.g.
-<% if authorized? %>
- # ... do secret admin stuff
-<% end %>
+
+``` erb
+<% if authorized? %>
+
+<% end %>
+```
+
Please visit http://trac.ariejan.net to report bugs. Ariejan.net will keep you updated on new major version. Please subscribe to the RSS Feed.
I hope you enjoy this plugin. Please post a comment if you use it in your project, or if you just like it. Bugs, feature requests and support requests should go into Trac
diff --git a/content/posts/2007-09-24-rails-20-new-features.md b/content/posts/2007-09-24-rails-20-new-features.md
index 1eda94b..3fe2fb9 100644
--- a/content/posts/2007-09-24-rails-20-new-features.md
+++ b/content/posts/2007-09-24-rails-20-new-features.md
@@ -8,7 +8,7 @@ slug = "rails-20-new-features"
As David Heinemeier Hansson already told us all during his RailsConfEurope 2007 keynote, it's time to take off the party hats. It's no longer at time to celebrate all the new stuff we get. It's time to celebrate what we have already.
With this statement DHH ends the revolution of Rails. During the past three years a lot of new and exiting features were added to Rails. However, now the time has come to evolve Rails further. No more new and exiting stuff, but fine tuning. Making things even better than they already are.
-
+
So, Rails 2.0 will not contain any major new features. But don't despair, there are quite a few nifty changes that you'll like to know about.
1. HTTP Authentication
@@ -19,14 +19,18 @@ HTTP Authentication is a great way to limit access to specific areas of your app
The performance of a web application goes down the drain when you add too much JavaScript and stylesheets. Each and every file must be downloaded separately. Rails 2.0 will be able to take all the javascript files, stuff 'em together, compress that one file and sent that to the client, where it will be cached.
-<%= javascript_include_tag :all, :cache => true %>
-<%= stylesheet_link_tag :all, :cache => true %>
+``` erb
+<%= javascript_include_tag :all, :cache => true %>
+<%= stylesheet_link_tag :all, :cache => true %>
+```
3. Asset Server
If you have a large (and busy) site, serving static files can be quite a performance issue. Rails 2.0 adds the notion of an "asset server". An asset server (in combination with item #2) will serve static content quickly, allowing your app to respond even faster to a user's request. To enable asset hosts, add the following line to your configuration:
-config.action_controller.asset_host = 'assets%d.example.com'
+``` ruby
+config.action_controller.asset_host = 'assets%d.example.com'
+```
You can even cycle through multiple asset servers by simply creating the appropriate CNAME records in DNS. Neat, eh?
@@ -54,22 +58,27 @@ Sexy Migrations have been around for some time as a plugin. Some people love the
Let's take an old migration:
-create_table :people do |t|
+``` ruby
+create_table :people do |t|
t.column :first_name, :string, :null => false
t.column :last_name, :string, :null => false
t.column :group_id, :integer
t.column :description, :text
t.column :created_at, :datetime
t.column :updated_at, :datetime
-end
+end
+```
- We now have this:
-create_table :people do |t|
+We now have this:
+
+``` ruby
+create_table :people do |t|
t.integer :group_id
t.string :first_name, :last_name, :null => false
t.text :description
t.timestamps
-end
+end
+```
8. Plugin Mania
diff --git a/content/posts/2007-12-12-how-to-install-mysql-on-ubuntudebian.md b/content/posts/2007-12-12-how-to-install-mysql-on-ubuntudebian.md
index ecb13e0..6029282 100644
--- a/content/posts/2007-12-12-how-to-install-mysql-on-ubuntudebian.md
+++ b/content/posts/2007-12-12-how-to-install-mysql-on-ubuntudebian.md
@@ -8,35 +8,47 @@ It may seem easy for some, but for others, installing MySQL on Ubuntu or Debian
First of all, make sure your package management tools are up-to-date. Also make sure you install all the latest software available.
- sudo apt-get update
- sudo apt-get dist-upgrade
+``` shell
+sudo apt-get update
+sudo apt-get dist-upgrade
+```
After a few moments (or minutes, depending on the state of your system), you're ready to install MySQL.
-~
+
By default, recent Ubuntu/Debian systems install a MySQL Server from the 5-branch. This is a good thing, so don't worry.
First, install the MySQL server and client packages:
- sudo apt-get install mysql-server mysql-client
+``` shell
+sudo apt-get install mysql-server mysql-client
+```
When done, you have a MySQL database read to rock 'n roll. However, there's more to do.
You need to set a root password, for starters. MySQL has it's own user accounts, which are not related to the user accounts on your Linux machine. By default, the root account of the MySQL Server is empty. You need to set it. Please replace 'mypassword' with your actual password and myhostname with your actual hostname.
- sudo mysqladmin -u root -h localhost password 'mypassword'
- sudo mysqladmin -u root -h myhostname password 'mypassword'
+``` shell
+sudo mysqladmin -u root -h localhost password 'mypassword'
+sudo mysqladmin -u root -h myhostname password 'mypassword'
+```
Now, you probably don't want just the MySQL Server. Most likely you have Apache+PHP already installed, and want MySQL to go with that. Here are some libraries you need to install to make MySQL available to PHP:
- sudo apt-get install php5-mysql
+``` shell
+sudo apt-get install php5-mysql
+```
Or for Ruby:
- sudo apt-get install libmysql-ruby
+``` shell
+sudo apt-get install libmysql-ruby
+```
You can now access your MySQL server like this:
- mysql -u root -p
+``` shell
+mysql -u root -p
+```
Have fun using MySQL Server.
diff --git a/content/posts/2008-04-09-rails-snippet-caching-expensive-calls.md b/content/posts/2008-04-09-rails-snippet-caching-expensive-calls.md
index a277a56..d627d64 100644
--- a/content/posts/2008-04-09-rails-snippet-caching-expensive-calls.md
+++ b/content/posts/2008-04-09-rails-snippet-caching-expensive-calls.md
@@ -7,30 +7,36 @@ slug = "rails-snippet-caching-expensive-calls"
In Rails, from time to time, you may encounter you have a method you call several times, but which returns always the same result. For example, have the following:
-class Person < ActiveRecord::Base
+``` ruby
+class Person < ActiveRecord::Base
has_many :articles
def get_approved_articles
self.articles.find(:all, :conditions => {:approved => true}, :order => 'approved_on DESC')
end
-end
+end
+```
A query is fired every time you call Person#get_approved_articles. To cache the result of the query during this request, just add a bit of magic
-class Person < ActiveRecord::Base
+``` ruby
+class Person < ActiveRecord::Base
has_many :articles
def get_approved_articles
@approved_articles ||= self.articles.find(:all, :conditions => {:approved => true}, :order => 'approved_on DESC')
end
-end
+end
+```
This will return the @approved_articles value if it exists. If it doesn't, which is the first time you access the method, the query is run and stored in @approved_articles for later use.
Note: I know it's much easier to define this kind of behaviour, but it's just an illustration.
-class Person < ActiveRecord::Base
+``` ruby
+class Person < ActiveRecord::Base
has_many :articles
has_many :approved_articles, :class_name => "Article", :conditions => {:approved => true}, :order => 'approved_on DESC'
-end
+end
+```
diff --git a/content/posts/2008-04-23-git-using-the-stash.md b/content/posts/2008-04-23-git-using-the-stash.md
index 020beac..370b833 100644
--- a/content/posts/2008-04-23-git-using-the-stash.md
+++ b/content/posts/2008-04-23-git-using-the-stash.md
@@ -23,48 +23,62 @@ will be reverted to HEAD (the last commit revision) of your code.
When you restore your stash, you changes are reapplied and you continue working
on your code.
-**Stash your current changes**
+## Stash your current changes
- $ git stash save create_table :posts, :id => false do |t|
+``` ruby
+create_table :posts, :id => false do |t|
t.string :uuid, :limit => 36, :primary => true
-end
+end
+```
In your Post model you should then set the name of this new primary key column.
-class Post < ActiveRecord::Base
+``` ruby
+class Post < ActiveRecord::Base
set_primary_key "uuid"
-end
+end
+```
The next step is to create the UUID itself. We'll have to do this the Rails app, because most databases don't support UUID out of the box.
First install the uuidtools gem
-sudo gem install uuidtools+``` shell +sudo gem install uuidtools +``` Create a file like lib/uuid_helper.rb and add the following content. -
require 'rubygems'
+``` ruby
+require 'rubygems'
require 'uuidtools'
module UUIDHelper
def before_create()
self.uuid = UUID.timestamp_create().to_s
end
-end
+end
+```
Then, include this module in all UUID-enabled models, like Post in this example.
-class Post < ActiveRecord::Base
+``` ruby
+class Post < ActiveRecord::Base
set_primary_key "uuid"
include UUIDHelper
-end
+end
+```
Now, when you save a new Post object, the uuid field is automatically filled with a Universally Unique Identifier. What else could you wish for?
diff --git a/content/posts/2008-08-17-activerecord-read-only-models.md b/content/posts/2008-08-17-activerecord-read-only-models.md
index 7dc5b47..a7361ca 100644
--- a/content/posts/2008-08-17-activerecord-read-only-models.md
+++ b/content/posts/2008-08-17-activerecord-read-only-models.md
@@ -9,34 +9,39 @@ ActiveRecord is great in providing CRUD for your data models. In some cases, how
I'm going to show you how you can easily mark a Model as read only all the time. In this example I have a Item model like this:
-class Item < ActiveRecord::Base
-end
+``` ruby
+class Item < ActiveRecord::Base
+end
+```
ActiveRecord::Base provides two methods that may be of interest here:
-def readonly!
+``` ruby
+def readonly!
@readonly = true
end
def readonly?
defined?(@readonly) && @readonly == true
-end
+end
+```
The first method sets the record to read only. This is great, but we don't want to set the read only property every time we load a model. The second, readonly?, return true if the object is read only or false if it isn't.
So, if we return true on the readonly? method, our object is marked as read only. Great!
-class Item < ActiveRecord::Base
+``` ruby
+class Item < ActiveRecord::Base
def readonly?
true
end
-end
+end
+```
That is all! All Item objects are now marked as read only all the time. If you try to write to the model, you'll receive an error.
-item = Item.find(:first)
+``` ruby
+item = Item.find(:first)
item.update_attributes(:name => 'Some item name')
-=> ActiveRecord::RecordReadOnly
-
-
-
+=> ActiveRecord::RecordReadOnly
+```
diff --git a/content/posts/2008-08-17-skinny-controllers-and-overweight-models.md b/content/posts/2008-08-17-skinny-controllers-and-overweight-models.md
index 9cb9cb1..dc854fd 100644
--- a/content/posts/2008-08-17-skinny-controllers-and-overweight-models.md
+++ b/content/posts/2008-08-17-skinny-controllers-and-overweight-models.md
@@ -12,42 +12,46 @@ Well, yes there is: create modules! Normally you'd write a module to reuse your
So, I package all related code (e.g. Authentication, state management, managing associated objects, etc) into different modules and place them in the /lib directory. Let's say you have a a bunch of methods to handle keep a counter on your User model
- Class User < ActiveRecord::Base
- attr_accessor :counter
+``` ruby
+class User < ActiveRecord::Base
+ attr_accessor :counter
- def up
- counter += 1
- end
+ def up
+ counter += 1
+ end
- def down
- counter -= 1
- end
+ def down
+ counter -= 1
+ end
- def reset
- counter = 0
- end
- end
+ def reset
+ counter = 0
+ end
+end
+```
You could create a new file lib/counter.rb and include that module in your User model.
- Class User < ActiveRecord::Base
- attr_accessor :counter
- include Counter
- end
+``` ruby
+class User < ActiveRecord::Base
+ attr_accessor :counter
+ include Counter
+end
- module Counter
- def up
- counter += 1
- end
+module Counter
+ def up
+ counter += 1
+ end
- def down
- counter -= 1
- end
+ def down
+ counter -= 1
+ end
- def reset
- counter = 0
- end
- end
+ def reset
+ counter = 0
+ end
+end
+```
As you can see, this keeps your fat User model clean and makes it easier for you to find code that applies to a certain function.
diff --git a/content/posts/2008-11-05-rspecing-with-timenow.md b/content/posts/2008-11-05-rspecing-with-timenow.md
index e8fd429..c62d942 100644
--- a/content/posts/2008-11-05-rspecing-with-timenow.md
+++ b/content/posts/2008-11-05-rspecing-with-timenow.md
@@ -1,17 +1,19 @@
-+++
-date = "2008-11-05"
-title = "RSpec'ing with Time.now"
-tags = ["General", "Ruby", "Rails", "rspec", "Test", "time"]
-slug = "rspecing-with-timenow"
-+++
++++
+date = "2008-11-05"
+title = "RSpec'ing with Time.now"
+tags = ["General", "Ruby", "Rails", "rspec", "Test", "time"]
+slug = "rspecing-with-timenow"
++++
I'm currently writing some RSpec tests that use Time.now.
I want my model to calculate a duration and store the future time in the database. I've already specced the calculation of the duration, but I also want to spec that everything gets saved correctly. Here's my first spec:
- it "should do stuff" do
- m = Model.create()
- m.expires_at.should eql(Time.now + some_value)
- end
+``` ruby
+it "should do stuff" do
+ m = Model.create()
+ m.expires_at.should eql(Time.now + some_value)
+end
+```
This fails.
@@ -21,12 +23,13 @@ So how do you test this kind of behaviour? I was not going to let this one beat
What you need to do is stub out Time#now to return a constant value within this test. This way, both calls will use the same Time.now value and thus yield the same result. This in turn makes your test pass (if the saving goes well, of course).
- it "should do stuff" do
- @time_now = Time.parse("Feb 24 1981")
- Time.stub!(:now).and_return(@time_now)
+``` ruby
+it "should do stuff" do
+ @time_now = Time.parse("Feb 24 1981")
+ Time.stub!(:now).and_return(@time_now)
+
+ m = Model.create()
+ m.expires_at.should eql(Time.now + some_value)
+end
+```
- m = Model.create()
- m.expires_at.should eql(Time.now + some_value)
- end
-
-
diff --git a/content/posts/2009-06-03-ruby-gem-imdb.md b/content/posts/2009-06-03-ruby-gem-imdb.md
index 8d4ea0a..d3e54ca 100644
--- a/content/posts/2009-06-03-ruby-gem-imdb.md
+++ b/content/posts/2009-06-03-ruby-gem-imdb.md
@@ -1,14 +1,16 @@
-+++
-date = "2009-06-03"
-title = "Ruby Gem: IMDB"
-tags = ["General", "Ruby", "imdb", "gem", "api"]
-slug = "ruby-gem-imdb"
-+++
++++
+date = "2009-06-03"
+title = "Ruby Gem: IMDB"
+tags = ["General", "Ruby", "imdb", "gem", "api"]
+slug = "ruby-gem-imdb"
++++
I just released version 0.1.0 of my IMDB gem which allows your app to search IMDB for IMDB movie ID's and access most data that's publicly available.
## Installation
- sudo gem install imdb
+``` shell
+sudo gem install imdb
+```
This will also install the dependencies Hpricot and HTTParty.
@@ -16,29 +18,31 @@ This will also install the dependencies Hpricot and HTTParty.
In your project, include the gem (and possibly rubygems as well).
- require 'rubygems'
- require 'imdb'
+``` ruby
+require 'rubygems'
+require 'imdb'
- search = Imdb::Search.new('Star Trek')
- => #class Beer < ActiveRecord::Base
+``` ruby
+class Beer < ActiveRecord::Base
def after_save
x = some_magic_method(self)
update_attribute(:my_attribute, x)
end
-end
+end
+```
The above will give you a nice infinite loop (which doesn't scale). It's possible to update your model, without calling the callbacks and without resorting to SQL.
-class Beer < ActiveRecord::Base
+``` ruby
+class Beer < ActiveRecord::Base
def after_save
x = some_magic_method(self)
Beer.update_all("my_attribute = #{x}", { :id => self.id })
end
-end
+end
+```
This is a bit unconventional, but it works nicely. You can use all the following ActiveRecord methods to update your model without calling callbacks:
diff --git a/content/posts/2009-09-03-rails-mysql-case-sensitive-strings-in-your-database.md b/content/posts/2009-09-03-rails-mysql-case-sensitive-strings-in-your-database.md
index e58dda0..78e8ca5 100644
--- a/content/posts/2009-09-03-rails-mysql-case-sensitive-strings-in-your-database.md
+++ b/content/posts/2009-09-03-rails-mysql-case-sensitive-strings-in-your-database.md
@@ -6,14 +6,17 @@ slug = "rails-mysql-case-sensitive-strings-in-your-database"
+++
When using Rails + MySQL, you'll find that normal string (or varchar(255)) fields are case insensitive. This can be quite a nuisance, but it's easy to resolve. You need to set your table to the utf8_bin collation. By using the binary variant, you're basically enabling case sensitivity.
- create_table :posts, :options => 'ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin' do |t|
- t.string :title, :limit => 100
- end
+``` ruby
+create_table :posts, :options => 'ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin' do |t|
+ t.string :title, :limit => 100
+end
+```
That's all. The title
field is now case sensitive.
Another question I get a lot is how to change the collation and charset for an existing column. That's easy with the following query. Just make sure to pick the right column and data type:
- ALTER TABLE posts MODIFY `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin;
-
+``` sql
+ALTER TABLE posts MODIFY `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin;
+```
diff --git a/content/posts/2009-10-13-valerii-32-base-string-encoder-and-decoder.md b/content/posts/2009-10-13-valerii-32-base-string-encoder-and-decoder.md
index ec9f357..ebf4098 100644
--- a/content/posts/2009-10-13-valerii-32-base-string-encoder-and-decoder.md
+++ b/content/posts/2009-10-13-valerii-32-base-string-encoder-and-decoder.md
@@ -13,52 +13,63 @@ We use a base-10 system. This means that for any number, every digit can hold 10
You may be familiar with hexadecimal numbers. Hexadecimal has a base of 16, meaning every digit can hold 16 distinct values. 0 through 9, a through f.
-Converting an integer to a 32-base string
+## Converting an integer to a 32-base string
The key to shortening a number to a string is that you need to store as many different values in a single digit. Because we want the digits to be part of an URL, we can only use valid URL characters. Characters like '/' and '?' are a no-go in this situation.
Another reason for sticking with 32 (and not 52 (a-z, A-Z, 0-9)) is that I'm going to use bit encoding. But, first we need to define an alphabet to use to represent the 32 different values:
-ENCODE_CHARS =
+``` ruby
+ENCODE_CHARS =
%w( B C D F G H J K
M N P Q R S T V
W Z b c d f h j
k m n p r x t v )
-
+```
For a value of 3 we'd use 'F'. Easy, right?
Let's say we want to encode the number 123. What valerii does first is convert 123 to a binary string.
-123.to_s(2) # => "1111011"
+``` ruby
+123.to_s(2) # => "1111011"
+```
Cool, now split up this string in blocks of 5 bits. 5 bits can contain 32 different values. We need to start 'chopping' from the right to the left, so first we reverse the binary string and split it up.
-"1111011".reverse.scan(/.{1,5}/) # => ["11011", "11"]
+``` ruby
+"1111011".reverse.scan(/.{1,5}/) # => ["11011", "11"]
+```
Now we convert the binary strings to 10-base numbers and map those to the characters defined in ENCODE_CHARS
. The resulting characters are reversed again and joined to one string:
-123.to_s(2).reverse.scan(/.{1,5}/).map do |bits|
+``` ruby
+123.to_s(2).reverse.scan(/.{1,5}/).map do |bits|
ENCODE_CHARS[bits.reverse.to_i(2)]
-end.reverse.join # => "Fp"
+end.reverse.join # => "Fp"
+```
-Converting a 32-base string to an integer
+## Converting a 32-base string to an integer
Converting a 32-base string back to its original integer value is quite easy now. The only trick is to create another hash that maps each character to its integer value:
-DECODE_MAP = ENCODE_CHARS.to_enum(:each_with_index).inject({}) do |h,(c,i)|
+``` ruby
+DECODE_MAP = ENCODE_CHARS.to_enum(:each_with_index).inject({}) do |h,(c,i)|
h[c] = i; h
-end
+end
+```
This looks scary, but it's actually a common way to reverse key/values in a hash.
Next is taking each character from the string and pushing the 5 bits we read in a variable. This variable is the original integer value.
-"Fp".split(//).map { |char|
+``` ruby
+"Fp".split(//).map { |char|
DECODE_MAP[char] or return nil
-}.inject(0) { |result,val| (result << 5) + val } # => 123
+}.inject(0) { |result,val| (result << 5) + val } # => 123
+```
-Notes
+## Notes
Once you have established your way of encoding/decoding you should not change the alphabet you're using, since it redefines the meaning and value of the encoded strings.
diff --git a/content/posts/2009-10-15-git-problem-error-unable-to-create-temporary-sha1-filename.md b/content/posts/2009-10-15-git-problem-error-unable-to-create-temporary-sha1-filename.md
index 0929369..a4840e9 100644
--- a/content/posts/2009-10-15-git-problem-error-unable-to-create-temporary-sha1-filename.md
+++ b/content/posts/2009-10-15-git-problem-error-unable-to-create-temporary-sha1-filename.md
@@ -5,13 +5,15 @@ tags = ["git", "prune", "repack", "fsck"]
slug = "git-problem-error-unable-to-create-temporary-sha1-filename"
+++
I got git problem: error: unable to create temporary sha1 filename
when pushing to a remote repository. The fix is rather easy.
-~
+
On both your local and remote repositories perform the following magic:
- git fsck
- git prune
- git repack
- git fsck
+``` shell
+git fsck
+git prune
+git repack
+git fsck
+```
The last fsck should not report any problems.
diff --git a/content/posts/2009-10-26-how-to-create-and-apply-a-patch-with-git.md b/content/posts/2009-10-26-how-to-create-and-apply-a-patch-with-git.md
index c814f33..db8ffb5 100644
--- a/content/posts/2009-10-26-how-to-create-and-apply-a-patch-with-git.md
+++ b/content/posts/2009-10-26-how-to-create-and-apply-a-patch-with-git.md
@@ -16,9 +16,11 @@ If you fix a bug or create a new feature – do it in a separate branch!
Let's say you want to create a patch for my imdb gem. You should clone my repository and create a new branch for the fix you have in mind. In this sample we'll do an imaginary fix for empty posters.
- git clone git://github.com/ariejan/imdb.git
- cd imdb
- git checkout -b fix_empty_poster
+``` shell
+git clone git://github.com/ariejan/imdb.git
+cd imdb
+git checkout -b fix_empty_poster
+```
Now, in the new fix_empty_poster
branch you can hack whatever you need to fix. Write tests, update code etc. etc.
@@ -28,10 +30,12 @@ When you're satisfied with all you changes, it's time to create your patch. FYI:
Okay, I've made some commits, here's the git log
for the fix_empty_poster
branch:
- git log --pretty=oneline -3
- * ce30d1f - (fix_empty_poster) Added poster URL as part of cli output (7 minutes ago)
- * 5998b80 - Added specs to test empty poster URL behaviour (12 minutes ago)
- * aecb8cb - (REL-0.5.0, origin/master, origin/HEAD, master) Prepare release 0.5.0 (4 months ago)
+``` shell
+git log --pretty=oneline -3
+* ce30d1f - (fix_empty_poster) Added poster URL as part of cli output (7 minutes ago)
+* 5998b80 - Added specs to test empty poster URL behaviour (12 minutes ago)
+* aecb8cb - (REL-0.5.0, origin/master, origin/HEAD, master) Prepare release 0.5.0 (4 months ago)
+```
In GitX it would look like this:
@@ -39,7 +43,9 @@ In GitX it would look like this:
Okay, now it's time to go and make a patch! All we really want are the two latest commits, stuff them in a file and send them to someone to apply them. But, since we created a separate branch, we don't have to worry about commits at all!
- git format-patch master --stdout > fix_empty_poster.patch
+``` shell
+git format-patch master --stdout > fix_empty_poster.patch
+```
This will create a new file fix_empty_poster.patch
with all changes from the current (fix_empty_poster
) against master
. Normally, git would create a separate patch file for each commit, but that's not what we want. All we need is a single patch file.
@@ -51,19 +57,25 @@ Now, you have a patch for the fix you wrote. Send it to the maintainer of the pr
First, take a look at what changes are in the patch. You can do this easily with git apply
- git apply --stat fix_empty_poster.patch
+``` shell
+git apply --stat fix_empty_poster.patch
+```
Note that this command does not apply the patch, but only shows you the stats about what it'll do. After peeking into the patch file with your favorite editor, you can see what the actual changes are.
Next, you're interested in how troublesome the patch is going to be. Git allows you to test the patch before you actually apply it.
- git apply --check fix_empty_poster.patch
+``` shell
+git apply --check fix_empty_poster.patch
+```
If you don't get any errors, the patch can be applied cleanly. Otherwise you may see what trouble you'll run into. To apply the patch, I'll use git am
instead of git apply
. The reason for this is that git am
allows you to sign off an applied patch. This may be useful for later reference.
- git am --signoff < fix_empty_poster.patch
- Applying: Added specs to test empty poster URL behaviour
- Applying: Added poster URL as part of cli output
+``` shell
+git am --signoff < fix_empty_poster.patch
+Applying: Added specs to test empty poster URL behaviour
+Applying: Added poster URL as part of cli output
+```
Okay, patches were applied cleanly and your master branch has been updated. Of course, run your tests again to make sure nothing got borked.
diff --git a/content/posts/2010-03-24-how-a-little-varnish-changed-my-life.md b/content/posts/2010-03-24-how-a-little-varnish-changed-my-life.md
index 15129eb..d0b16ca 100644
--- a/content/posts/2010-03-24-how-a-little-varnish-changed-my-life.md
+++ b/content/posts/2010-03-24-how-a-little-varnish-changed-my-life.md
@@ -23,8 +23,10 @@ Now I have a few other sites running on my vps which I don't want to cache just
Here's the entire configuration for Varnish to accomplish just that:
- backend default { .host = "127.0.0.1"; .port = "8080"; }
- sub vcl_recv { if (req.http.host !~ "ariejan.net") { return(pass); } }
+``` text
+backend default { .host = "127.0.0.1"; .port = "8080"; }
+sub vcl_recv { if (req.http.host !~ "ariejan.net") { return(pass); } }
+```
Yes, that is just two lines! What this does is forward everything you throw at varnish to the server at port 8080. The `vcl_recv` makes sure that if the hostname does not include ariejan.net varnish passes the request forward - no caching.
@@ -36,33 +38,35 @@ When I first ran my `ab` benchmark with 10 concurrent connections I got to about
For the record:
- # ab -c 1000 -n 60000 http://ariejan.net/2010/03/22/shields-up-rrrack-alert/
+``` shell
+$ ab -c 1000 -n 60000 http://ariejan.net/2010/03/22/shields-up-rrrack-alert/
- Server Software: Apache/2.2.15
- Server Hostname: ariejan.net
- Server Port: 80
+Server Software: Apache/2.2.15
+Server Hostname: ariejan.net
+Server Port: 80
- Document Path: /2010/03/22/shields-up-rrrack-alert/
- Document Length: 5117 bytes
+Document Path: /2010/03/22/shields-up-rrrack-alert/
+Document Length: 5117 bytes
- Concurrency Level: 1000
- Time taken for tests: 6.290 seconds
- Complete requests: 60000
- Failed requests: 0
- Write errors: 0
- Total transferred: 331434376 bytes
- HTML transferred: 307460062 bytes
- Requests per second: 9539.34 [#/sec] (mean)
- Time per request: 104.829 [ms] (mean)
- Time per request: 0.105 [ms] (mean, across all concurrent requests)
- Transfer rate: 51459.38 [Kbytes/sec] received
+Concurrency Level: 1000
+Time taken for tests: 6.290 seconds
+Complete requests: 60000
+Failed requests: 0
+Write errors: 0
+Total transferred: 331434376 bytes
+HTML transferred: 307460062 bytes
+Requests per second: 9539.34 [#/sec] (mean)
+Time per request: 104.829 [ms] (mean)
+Time per request: 0.105 [ms] (mean, across all concurrent requests)
+Transfer rate: 51459.38 [Kbytes/sec] received
- Connection Times (ms)
- min mean[+/-sd] median max
- Connect: 1 56 364.9 12 6209
- Processing: 2 22 76.7 16 3073
- Waiting: 2 19 76.6 13 3070
- Total: 3 78 374.6 29 6223
+Connection Times (ms)
+ min mean[+/-sd] median max
+Connect: 1 56 364.9 12 6209
+Processing: 2 22 76.7 16 3073
+Waiting: 2 19 76.6 13 3070
+Total: 3 78 374.6 29 6223
+```
Interested? Check out [Varnish][1] now or ask us at [Kabisa][2] to help you out!
diff --git a/content/posts/2010-03-25-installing-the-nokogiri-ruby-gem-on-debian.md b/content/posts/2010-03-25-installing-the-nokogiri-ruby-gem-on-debian.md
index 7cd6897..9f6aa1b 100644
--- a/content/posts/2010-03-25-installing-the-nokogiri-ruby-gem-on-debian.md
+++ b/content/posts/2010-03-25-installing-the-nokogiri-ruby-gem-on-debian.md
@@ -8,7 +8,9 @@ To install Nokogiri on a Debian system you need some system packages in place. T
~
First, install the necessary debian packages if you don't have them already:
- apt-get install build-essential libxml2-dev libxslt1-dev
+``` shell
+apt-get install build-essential libxml2-dev libxslt1-dev
+```
Then you can install nokogiri without any problem with `gem install nokogiri`
diff --git a/content/posts/2010-03-29-announcing-firefly-a-ruby-url-shortener.md b/content/posts/2010-03-29-announcing-firefly-a-ruby-url-shortener.md
index 6075cfb..6a62833 100644
--- a/content/posts/2010-03-29-announcing-firefly-a-ruby-url-shortener.md
+++ b/content/posts/2010-03-29-announcing-firefly-a-ruby-url-shortener.md
@@ -15,7 +15,6 @@ _FYI: I'm currently running aj.gs on Firefly 0.1 with MySQL._
[1]: http://ariejan.net/2010/03/28/really-another-sinatra-url-shortener-in-ruby/
[2]: http://github.com/ariejan/firefly#readme
[3]: http://github.com/ariejan/firefly
-~
### FireFly
@@ -23,33 +22,39 @@ FireFly is a simple URL shortener for personal use.
### Installation
- sudo gem install firefly
+``` shell
+sudo gem install firefly
+```
After you have installed the Firefly gem you should create a `config.ru` file that tells your webserver what to do. Here is a sample `config.ru`:
- require 'rubygems'
- require 'firefly'
+``` ruby
+require 'rubygems'
+require 'firefly'
- disable :run
+disable :run
- app = Firefly::Server.new do
- set :hostname, "localhost:3000"
- set :api_key, "test"
+app = Firefly::Server.new do
+ set :hostname, "localhost:3000"
+ set :api_key, "test"
- # Use Sqlite3 by default
- set :database, "sqlite3://#{Dir.pwd}/firefly.sqlite3"
+ # Use Sqlite3 by default
+ set :database, "sqlite3://#{Dir.pwd}/firefly.sqlite3"
- # You can use MySQL as well.
- # Make sure to install the do_mysql gem:
- # sudo gem install do_mysql
- # set :database, "mysql://root@localhost/firefly"
- end
+ # You can use MySQL as well.
+ # Make sure to install the do_mysql gem:
+ # sudo gem install do_mysql
+ # set :database, "mysql://root@localhost/firefly"
+end
- run app
+run app
+```
Next you can start your web server. You may try thin:
- thin start -R config.ru
+``` shell
+thin start -R config.ru
+```
### Configuration
@@ -67,24 +72,30 @@ It's possible to use all kinds of backends with DataMapper. Sqlite3 and MySQL ha
Adding a URL is done by doing a simple POST request that includes the URL and your API key.
- curl -d "url=http://ariejan.net" -d "api_key=test" http://localhost:3000/api/add
+``` shell
+curl -d "url=http://ariejan.net" -d "api_key=test" http://localhost:3000/api/add
+```
If you're on a MacOSX you could add the following function to your `~/.profile` to automate URL shortening:
- shorten(){
- URL=$1
- SHORT_URL=`curl -s -d "url=$URL&api_key=test" http://localhost:3000/api/add`
- echo $SHORT_URL | pbcopy
+``` shell
+shorten(){
+ URL=$1
+ SHORT_URL=`curl -s -d "url=$URL&api_key=test" http://localhost:3000/api/add`
+ echo $SHORT_URL | pbcopy
- echo "-- $URL => $SHORT_URL"
- echo "Short URL copied to clipboard."
- }
+ echo "-- $URL => $SHORT_URL"
+ echo "Short URL copied to clipboard."
+}
+```
After you restart Terminal.app (or at least reload the `.profile` file) you can use it like this:
- $ shorten http://ariejan.net
- -- http://ariejan.net => http://aj.gs/1
- Short URL copied to clipboard.
+``` shell
+$ shorten http://ariejan.net
+-- http://ariejan.net => http://aj.gs/1
+Short URL copied to clipboard.
+```
### Bugs, Feature Requests, etc.
diff --git a/content/posts/2010-04-05-detect-browser-web-sockets-support.md b/content/posts/2010-04-05-detect-browser-web-sockets-support.md
index c7b5e8c..aa7348f 100644
--- a/content/posts/2010-04-05-detect-browser-web-sockets-support.md
+++ b/content/posts/2010-04-05-detect-browser-web-sockets-support.md
@@ -13,11 +13,13 @@ Luckily, it's easy to detect web sockets support through JavaScript. All you rea
Here's a simple example, note that I'm using jQuery here.
- $(document).ready(function() {
- if( typeof(WebSocket) != "function" ) {
- $('body').html("Your browser does not support HTML5 Web Sockets. Try Google Chrome instead.
"); - } - }); +``` javascript +$(document).ready(function() { + if( typeof(WebSocket) != "function" ) { + $('body').html("Your browser does not support HTML5 Web Sockets. Try Google Chrome instead.
"); + } +}); +``` Maybe there are better ways, but _it works for me_. diff --git a/content/posts/2010-04-13-get-ready-for-firefly-03.md b/content/posts/2010-04-13-get-ready-for-firefly-03.md index bf042b4..070134d 100644 --- a/content/posts/2010-04-13-get-ready-for-firefly-03.md +++ b/content/posts/2010-04-13-get-ready-for-firefly-03.md @@ -15,34 +15,39 @@ Hot off the press is Firefly 0.3! Firefly is a simple URL shortener application * Works with any Rack capable web server Interested? Give it a go! Here's how in ht -~ ### 1. Install Firefly - gem install firefly +``` shell +gem install firefly +``` ### 2. Ready? Create a new directory and place the following `config.ru` file in it: - require 'rubygems' - require 'firefly' +``` ruby +require 'rubygems' +require 'firefly' - disable :run +disable :run - app = Firefly::Server.new do - set :hostname, "localhost:3000" - set :api_key, "test" - set :database, "sqlite3://#{Dir.pwd}/firefly.sqlite3" - end +app = Firefly::Server.new do + set :hostname, "localhost:3000" + set :api_key, "test" + set :database, "sqlite3://#{Dir.pwd}/firefly.sqlite3" +end - run app +run app +``` ### 3. Go! Start your engines! In this case I use `thin`: - thin start -R config.ru +``` shell +thin start -R config.ru +``` Now, when you visit `http://localhost:3000/` you'll be asked for your API key to login. Then, start shortening! @@ -54,11 +59,14 @@ When you update from 0.2 you'll notice your click stats are all indicating `0`. 1. Remove the `clicks` field from `firefly_urls` - ALTER TABLE `firefly_urls` DROP `clicks`; +``` sql +ALTER TABLE `firefly_urls` DROP `clicks`; +``` 2. Rename the `visits` field to `clicks` - ALTER TABLE `firefly_urls` CHANGE `visits` `clicks` int; +``` sql +ALTER TABLE `firefly_urls` CHANGE `visits` `clicks` int; +``` All done! No restart required. - diff --git a/content/posts/2010-04-25-ruby-version-and-gemset-in-your-bash-prompt-yes-sir.md b/content/posts/2010-04-25-ruby-version-and-gemset-in-your-bash-prompt-yes-sir.md index 1d4eb51..7967551 100644 --- a/content/posts/2010-04-25-ruby-version-and-gemset-in-your-bash-prompt-yes-sir.md +++ b/content/posts/2010-04-25-ruby-version-and-gemset-in-your-bash-prompt-yes-sir.md @@ -7,29 +7,37 @@ slug = "ruby-version-and-gemset-in-your-bash-prompt-yes-sir" RVM is an easy way to switch between different ruby implementations and gemsets. If you don't know about it, [go check it out][1]. If you do know about, you'll know how annoying it is never to know which ruby version and gemset you're currently using. Here is a nice `.profile` hack that shows your current ruby version and optional gemset in your prompt. [1]: http://rvm.beginrescueend.com/ -~ + Firstly, add the following function to your `~/.profile`: - function rvm_version { - local gemset=$(echo $GEM_HOME | awk -F'@' '{print $2}') - [ "$gemset" != "" ] && gemset="@$gemset" - local version=$(echo $MY_RUBY_HOME | awk -F'-' '{print $2}') - [ "$version" != "" ] && version="@$version" - local full="$version$gemset" - [ "$full" != "" ] && echo "$full " - } +``` shell +function rvm_version { + local gemset=$(echo $GEM_HOME | awk -F'@' '{print $2}') + [ "$gemset" != "" ] && gemset="@$gemset" + local version=$(echo $MY_RUBY_HOME | awk -F'-' '{print $2}') + [ "$version" != "" ] && version="@$version" + local full="$version$gemset" + [ "$full" != "" ] && echo "$full " +} +``` Next, you can use this function in your prompt. Like this: - export PS1="\$(rvm_version) \w \$(parse_git_branch) \$ " +``` shell +export PS1="\$(rvm_version) \w \$(parse_git_branch) \$ " +``` The results? For standard ruby 1.8.7 - @1.8.7 ~ $ +``` text +@1.8.7 ~ $ +``` Or with the `rails3` gemset enabled: - @1.8.7@rails3 ~ $ +``` text +@1.8.7@rails3 ~ $ +``` So, now you always know which ruby you're using! Happy coding! diff --git a/content/posts/2010-04-30-firefly-041-released.md b/content/posts/2010-04-30-firefly-041-released.md index 7ce5459..fa44d4d 100644 --- a/content/posts/2010-04-30-firefly-041-released.md +++ b/content/posts/2010-04-30-firefly-041-released.md @@ -6,7 +6,9 @@ slug = "firefly-041-released" +++ I just pushed [Firefly 0.4.1][1] to [Rubygems][2]. Updating is easy: - gem update firefly +``` shell +gem update firefly +``` Don't forget to restart your server, that's all. @@ -19,7 +21,7 @@ The 0.4.1 release covers the following changes: [1]: http://github.com/ariejan/firefly/tree/v0.4.1 [2]: http://rubygems.org/gems/firefly -~ + If you are interested in contributing to Firefly, please fork the project on [github][3]. Pull requests are very welcome. [3]: http://github.com/ariejan/firefly diff --git a/content/posts/2010-05-17-bundler-passenger-with-rails-235-yes-please.md b/content/posts/2010-05-17-bundler-passenger-with-rails-235-yes-please.md index 7339b3f..d33581e 100644 --- a/content/posts/2010-05-17-bundler-passenger-with-rails-235-yes-please.md +++ b/content/posts/2010-05-17-bundler-passenger-with-rails-235-yes-please.md @@ -7,21 +7,23 @@ slug = "bundler-passenger-with-rails-235-yes-please" Bundler allows you to define the gems your application uses, resolve dependencies and load everything up. This is great, because you don't have to manage all those different gem versions yourself any more. There is a little problem, though. When you want to use Bundler with Rails 2.3.5. you need to do a bit of extra work. You'll need to create a file `config/preinitializer.rb` that contains the following: -~ - require "rubygems" - require "bundler" - if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.5") - raise RuntimeError, "Your bundler version is too old." + - "Run `gem install bundler` to upgrade." - end +``` ruby +require "rubygems" +require "bundler" - # Set up load paths for all bundled gems - Bundler.setup - rescue Bundler::GemNotFound - raise RuntimeError, "Bundler couldn't find some gems." + - "Did you run `bundle install`?" - end +if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.5") + raise RuntimeError, "Your bundler version is too old." + + "Run `gem install bundler` to upgrade." + end + + # Set up load paths for all bundled gems + Bundler.setup +rescue Bundler::GemNotFound + raise RuntimeError, "Bundler couldn't find some gems." + + "Did you run `bundle install`?" +end +``` Then you deploy your app with Capistrano (as `root`) and find that Passenger can't find your gems. True, you need to install them, so you add a Capistrano task to run `bundle install` after you update your code. Still, passenger can't find the gems. @@ -29,10 +31,9 @@ The problem is that bundler installs the gems to your `~/.bundle`. When you run A solution is easy: `bundle install .bundle` will install the gems to `./.bundle`, which should be your rails root directory. That solves your problem with passenger! Here's the full Capistrano task: - desc "Install bundled gems into ./.bundle" - task :bundle do - run "cd #{release_path}; bundle install .bundle" - end - - - +``` ruby +desc "Install bundled gems into ./.bundle" +task :bundle do + run "cd #{release_path}; bundle install .bundle" +end +``` diff --git a/content/posts/2010-05-30-upgrading-to-mongoid-beta-6.md b/content/posts/2010-05-30-upgrading-to-mongoid-beta-6.md index dd41e02..ee649db 100644 --- a/content/posts/2010-05-30-upgrading-to-mongoid-beta-6.md +++ b/content/posts/2010-05-30-upgrading-to-mongoid-beta-6.md @@ -6,29 +6,34 @@ slug = "upgrading-to-mongoid-beta-6" +++ If you are working with Rails 3 and Mongoid, you're likely to upgrade to [`mongoid-2.0.0.beta6`][1]. That's okay, but you will run into a few problems. Among others, one will be: - Database should be a Mongo::DB, not NilClass +``` text +Database should be a Mongo::DB, not NilClass +``` or - Mongoid::Errors::InvalidDatabase: Mongoid::Errors::InvalidDatabase +``` text +Mongoid::Errors::InvalidDatabase: Mongoid::Errors::InvalidDatabase +``` Another, Mongoid-related problem is the error `uninitialized constant OrderedHash`. Luckily, these problems can be solved quite easily. [1]: http://rubygems.org/gems/mongoid -~ + The first thing you need to do is make sure you use the right version of `bson_ext`. Beta 6 requires you to run `bson_ext-1.0.1` or you'll get the `OrderedHash` error. Okay, with that out of the way, let's focus on the MongoDB errors. The problem is that Mongoid is accessed/used before it is properly initialized. To resolve this issue, add the following line to your other requires at the top of `config/application.rb`. - require 'mongoid/railtie' +``` ruby +require 'mongoid/railtie' +``` With that, you initialize Mongoid correctly. Hope it helps. Update: I also ran into `keys must be strings or symbols` errors. This is now a _known issue_ with `mongoid-2.0.0.beta6` and has been fixed in `master`. If you are using Bundler (you are, aren't you?) then you can use the master branch instead of the gem: - # gem 'mongoid', '2.0.0.beta6' - gem 'mongoid', :git => 'http://github.com/durran/mongoid.git' - - - +``` ruby +# gem 'mongoid', '2.0.0.beta6' +gem 'mongoid', :git => 'http://github.com/durran/mongoid.git' +``` diff --git a/content/posts/2010-06-06-firefly-043-and-firefly-client-040-released.md b/content/posts/2010-06-06-firefly-043-and-firefly-client-040-released.md index 4073fe4..58fab8d 100644 --- a/content/posts/2010-06-06-firefly-043-and-firefly-client-040-released.md +++ b/content/posts/2010-06-06-firefly-043-and-firefly-client-040-released.md @@ -9,24 +9,26 @@ Today version 0.4.3 of Firefly was released with some minor updates. To complete The client library allows your Ruby application to easily shorten URLs with a remote Firefly server. It's very easy to use and lightweight. [1]: http://github.com/ariejan/firefly-client -~ -*Firefly 0.4.3 Changelog* + +## Firefly 0.4.3 Changelog * Handle invalid API keys correctly. * Added a fix for MySQL users to update the `code` column to use the correct collation. Fixes [issue #9][2] [2]: github.com/ariejan/firefly/issues/9 -*Firefly Client* +## Firefly Client Using the Firefly Client is very easy, read the following snippet from the [README][3]: - require 'rubygems' - require 'firefly-client' +``` rubvy +require 'rubygems' +require 'firefly-client' - firefly = Firefly::Client.new("http://aj.gs", "my_api_key") - firefly.shorten("http://google.com") - => "http://aj.gs/8ds" +firefly = Firefly::Client.new("http://aj.gs", "my_api_key") +firefly.shorten("http://google.com") + => "http://aj.gs/8ds" +``` Nice, huh? Get more info over at [github][1] diff --git a/content/posts/2010-06-07-uploading-files-with-curl.md b/content/posts/2010-06-07-uploading-files-with-curl.md index 8615b60..1cb1e66 100644 --- a/content/posts/2010-06-07-uploading-files-with-curl.md +++ b/content/posts/2010-06-07-uploading-files-with-curl.md @@ -8,7 +8,9 @@ I've always trouble uploading files with Curl. Some how the syntax for that comm What I want to do is perform a normal `POST`, including a file and some other variables to a remote server. This is it: - curl -i -F name=test -F filedata=@localfile.jpg http://example.org/upload +``` shell +curl -i -F name=test -F filedata=@localfile.jpg http://example.org/upload +``` You can add as many `-F` as you want. The `-i` option tells curl to show the response headers as well, which I find useful most of the time. ~ diff --git a/content/posts/2010-06-10-cherry-picking-specific-commits-from-another-branch.md b/content/posts/2010-06-10-cherry-picking-specific-commits-from-another-branch.md index 616aef6..0e53021 100644 --- a/content/posts/2010-06-10-cherry-picking-specific-commits-from-another-branch.md +++ b/content/posts/2010-06-10-cherry-picking-specific-commits-from-another-branch.md @@ -8,30 +8,38 @@ I'm often asked how to merge only specific commits from another branch into the First of all, use `git log` or the awesome [GitX][1] tool to see exactly which commit you want to pick. An example: - dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master] - \ - 76cada - 62ecb3 - b886a0 [feature] +``` text +dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master] + \ + 76cada - 62ecb3 - b886a0 [feature] +``` Let's say you've written some code in commit `62ecb3` of the `feature` branch that is very important right now. It may contain a bug fix or code that other people need to have access to now. Whatever the reason, you want to have commit `62ecb3` in the master branch right now, but not the other code you've written in the `feature` branch. -~ + Here comes `git cherry-pick`. In this case, `62ecb3` is the cherry and you want to pick it! - git checkout master - git cherry-pick 62ecb3 +``` shell +git checkout master +git cherry-pick 62ecb3 +``` That's all. `62ecb3` is now applied to the master branch and commited (as a new commit) in `master`. `cherry-pick` behaves just like `merge`. If git can't apply the changes (e.g. you get merge conflicts), git leaves you to resolve the conflicts manually and make the commit yourself. -*Cherry picking a range of commits* +## Cherry picking a range of commits In some cases picking one single commit is not enough. You need, let's say three consecutive commits. `cherry-pick` is not the right tool for this. `rebase` is. From the previous example, you'd want commit `76cada` and `62ecb3` in `master`. The flow is to first create a new branch from `feature` at the last commit you want, in this case `62ecb3`. - git checkout -b newbranch 62ecb3 +``` shell +git checkout -b newbranch 62ecb3 +``` Next up, you rebase the `newbranch` commit `--onto master`. The `76cada^` indicates that you want to start from that specific commit. - git rebase --onto master 76cada^ +``` shell +git rebase --onto master 76cada^ +``` The result is that commits `76cada` through `62ecb3` are applied to `master`. diff --git a/content/posts/2010-08-09-rename-a-git-branch.md b/content/posts/2010-08-09-rename-a-git-branch.md index ce0abc5..092e97b 100644 --- a/content/posts/2010-08-09-rename-a-git-branch.md +++ b/content/posts/2010-08-09-rename-a-git-branch.md @@ -8,9 +8,8 @@ In git, branching is cheap and easy. You do it all the time (you're not? Well, y No problem for git! Renaming a branch is really easy: - git branch -m old_branch new_branch +``` shell +git branch -m old_branch new_branch +``` That's all. -~ - - diff --git a/content/posts/2010-08-23-resque-how-to-requeue-failed-jobs.md b/content/posts/2010-08-23-resque-how-to-requeue-failed-jobs.md index 7027ccf..d2ca987 100644 --- a/content/posts/2010-08-23-resque-how-to-requeue-failed-jobs.md +++ b/content/posts/2010-08-23-resque-how-to-requeue-failed-jobs.md @@ -18,11 +18,13 @@ To requeue jobs, you can use `Resque::Failure.requeue(index)` where index corres To requeue all jobs in the _failed_ queue, you can simply run the following commands: - # Requeue all jobs in the failed queue - (Resque::Failure.count-1).downto(0).each { |i| Resque::Failure.requeue(i) } +``` ruby +# Requeue all jobs in the failed queue +(Resque::Failure.count-1).downto(0).each { |i| Resque::Failure.requeue(i) } - # Clear the failed queue - Resque::Failure.clear +# Clear the failed queue +Resque::Failure.clear +``` That's all there is to it, really. Happy processing! diff --git a/content/posts/2010-09-11-mass-convert-wma-to-mp3-using-ffmpeg-and-ruby.md b/content/posts/2010-09-11-mass-convert-wma-to-mp3-using-ffmpeg-and-ruby.md index 6ee0263..10f9fb6 100644 --- a/content/posts/2010-09-11-mass-convert-wma-to-mp3-using-ffmpeg-and-ruby.md +++ b/content/posts/2010-09-11-mass-convert-wma-to-mp3-using-ffmpeg-and-ruby.md @@ -12,8 +12,10 @@ The first tool you need is ffmpeg. If you're on Mac, simple run `brew install ff With `ffmpeg` setup and in your path, create a directory and stuff you WMA's there. Then open `irb` and run the following Ruby command: - ext = ".wma" - Dir.glob("*#{ext}").each {|f| m = f.gsub(ext, '.mp3'); `ffmpeg -i '#{f}' -ab 192k -ac 2 -ar 44100 '#{m}'` } +``` ruby +ext = ".wma" +Dir.glob("*#{ext}").each {|f| m = f.gsub(ext, '.mp3'); `ffmpeg -i '#{f}' -ab 192k -ac 2 -ar 44100 '#{m}'` } +``` When done, you'll find the WMA files converted to MP3 (having the same filename, except for the extention). diff --git a/content/posts/2010-10-11-setup-a-ubuntu-vpn-server.md b/content/posts/2010-10-11-setup-a-ubuntu-vpn-server.md index 32ce329..6631d23 100644 --- a/content/posts/2010-10-11-setup-a-ubuntu-vpn-server.md +++ b/content/posts/2010-10-11-setup-a-ubuntu-vpn-server.md @@ -1,9 +1,9 @@ -+++ -date = "2010-10-11" -title = "Setup a Ubuntu VPN server" -tags = ["Linux", "Ubuntu", "vpn"] -slug = "setup-a-ubuntu-vpn-server" -+++ ++++ +date = "2010-10-11" +title = "Setup a Ubuntu VPN server" +tags = ["Linux", "Ubuntu", "vpn"] +slug = "setup-a-ubuntu-vpn-server" ++++ I recently installed Ubuntu Linux on a home server (I hate that word, but it best describes what it is, so). Anyway, I'd like to be able to create a VPN network between my home server and my MacbookPro, which might be anywhere in @@ -15,12 +15,16 @@ First, install the `pptpd` package. `pptpd` offers a `PPTP`-type VPN which is supported by Microsoft and other network vendors. This is also the easiest to setup. - sudo apt-get install pptpd +``` shell +sudo apt-get install pptpd +``` Next up, edit `/etc/pptpd.conf` with `sudo vi /etc/pptp.conf`. At the bottom add the following lines: - localip 192.168.1.10 - remoteip 192.168.1.230-239 +``` text +localip 192.168.1.10 +remoteip 192.168.1.230-239 +``` Here `localip` references the IP of my home server. The `remoteip` variable configures which IPs remote clients may use when the connect through VPN to my @@ -30,8 +34,10 @@ network. In this case I reserve 10 IP address: 192.168.1.230 through With that out of the way, let's tell `PPTP` which users to allow. Edit `/etc/ppp/chap-secrets`, just like you did before using `sudo`. - # client server secret IP Address - ariejan pptpd somepassword * +``` text +# client server secret IP Address +ariejan pptpd somepassword * +``` That's all! Yes, seriously. Just restart the `pptpd` daemon and you're good to go. @@ -41,5 +47,5 @@ Now, go and watch my [PPTP VPN setup for Mac OS X Snow Leopard][1] _Note: This was tested on Ubuntu 10.10-amd64_ [1]: http://ariejan.net/2010/10/12/setup-a-pptp-vpn-connection-on-mac-os-x-snow-leopard/ - - + + diff --git a/content/posts/2010-10-26-clear-your-mysql-password.md b/content/posts/2010-10-26-clear-your-mysql-password.md index db8955c..8392812 100644 --- a/content/posts/2010-10-26-clear-your-mysql-password.md +++ b/content/posts/2010-10-26-clear-your-mysql-password.md @@ -1,27 +1,33 @@ -+++ -date = "2010-10-26" -title = "Clear your MySQL password" -tags = ["MySQL", "development", "password"] -slug = "clear-your-mysql-password" -+++ ++++ +date = "2010-10-26" +title = "Clear your MySQL password" +tags = ["MySQL", "development", "password"] +slug = "clear-your-mysql-password" ++++ Most people need their MySQL database protected with at least a decent password. I agree, but in development this often causes conflicts - and I prefer to work with my MySQL datbase without all the password-hassle. On Ubuntu I recently installed MySQL and set a password. Here's how to remove that password so you can skip all the password stuff during development. ~ First, connect to MySQL and check what permissions are currently set: - $ mysql -u root -p - use mysql; - select Host, User, Password from user; +``` shell +$ mysql -u root -p +use mysql; +select Host, User, Password from user; +``` You'll probably see three entries for the `root` user: `localhost`, `127.0.0.1` and your hostname like `hostname`. To clear the password for the root user issue the following query: - update user set password = '' where user = 'root'; +``` sql +update user set password = '' where user = 'root'; +``` Optionally, you may only want to reset the password for `localhost`: - update user set password = '' where user = 'root' and host = 'localhost'; +``` sql +update user set password = '' where user = 'root' and host = 'localhost'; +``` Keep in mind that using no MySQL password is insecure. Always protected your MySQL database with at least a strong password in production. - - + + diff --git a/content/posts/2010-11-25-hide-last-login-on-bash-login.md b/content/posts/2010-11-25-hide-last-login-on-bash-login.md index 32b8e18..114ee9e 100644 --- a/content/posts/2010-11-25-hide-last-login-on-bash-login.md +++ b/content/posts/2010-11-25-hide-last-login-on-bash-login.md @@ -6,13 +6,17 @@ slug = "hide-last-login-on-bash-login" +++ Everytime I open a new Terminal on my Mac, I get a line like this: - Last login: Thu Nov 25 09:07:55 on ttys004 +``` text +Last login: Thu Nov 25 09:07:55 on ttys004 +``` This annoys me. I don't care when I last opened a local Terminal. -~ + To hide this "Last login" message when logging in to bash you need to create a file in your homedirectory. - touch ~/.hushlogin +``` shell +touch ~/.hushlogin +``` With this `.hushlogin` file in place you won't see the "Last login" message and go directly to your prompt, where you want to be. diff --git a/content/posts/2010-12-15-why-did-errormessagesfor-disappear-from-rails-3.md b/content/posts/2010-12-15-why-did-errormessagesfor-disappear-from-rails-3.md index 5b7221c..9b854fc 100644 --- a/content/posts/2010-12-15-why-did-errormessagesfor-disappear-from-rails-3.md +++ b/content/posts/2010-12-15-why-did-errormessagesfor-disappear-from-rails-3.md @@ -6,7 +6,7 @@ slug = "why-did-errormessagesfor-disappear-from-rails-3" +++ Today I learned that `error_messages_for` has disappear from Rails 3. When I tried using it I got the following deprecation warning: - DEPRECATION WARNING: form.error_messages was removed from Rails and is now available as a plugin. +**DEPRECATION WARNING: form.error_messages was removed from Rails and is now available as a plugin.** What happened? Why was this pulled from Rails 3? ~ @@ -15,19 +15,20 @@ The reason `error_messages_for` was pulled from Rails 3 is a new guideline that Okay, that's all well and good. How do you fix this problem? There are two ways. The first is to implement your own error handling. A HAML snippet: - - if @post.errors.any? - .errors - %h2 There was a problem saving this post +``` ruby +- if @post.errors.any? + .errors + %h2 There was a problem saving this post - %ul - - @post.errors.full_messages.each do |msg| - %li= msg + %ul + - @post.errors.full_messages.each do |msg| + %li= msg +``` This is by far the best way to go about it. However, if you have a current Rails 2 app you're upgrading, writing your own error handling may be rather difficult or time consuming. In that case you can install a plugin that restores the original functionality of `error_messages_for`. - rails plugin install git://github.com/rails/dynamic_form.git +``` shell +rails plugin install git://github.com/rails/dynamic_form.git +``` Just make sure to restart your server. - - - diff --git a/content/posts/2010-12-24-public-readable-amazon-s3-bucket-policy.md b/content/posts/2010-12-24-public-readable-amazon-s3-bucket-policy.md index 4296697..62e1847 100644 --- a/content/posts/2010-12-24-public-readable-amazon-s3-bucket-policy.md +++ b/content/posts/2010-12-24-public-readable-amazon-s3-bucket-policy.md @@ -10,20 +10,22 @@ Luckily, Amazon features _bucket policies_, which allow you to define permission ~ This example will give _read_ access to _Everyone_ on _all files_ in your bucket. - { - "Version":"2008-10-17", - "Statement":[{ - "Sid":"AllowPublicRead", - "Effect":"Allow", - "Principal": { - "AWS": "*" - }, - "Action":["s3:GetObject"], - "Resource":["arn:aws:s3:::bucket/*" - ] - } - ] - } +``` json +{ + "Version":"2008-10-17", + "Statement":[{ + "Sid":"AllowPublicRead", + "Effect":"Allow", + "Principal": { + "AWS": "*" + }, + "Action":["s3:GetObject"], + "Resource":["arn:aws:s3:::bucket/*" + ] + } + ] +} +``` **Make sure you replace `bucket` in `arn:aws:s3:::bucket/*` with your bucket name.** diff --git a/content/posts/2011-01-01-rake-task-to-sync-your-assets-to-amazon-s3cloudfront.md b/content/posts/2011-01-01-rake-task-to-sync-your-assets-to-amazon-s3cloudfront.md index aa870ce..8ccf2a2 100644 --- a/content/posts/2011-01-01-rake-task-to-sync-your-assets-to-amazon-s3cloudfront.md +++ b/content/posts/2011-01-01-rake-task-to-sync-your-assets-to-amazon-s3cloudfront.md @@ -31,79 +31,82 @@ I don't want to configure anything, if possible. Well, this is the rake task I currently use: - require 's3' - require 'digest/md5' - require 'mime/types' +``` ruby +require 's3' +require 'digest/md5' +require 'mime/types' - ## These are some constants to keep track of my S3 credentials and - ## bucket name. Nothing fancy here. +## These are some constants to keep track of my S3 credentials and +## bucket name. Nothing fancy here. - AWS_ACCESS_KEY_ID = "xxxxx" - AWS_SECRET_ACCESS_KEY = "yyyyy" - AWS_BUCKET = "my_bucket" +AWS_ACCESS_KEY_ID = "xxxxx" +AWS_SECRET_ACCESS_KEY = "yyyyy" +AWS_BUCKET = "my_bucket" - ## This defines the rake task `assets:deploy`. - namespace :assets do - desc "Deploy all assets in public/**/* to S3/Cloudfront" - task :deploy, :env, :branch do |t, args| +## This defines the rake task `assets:deploy`. +namespace :assets do + desc "Deploy all assets in public/**/* to S3/Cloudfront" + task :deploy, :env, :branch do |t, args| - ## Minify all CSS files - Rake::Task[:minify].execute +## Minify all CSS files + Rake::Task[:minify].execute - ## Use the `s3` gem to connect my bucket - puts "== Uploading assets to S3/Cloudfront" +## Use the `s3` gem to connect my bucket + puts "== Uploading assets to S3/Cloudfront" - service = S3::Service.new( - :access_key_id => AWS_ACCESS_KEY_ID, - :secret_access_key => AWS_SECRET_ACCESS_KEY) - bucket = service.buckets.find(AWS_BUCKET) + service = S3::Service.new( + :access_key_id => AWS_ACCESS_KEY_ID, + :secret_access_key => AWS_SECRET_ACCESS_KEY) + bucket = service.buckets.find(AWS_BUCKET) - ## Needed to show progress - STDOUT.sync = true +## Needed to show progress + STDOUT.sync = true - ## Find all files (recursively) in ./public and process them. - Dir.glob("public/**/*").each do |file| +## Find all files (recursively) in ./public and process them. + Dir.glob("public/**/*").each do |file| - ## Only upload files, we're not interested in directories - if File.file?(file) +## Only upload files, we're not interested in directories + if File.file?(file) - ## Slash 'public/' from the filename for use on S3 - remote_file = file.gsub("public/", "") +## Slash 'public/' from the filename for use on S3 + remote_file = file.gsub("public/", "") - ## Try to find the remote_file, an error is thrown when no - ## such file can be found, that's okay. - begin - obj = bucket.objects.find_first(remote_file) - rescue - obj = nil - end - - ## If the object does not exist, or if the MD5 Hash / etag of the - ## file has changed, upload it. - if !obj || (obj.etag != Digest::MD5.hexdigest(File.read(file))) - print "U" - - ## Simply create a new object, write the content and set the proper - ## mime-type. `obj.save` will upload and store the file to S3. - obj = bucket.objects.build(remote_file) - obj.content = open(file) - obj.content_type = MIME::Types.type_for(file).to_s - obj.save - else - print "." - end - end +## Try to find the remote_file, an error is thrown when no +## such file can be found, that's okay. + begin + obj = bucket.objects.find_first(remote_file) + rescue + obj = nil end - STDOUT.sync = false # Done with progress output. - puts - puts "== Done syncing assets" +## If the object does not exist, or if the MD5 Hash / etag of the +## file has changed, upload it. + if !obj || (obj.etag != Digest::MD5.hexdigest(File.read(file))) + print "U" + +## Simply create a new object, write the content and set the proper +## mime-type. `obj.save` will upload and store the file to S3. + obj = bucket.objects.build(remote_file) + obj.content = open(file) + obj.content_type = MIME::Types.type_for(file).to_s + obj.save + else + print "." + end end end + STDOUT.sync = false # Done with progress output. + + puts + puts "== Done syncing assets" + end +end +``` This rake task is hooked into my `rake deploy:production` script and generates the following output (I added a new file just to show you what happens.) +``` shell $ rake deploy:production (in /Users/ariejan/Code/Sites/ariejannet) Deploying master to production @@ -121,6 +124,7 @@ This rake task is hooked into my `rake deploy:production` script and generates t Total 30 (delta 17), reused 0 (delta 0) -----> Heroku receiving push +``` ### Conclusion ### diff --git a/content/posts/2011-02-01-hot-firefly-130-url-shortener-released.md b/content/posts/2011-02-01-hot-firefly-130-url-shortener-released.md index 9ae8b18..0b61102 100644 --- a/content/posts/2011-02-01-hot-firefly-130-url-shortener-released.md +++ b/content/posts/2011-02-01-hot-firefly-130-url-shortener-released.md @@ -32,7 +32,9 @@ added. I'll just summarize those and ignore the 1.2.x release I made. Simple install the latest gem version and restart your server. - gem install firefly -v1.3.0 +``` shell +gem install firefly -v1.3.0 +``` Then restart your server. DataMapper will take care of migrating your database for you. diff --git a/content/posts/2011-02-07-using-your-firefly-url-shortener-with-twitter-for-iphone.md b/content/posts/2011-02-07-using-your-firefly-url-shortener-with-twitter-for-iphone.md index ab33efa..09378f3 100644 --- a/content/posts/2011-02-07-using-your-firefly-url-shortener-with-twitter-for-iphone.md +++ b/content/posts/2011-02-07-using-your-firefly-url-shortener-with-twitter-for-iphone.md @@ -27,7 +27,9 @@ All right, you're now ready to enter your magic URL. Simply replace the `YOUR_DOMAIN` and `YOUR_API_KEY` placeholders with your actual domain name and API key (you can find them in your `config.ru`) - http://YOUR_DOMAIN/api/add?api_key=YOUR_API_KEY&url=%@ +``` text +http://YOUR_DOMAIN/api/add?api_key=YOUR_API_KEY&url=%@ +``` Then hit _"Save"_ and you're set! Twitter for iPhone will now automatically use your Firefly instance to shorten URLs! diff --git a/content/posts/2011-02-11-narf-a-ruby-micro-test-framework.md b/content/posts/2011-02-11-narf-a-ruby-micro-test-framework.md index 123a906..2f644da 100644 --- a/content/posts/2011-02-11-narf-a-ruby-micro-test-framework.md +++ b/content/posts/2011-02-11-narf-a-ruby-micro-test-framework.md @@ -16,9 +16,11 @@ citizen I want to test that method. Using RSpec or Cucumber here just seems wrong here. So, I've implemented my own _Ruby Micro Test Framework_: *Narf* - def assert(message, &block) - puts "#{"%6s" % ((yield || false) ? ' PASS' : '! FAIL')} - #{message}" - end +``` ruby +def assert(message, &block) + puts "#{"%6s" % ((yield || false) ? ' PASS' : '! FAIL')} - #{message}" +end +``` (Yes, that's it.) @@ -28,48 +30,56 @@ method. And example: Let's say you're going to write a method that counts how often the word 'ruby' occurs in a given String: - def count_rubies(text) - # TODO - end +``` ruby +def count_rubies(text) + # TODO +end - #--- Ruby Micro Test Framework - def assert(message, &block) - puts "#{"%6s" % ((yield || false) ? ' PASS' : '! FAIL')} - #{message}" - end - #--- +#--- Ruby Micro Test Framework +def assert(message, &block) + puts "#{"%6s" % ((yield || false) ? ' PASS' : '! FAIL')} - #{message}" +end +#--- - #--- Tests - assert "Count zero rubies" do - count_rubies("this is Sparta!") == 0 - end +#--- Tests +assert "Count zero rubies" do + count_rubies("this is Sparta!") == 0 +end - assert "Count one ruby" do - count_rubies("This is one ruby") == 1 - end +assert "Count one ruby" do + count_rubies("This is one ruby") == 1 +end - assert "Count one RuBy" do - count_rubies("This is one RuBy") == 1 - end +assert "Count one RuBy" do + count_rubies("This is one RuBy") == 1 +end +``` Now, simple save this file and feed it to ruby: - $ ruby my_method.rb - ! FAIL - Count zero rubies - ! FAIL - Count one ruby - ! FAIL - Count one RuBy +``` shell +$ ruby my_method.rb +! FAIL - Count zero rubies +! FAIL - Count one ruby +! FAIL - Count one RuBy +``` Now, implement your method... - def count_rubies(text) - text.match(/(ruby)/i).size - end +``` ruby +def count_rubies(text) + text.match(/(ruby)/i).size +end +``` And re-run your tests: - $ ruby my_method.rb - PASS - Count zero rubies - PASS - Count one ruby - PASS - Count one RuBy +``` shell +$ ruby my_method.rb + PASS - Count zero rubies + PASS - Count one ruby + PASS - Count one RuBy +``` So with the addition of just a single method you can fully TDD/BDD your single method Ruby code. Pretty need, huh? diff --git a/content/posts/2011-03-27-rails-3-devise-uploadify-no-flash-session-hacks.md b/content/posts/2011-03-27-rails-3-devise-uploadify-no-flash-session-hacks.md index 51e082d..ce8b073 100644 --- a/content/posts/2011-03-27-rails-3-devise-uploadify-no-flash-session-hacks.md +++ b/content/posts/2011-03-27-rails-3-devise-uploadify-no-flash-session-hacks.md @@ -61,8 +61,10 @@ required - it's all built in into devise already! Let me show you. First check that your (devise-powered) user has an authentitication token: - @user.authentication_token - => "4R2bzzQRdoT_iz-ND4Bb" +``` ruby +@user.authentication_token +=> "4R2bzzQRdoT_iz-ND4Bb" +``` In case your `authentication_token` is nil, you should generate one with `@user.reset_authentication_token!` @@ -72,10 +74,12 @@ request to the server (while uploading files). Nothing fancy here either. Not that this is a snippet from JavaScript, embedded in a HAML template: - $('#image_file').uploadify({ - // I omitted all other config options, since they're not relevant. - 'script' : '#{images_path(:auth_token => current_user.authentication_token, :format => :json)}' - ) +``` javascript +$('#image_file').uploadify({ + // I omitted all other config options, since they're not relevant. + 'script' : '#{images_path(:auth_token => current_user.authentication_token, :format => :json)}' +) +``` Rails will generate a URL like this: `/images.json?auth_token=4R2bzzQRdoT_iz-ND4Bb`. @@ -83,13 +87,15 @@ Rails will generate a URL like this: The final step is to protect your `ImagesController#create` action with devise. - class ImagesController < ApplicationController - before_filter :authenticate_user! +``` ruby +class ImagesController < ApplicationController + before_filter :authenticate_user! - def create - # Handle your upload - end - end + def create + # Handle your upload + end +end +``` That's all. You dont' even need to add rack middleware or hack Uploadify to allow an authenticated devise user to upload images through flash. diff --git a/content/posts/2011-04-04-rake-with-namespaces-and-default-tasks.md b/content/posts/2011-04-04-rake-with-namespaces-and-default-tasks.md index 4c024a4..a443ce5 100644 --- a/content/posts/2011-04-04-rake-with-namespaces-and-default-tasks.md +++ b/content/posts/2011-04-04-rake-with-namespaces-and-default-tasks.md @@ -1,9 +1,9 @@ -+++ -date = "2011-04-04" -title = "Rake with namespaces and default tasks" -tags = ["Ruby", "rake"] -slug = "rake-with-namespaces-and-default-tasks" -+++ ++++ +date = "2011-04-04" +title = "Rake with namespaces and default tasks" +tags = ["Ruby", "rake"] +slug = "rake-with-namespaces-and-default-tasks" ++++ Rake is an awesome tool to automate tasks for your Ruby (or Rails) application. In this short article I'll show you how to use namespaces and set default tasks for them. @@ -18,28 +18,32 @@ kick off the clean up process. This is what I'd like: - rake cleanup # Cleanup everything - rake cleanup:clicks # Aggregate click stats - rake cleanup:logs # Clean old logs +``` shell +rake cleanup # Cleanup everything +rake cleanup:clicks # Aggregate click stats +rake cleanup:logs # Clean old logs +``` Here's what I put in `lib/tasks/cleanup.rake`: - namespace :cleanup do - desc "Aggregate click stats" - task :clicks => :environment do - Click.cleanup! - end +``` ruby +namespace :cleanup do + desc "Aggregate click stats" + task :clicks => :environment do + Click.cleanup! + end - desc "Clean old logs" - task :logs => :environment do - Log.cleanup! - end + desc "Clean old logs" + task :logs => :environment do + Log.cleanup! + end - task :all => [:clicks, :logs] - end + task :all => [:clicks, :logs] +end - desc "Cleanup everything" - task :cleanup => 'cleanup:all' +desc "Cleanup everything" +task :cleanup => 'cleanup:all' +``` Notice that the `cleanup:all` task does not have a description. Without it, it won't show up when you do a `rake -T` to view available tasks. @@ -47,5 +51,5 @@ it, it won't show up when you do a `rake -T` to view available tasks. The task `cleanup` has the same name as the namespace and calls the (undocumentend) `cleanup:all` task, kicking off the entire cleanup process. - - + + diff --git a/content/posts/2011-06-10-vows-and-coffeescript.md b/content/posts/2011-06-10-vows-and-coffeescript.md index 868eafb..9032e63 100644 --- a/content/posts/2011-06-10-vows-and-coffeescript.md +++ b/content/posts/2011-06-10-vows-and-coffeescript.md @@ -1,9 +1,10 @@ -+++ -date = "2011-06-10" -title = "Vows and CoffeeScript" -tags = ["javascript", "bdd", "nodejs", "coffee-script", "vows", "v8"] -slug = "vows-and-coffeescript" -+++ ++++ +date = "2011-06-10" +title = "Vows and CoffeeScript" +tags = ["javascript", "bdd", "nodejs", "coffee-script", "vows", "v8"] +slug = "vows-and-coffeescript" ++++ + CoffeeScript is a really nice way to write JavaScript code. Combined with NodeJS you are empowered by a very fast platform to develop server-side applications. Of course, you want to test these apps as well. [Vows][1] is really @@ -16,35 +17,39 @@ First off, make sure you have CoffeeScript and Vows installed. Here I install them _globally_ so you can use the `coffee` and `vows` command line utilities. - npm install -g coffee-script - npm install -g vows +``` shell +npm install -g coffee-script +npm install -g vows +``` Next up, in your product directory, create a directory named `test`. Here we'll create (classic) example: `division-test.coffee` - vows = require 'vows' - assert = require 'assert' +``` coffee +vows = require 'vows' +assert = require 'assert' - vows - .describe('Division by zero') - .addBatch - 'when dividing a number by zero': - topic: -> 42/ 0 +vows + .describe('Division by zero') + .addBatch + 'when dividing a number by zero': + topic: -> 42/ 0 - 'we get Infinity': (topic) -> - assert.equal topic, Infinity + 'we get Infinity': (topic) -> + assert.equal topic, Infinity - 'but when dividing zero by zero': - topic: -> 0 / 0 + 'but when dividing zero by zero': + topic: -> 0 / 0 - 'we get a value which': - 'is not a number': (topic) -> - assert.isNaN topic + 'we get a value which': + 'is not a number': (topic) -> + assert.isNaN topic - 'is not equal to itself': (topic) -> - assert.notEqual topic, topic + 'is not equal to itself': (topic) -> + assert.notEqual topic, topic - .export(module) + .export(module) +``` I'm not going to explain the intimate details of Vows here, suffice it to say that you calculate a value and store it in `topic`. Then you @@ -61,17 +66,18 @@ run them. With the `test/division-test.coffee` saved, try running `vows` from your console. Here's the output from `vows --spec`: - λ vows --spec +``` shell +vows --spec +♢ Division by zero - ♢ Division by zero + when dividing a number by zero + ✓ we get Infinity + but when dividing zero by zero we get a value which + ✓ is not a number + ✓ is not equal to itself - when dividing a number by zero - ✓ we get Infinity - but when dividing zero by zero we get a value which - ✓ is not a number - ✓ is not equal to itself - - ✓ OK » 3 honored (0.002s) +✓ OK » 3 honored (0.002s) +``` Another great tip is `vows -w`. This will keep vows running and monitor your test files for changes. When a file changes, it will re-run your @@ -80,5 +86,5 @@ vows for you. Happy testing! _Yes, I know there are issues with Coderay parsing UTF-8 characters._ - - + + diff --git a/content/posts/2011-06-24-git-what-files-were-changed-since-the-last-release.md b/content/posts/2011-06-24-git-what-files-were-changed-since-the-last-release.md index 96a62c8..315b719 100644 --- a/content/posts/2011-06-24-git-what-files-were-changed-since-the-last-release.md +++ b/content/posts/2011-06-24-git-what-files-were-changed-since-the-last-release.md @@ -8,7 +8,9 @@ Sometimes it handy to get a list out of `git log` that tells you which files wer ~ Let's say you want to view all the changed files since the last tagged release, `v1.3.1`: - git log --reverse --name-status HEAD...v1.3.1 | grep -e ^[MAD][[:space:]] +``` shell +git log --reverse --name-status HEAD...v1.3.1 | grep -e ^[MAD][[:space:]] +``` As you're used to, this shows each files that *A*dded, *M*odified or *D*eleted. This command does not squash file changes. So it's possible for a file to first be added, the deleted, then added again and later modified. The `--reverse` option shows file changes historically, so the first file changed after the v1.3.1 release is shown first. diff --git a/content/posts/2011-06-27-your-mac-slow-disable-spotlight-in-snow-leopard.md b/content/posts/2011-06-27-your-mac-slow-disable-spotlight-in-snow-leopard.md index 28ba5e7..c92a3dc 100644 --- a/content/posts/2011-06-27-your-mac-slow-disable-spotlight-in-snow-leopard.md +++ b/content/posts/2011-06-27-your-mac-slow-disable-spotlight-in-snow-leopard.md @@ -1,9 +1,9 @@ -+++ -date = "2011-06-27" -title = "Your Mac slow? Disable Spotlight in Snow Leopard" -tags = ["MacOSX", "spotlight", "diskio"] -slug = "your-mac-slow-disable-spotlight-in-snow-leopard" -+++ ++++ +date = "2011-06-27" +title = "Your Mac slow? Disable Spotlight in Snow Leopard" +tags = ["MacOSX", "spotlight", "diskio"] +slug = "your-mac-slow-disable-spotlight-in-snow-leopard" ++++ For some time now I've experience my mac to be very slow. Opening Vim would take minutes. Creating a new Tab in iTerm would take more than 20 seconds. What the hell is going on - this is a brand new MacBook Pro! ~ After investigating, using _Activity Monitor_ I discovered the following: @@ -18,7 +18,9 @@ After investigating, using _Activity Monitor_ I discovered the following: So, something is using my disk. But what? The solution is to use the `iotop` utility: - sudo iotop -C 5 12 +``` shell +sudo iotop -C 5 12 +``` A common entry here is the `mds` procoess, which has an insane amount of `BYTES`. So, this `mds` process is causing a lot of I/O, causing things to get slow. @@ -30,7 +32,9 @@ A quick Google search reveals that the `mds` process is actually the Spotlight i I don't use Spotlight at all, so let's disable it - preventing the disk I/O. - sudo mdutil -a -i off +``` shell +sudo mdutil -a -i off +``` That's all. Spotlight indexing disabled. After a few seconds the disk I/O dropped from ± 450w/s to 0w/s. Vim starts ups again within a seconds. I'm happy. @@ -38,5 +42,6 @@ That's all. Spotlight indexing disabled. After a few seconds the disk I/O droppe If, for some obscure reason, you want to re-enable Spotlight, use the following command: - sudo mdutil -a -i on - +``` shell +sudo mdutil -a -i on +``` diff --git a/content/posts/2011-07-05-git-squash-your-latests-commits-into-one.md b/content/posts/2011-07-05-git-squash-your-latests-commits-into-one.md index 2b7b4d8..b052d34 100644 --- a/content/posts/2011-07-05-git-squash-your-latests-commits-into-one.md +++ b/content/posts/2011-07-05-git-squash-your-latests-commits-into-one.md @@ -1,39 +1,48 @@ -+++ -date = "2011-07-05" -title = "Git: Squash your latests commits into one" -tags = ["git", "rebase", "squash"] -slug = "git-squash-your-latests-commits-into-one" -+++ ++++ +date = "2011-07-05" +title = "Git: Squash your latests commits into one" +tags = ["git", "rebase", "squash"] +slug = "git-squash-your-latests-commits-into-one" ++++ + With git it's possible to squash previous commits into one. This is a great way to group certain changes together before sharing them with others. ~ Here's how to squash some commits into one. Let's say this is your current `git log`. - * df71a27 - (HEAD feature_x) Updated CSS for new elements (4 minutes ago) - * ba9dd9a - Added new elements to page design (15 minutes ago) - * f392171 - Added new feature X (1 day ago) - * d7322aa - (origin/feature_x) Proof of concept for feature X (3 days ago) +``` text +* df71a27 - (HEAD feature_x) Updated CSS for new elements (4 minutes ago) +* ba9dd9a - Added new elements to page design (15 minutes ago) +* f392171 - Added new feature X (1 day ago) +* d7322aa - (origin/feature_x) Proof of concept for feature X (3 days ago) +``` You have a branch `feature_x` here. You've already pushed `d7322aa` with the proof of concept of the new feature X. After that you've been working to add new element to the feature, including some changes in CSS. Now, you want to squash your last three commits in one to make your history look pretty. The command to accomplish that is: - git rebase -i HEAD~3 +``` shell +git rebase -i HEAD~3 +``` This will open up your editor with the following: - pick f392171 Added new feature X - pick ba9dd9a Added new elements to page design - pick df71a27 Updated CSS for new elements +``` text +pick f392171 Added new feature X +pick ba9dd9a Added new elements to page design +pick df71a27 Updated CSS for new elements +``` Now you can tell git what to do with each commit. Let's keep the commit `f392171`, the one were we added our feature. We'll squash the following two commits into the first one - leaving us with one clean commit with features X in it, including the added element and CSS. Change your file to this: - pick f392171 Added new feature X - squash ba9dd9a Added new elements to page design - squash df71a27 Updated CSS for new elements +``` text +pick f392171 Added new feature X +squash ba9dd9a Added new elements to page design +squash df71a27 Updated CSS for new elements +``` When done, save and quit your editor. Git will now squash the commits into one. All done! -Note: do not squash commits that you've already shared with others. You're changing history and it will cause trouble for others. - +Note: do not squash commits that you've already shared with others. You're changing history and it will cause trouble for others. + diff --git a/content/posts/2011-08-24-git-log-what-did-i-do-yesterday-exactly.md b/content/posts/2011-08-24-git-log-what-did-i-do-yesterday-exactly.md index 812af59..cdf87ef 100644 --- a/content/posts/2011-08-24-git-log-what-did-i-do-yesterday-exactly.md +++ b/content/posts/2011-08-24-git-log-what-did-i-do-yesterday-exactly.md @@ -1,37 +1,45 @@ -+++ -date = "2011-08-24" -title = "Git Log: What did I do yesterday, exactly?" -tags = ["git"] -slug = "git-log-what-did-i-do-yesterday-exactly" -+++ ++++ +date = "2011-08-24" +title = "Git Log: What did I do yesterday, exactly?" +tags = ["git"] +slug = "git-log-what-did-i-do-yesterday-exactly" ++++ Sometimes you have to take your git repository's log to see what you did the day before (ideal in preparation for the daily stand-up). What I want is a clean overview of each commit messages, their author and the time. The output result should be easily grep-able so I can filter stuff I don't need out. ~ To do this, I use the following custom `git log` command: - git log --pretty=format:'%Cred%h%Creset - %C(yellow)%ae%Creset - %Cgreen%cd%Creset - %s%Creset' --abbrev-commit --date=iso +``` shell +git log --pretty=format:'%Cred%h%Creset - %C(yellow)%ae%Creset - %Cgreen%cd%Creset - %s%Creset' --abbrev-commit --date=iso +``` The result: - 5d6ef1e - ariejan@ariejan.net - 2011-05-02 10:36:43 +0200 - Bumped to version 1.5.2 - afede9e - ariejan@ariejan.net - 2011-05-02 10:35:53 +0200 - Fixed #29 - Sharing to facebook without a title now works properly. - d9985a1 - ariejan@ariejan.net - 2011-04-23 00:13:06 -0700 - Added Travis build status to README - 3e1149c - ariejan@ariejan.net - 2011-04-22 13:44:21 +0200 - Bumped version to 1.5.1 - fcab3bf - ariejan@ariejan.net - 2011-04-22 13:43:41 +0200 - Don't test on ruby 1.9.2 for now. See issue #27 - 93843ec - ariejan@ariejan.net - 2011-04-22 13:42:29 +0200 - Fixed issue #28 - Share-to-* double-encodes titles - ec56315 - ariejan@ariejan.net - 2011-04-22 12:43:41 +0200 - Fixed up utf-8 encoding for ruby 1.9.2 - 2146134 - ariejan@ariejan.net - 2011-04-22 12:39:37 +0200 - Bump Sinatra to 1.2.3 - c5efbf4 - ariejan@ariejan.net - 2011-04-22 12:07:41 +0200 - Truncate long URLs in the back-end to maintain a correct layout. +``` text +5d6ef1e - ariejan@ariejan.net - 2011-05-02 10:36:43 +0200 - Bumped to version 1.5.2 +afede9e - ariejan@ariejan.net - 2011-05-02 10:35:53 +0200 - Fixed #29 - Sharing to facebook without a title now works properly. +d9985a1 - ariejan@ariejan.net - 2011-04-23 00:13:06 -0700 - Added Travis build status to README +3e1149c - ariejan@ariejan.net - 2011-04-22 13:44:21 +0200 - Bumped version to 1.5.1 +fcab3bf - ariejan@ariejan.net - 2011-04-22 13:43:41 +0200 - Don't test on ruby 1.9.2 for now. See issue #27 +93843ec - ariejan@ariejan.net - 2011-04-22 13:42:29 +0200 - Fixed issue #28 - Share-to-* double-encodes titles +ec56315 - ariejan@ariejan.net - 2011-04-22 12:43:41 +0200 - Fixed up utf-8 encoding for ruby 1.9.2 +2146134 - ariejan@ariejan.net - 2011-04-22 12:39:37 +0200 - Bump Sinatra to 1.2.3 +c5efbf4 - ariejan@ariejan.net - 2011-04-22 12:07:41 +0200 - Truncate long URLs in the back-end to maintain a correct layout. +``` Now, it's easy to see what I did on april 22nd using grep - git logThe content of this post is no longer correct. Please read this article for details.
Testing scopes has always felt a bit weird to me. Normally I'd do something like this: - class Post < ActiveRecord::Base - scope :published, where(:published => true) - scope :latest, order("created_at DESC") +``` ruby +class Post < ActiveRecord::Base + scope :published, where(:published => true) + scope :latest, order("created_at DESC") +end + +describe Post do + context 'scopes' do + before(:all) do + @first = FactoryGirl.create(:post, :created_at => 1.day.ago, :published => true) + @last = FactoryGirl.create(:post, :created_at => 4.day.ago, :published => false) end - describe Post do - context 'scopes' do - before(:all) do - @first = FactoryGirl.create(:post, :created_at => 1.day.ago, :published => true) - @last = FactoryGirl.create(:post, :created_at => 4.day.ago, :published => false) - end - - it "should only return published posts" do - Post.published.should == [@first] - end - - it "should return posts in the correct order" do - Post.latest.should == [@first, @last] - end - end + it "should only return published posts" do + Post.published.should == [@first] end + it "should return posts in the correct order" do + Post.latest.should == [@first, @last] + end + end +end +``` + This test is okay. It tests if the named scope does what it needs to do. And there's also the problem. Scopes are part of ActiveRecord and are already extensively tested there. All we need to do is check if we _configure_ the scope correctly. What we need is a way to inspect what `where` and `order` rules are set for a particular scope and make sure those are the correct ones. We can then trust ActiveRecord to keep its promise to execute the proper SQL query for us. Here's another test that utilizes some Rails 3 methods you may not have heard of before. - describe Post do - context 'scopes' do - it "should only return published posts" do - Post.published.where_values_hash.should == {:published => true} - end - - it "should return posts in the correct order" do - Post.latest.order_values.should == ["created_at DESC"] - end - end +``` ruby +describe Post do + context 'scopes' do + it "should only return published posts" do + Post.published.where_values_hash.should == {:published => true} end + it "should return posts in the correct order" do + Post.latest.order_values.should == ["created_at DESC"] + end + end +end +``` + The `where_values_hash` and `order_values` allow you to inspect what a scopes doing. By writing your test this way you achieve two import goals: 1. You test _your_ code (instead of the ActiveRecord) 2. You don't use the database, which is a significant speed boost -Happy testing to you all! - +Happy testing to you all! + diff --git a/content/posts/2011-10-09-testing-rails-3-scopes-revisited.md b/content/posts/2011-10-09-testing-rails-3-scopes-revisited.md index d306d3d..9e53817 100644 --- a/content/posts/2011-10-09-testing-rails-3-scopes-revisited.md +++ b/content/posts/2011-10-09-testing-rails-3-scopes-revisited.md @@ -1,9 +1,9 @@ -+++ -date = "2011-10-09" -title = "Testing Rails 3 scopes revisited" -tags = ["Ruby on Rails", "Rails", "rspec", "rails3", "scope", "named_scope"] -slug = "testing-rails-3-scopes-revisited" -+++ ++++ +date = "2011-10-09" +title = "Testing Rails 3 scopes revisited" +tags = ["Ruby on Rails", "Rails", "rspec", "rails3", "scope", "named_scope"] +slug = "testing-rails-3-scopes-revisited" ++++ In my [previous article][pa] I told you about how I like to tests my scope. There was a fair amount of criticism on that post and after considering it all (and hearing Corey Haines' talk on Arrrrcamp last friday), I'm convinced it's the wrong path. In essence Rails allows you to create a scope to generate a custom database query for you. Now, if you only test your configuration of Rails (as I did in my previous post), you don't know if that scope works or not. If a piece directly relies on your database, you must test it against your database. @@ -12,26 +12,28 @@ Also, your configuration may be correct, but what happens when you upgrade to a So, this is the proper way of testing your scopes: - class Post < ActiveRecord::Base - scope :latest, order("created_at DESC") +``` ruby +class Post < ActiveRecord::Base + scope :latest, order("created_at DESC") +end + +describe Post do + context 'scopes' do + before(:all) do + @first = FactoryGirl.create(:post, :created_at => 1.day.ago) + @last = FactoryGirl.create(:post, :created_at => 4.day.ago) end - describe Post do - context 'scopes' do - before(:all) do - @first = FactoryGirl.create(:post, :created_at => 1.day.ago) - @last = FactoryGirl.create(:post, :created_at => 4.day.ago) - end - - it "should return posts in the correct order" do - Post.latest.should == [@first, @last] - end - end + it "should return posts in the correct order" do + Post.latest.should == [@first, @last] end + end +end +``` ## A note on speed So, you now have to utilize the whole Rails stack _and_ hit your database to perform this test, which is slow. But then you don't upgrade Rails or your database very often, so you don't have run this spec with every TDD Baby Step you take. (More on that in a later post.) -[pa]: http://ariejan.net/2011/09/25/properly-testing-rails-3-scopes - +[pa]: http://ariejan.net/2011/09/25/properly-testing-rails-3-scopes + diff --git a/content/posts/2011-10-13-fast-specs-run-your-specs-in-less-than-1-second.md b/content/posts/2011-10-13-fast-specs-run-your-specs-in-less-than-1-second.md index faf5691..03dbd9b 100644 --- a/content/posts/2011-10-13-fast-specs-run-your-specs-in-less-than-1-second.md +++ b/content/posts/2011-10-13-fast-specs-run-your-specs-in-less-than-1-second.md @@ -1,9 +1,9 @@ -+++ -date = "2011-10-13" -title = "Fast specs - Run your specs in less than 1 second" -tags = ["Ruby", "Rails", "rspec", "testing", "bdd", "tdd", "cucumber", "fast_spec", "fastspec", "coreyhaines"] -slug = "fast-specs-run-your-specs-in-less-than-1-second" -+++ ++++ +date = "2011-10-13" +title = "Fast specs - Run your specs in less than 1 second" +tags = ["Ruby", "Rails", "rspec", "testing", "bdd", "tdd", "cucumber", "fast_spec", "fastspec", "coreyhaines"] +slug = "fast-specs-run-your-specs-in-less-than-1-second" ++++ Okay, let me clarify that title first. I, as most of you, have two sets of tests for my Rails application: rspec and cucumber. rspec heavily focusses on testing models and business logic while cucumber focusses on testing the entire application stack and user interaction. The problem is that as your app grows, your test set grows - and so does the time it takes to run those tests. @@ -29,39 +29,45 @@ So, let's take a closer look at a real-world example. This is a `Post` model, it `belongs_to` and author and it can give you a summary of an article by returning the text above a '~' marker. - # app/models/post.rb - class Post < ActiveRecord::Base - DELIMITER = "~\n" +``` ruby +# app/models/post.rb +class Post < ActiveRecord::Base + DELIMITER = "~\n" - belongs_to :author + belongs_to :author - def summary - summary = if body =~ /#{DELIMITER}/i - body.split(/#{DELIMITER}/i).first.strip - else - body - end - end + def summary + summary = if body =~ /#{DELIMITER}/i + body.split(/#{DELIMITER}/i).first.strip + else + body end + end +end +``` This is a spec that's defined for the `Post` model: - # spec/models/post_spec.rb - require 'spec/helper' +``` ruby +# spec/models/post_spec.rb +require 'spec/helper' - describe Post do - context "summary" do - it "should return the summary" do - post = FactoryGirl.build(:post, :body => "Summary\n~\nNo summary.") - post.summary.should == "Summary" - end - end +describe Post do + context "summary" do + it "should return the summary" do + post = FactoryGirl.build(:post, :body => "Summary\n~\nNo summary.") + post.summary.should == "Summary" end + end +end +``` Running this spec would take at least 10 seconds. Running `time rspec spec/models/post_spec.rb` woudl output something like this: - Finished in 0.05523 seconds - real 0m10.387s +``` text +Finished in 0.05523 seconds +real 0m10.387s +``` This means that running the actual spec took 0.05s, but running the entire command took 10 seconds. What is slowing us down? @@ -91,20 +97,22 @@ There are a lot of scenarios where the answer to that question is _NO_. This may seem a bit weird at first, but let's take another look at the `Post` model: - # app/models/post.rb - class Post < ActiveRecord::Base - DELIMITER = "~\n" +``` ruby +# app/models/post.rb +class Post < ActiveRecord::Base + DELIMITER = "~\n" - belongs_to :author + belongs_to :author - def summary - summary = if body =~ /#{DELIMITER}/i - body.split(/#{DELIMITER}/i).first.strip - else - body - end - end + def summary + summary = if body =~ /#{DELIMITER}/i + body.split(/#{DELIMITER}/i).first.strip + else + body end + end +end +``` The `summary` method does not interact with the `Post` model at all, except that it access the `body` attribute. But the `body` attribute is just a `String`. @@ -112,18 +120,20 @@ So, if we wanted to test the `summary` method and remove all Rails dependencies, Consider this: - # app/logic/myapp/summary.rb - module MyApp - class Summary - def self.for(text, delimiter) - summary = if text =~ /#{delimiter}/i - text.split(/#{delimiter}/i).first.strip - else - text - end - end +``` ruby +# app/logic/myapp/summary.rb +module MyApp + class Summary + def self.for(text, delimiter) + summary = if text =~ /#{delimiter}/i + text.split(/#{delimiter}/i).first.strip + else + text end end + end +end +``` I think you can quickly see that this method does exactly the same as `Post#summary`. But it does not have any dependency to ActiveRecord. @@ -144,31 +154,35 @@ That looks good! Note that this spec _does not_ include `spec_helper`. `spec_hel The `Post` model should also be updated, of course to utilise this new class. - # app/models/post.rb - class Post < ActiveRecord::Base - DELIMITER = "~\n" +``` ruby +# app/models/post.rb +class Post < ActiveRecord::Base + DELIMITER = "~\n" - belongs_to :author + belongs_to :author - def summary - MyApp::Summary.for(body, DELIMITER) - end - end + def summary + MyApp::Summary.for(body, DELIMITER) + end +end +``` The spec for `Post` should also be changed. Since we already have tested that `MyApp::Summary#for` returns the right summary for a given text and delimiter, all we have left to do is make sure that `Post#summary` calls it correctly. - # spec/models/post_spec.rb - require 'spec/helper' +``` ruby +# spec/models/post_spec.rb +require 'spec/helper' - describe Post do - context "summary" do - it "should return the summary" do - post = FactoryGirl.build(:post) - MyApp::Summary.should_receive(:for).with(post.body, Post::DELIMITER) - post.summary - end - end +describe Post do + context "summary" do + it "should return the summary" do + post = FactoryGirl.build(:post) + MyApp::Summary.should_receive(:for).with(post.body, Post::DELIMITER) + post.summary end + end +end +``` ## Running fast specs @@ -176,12 +190,16 @@ The files above are located in `fast_spec` and `app/logic`. I do this because I Running fast specs works like this: - rspec -I app/logic fast_spec +``` shell +rspec -I app/logic fast_spec +``` Try it out with `time rspec -I app/logic fast_spec`: - Finished in 0.03223 seconds - real 0m0.421s +``` text +Finished in 0.03223 seconds +real 0m0.421s +``` That's your same spec, down from about 10 seconds to 0.5 second. @@ -217,5 +235,5 @@ As Corey Haines put it: This would also be my advise to you. Try to extract one piece of functionality from a model into a fast_spec. It may be difficult at first, but try it and see the results. -Then, when you have that one example working, add more. - +Then, when you have that one example working, add more. + diff --git a/content/posts/2011-10-14-rails-3-customized-exception-handling.md b/content/posts/2011-10-14-rails-3-customized-exception-handling.md index 28b2e03..a3bae48 100644 --- a/content/posts/2011-10-14-rails-3-customized-exception-handling.md +++ b/content/posts/2011-10-14-rails-3-customized-exception-handling.md @@ -1,19 +1,21 @@ -+++ -date = "2011-10-14" -title = "Rails 3: Customized exception handling" -tags = ["Rails", "rails3", "exceptions", "error", "rescue"] -slug = "rails-3-customized-exception-handling" -+++ ++++ +date = "2011-10-14" +title = "Rails 3: Customized exception handling" +tags = ["Rails", "rails3", "exceptions", "error", "rescue"] +slug = "rails-3-customized-exception-handling" ++++ Exceptions happen. There's no way around that. But not all exceptions are created equally. For instance, a 404 "Not found" error can (and should) be handled correctly in your application. Let me give you an example of how to handle a `ActiveRecord::RecordNotFound` exception. Let's assume you have an application that could show a user profile: - # GET /p/:name - def show - @profile = Profile.find(params[:name]) - end +``` ruby +# GET /p/:name +def show + @profile = Profile.find(params[:name]) +end +``` Now, it may happen that the `:name` paramater contains a value that cannot be found in our database, most likely because someone made a typo in the URL. @@ -25,12 +27,14 @@ Now, instead of showing the user the (by default ugly) 404 page from `public/404 Here's one solution: - # GET /p/:name - def show - @profile = Profile.find(params[:name]) - rescue - render :template => 'application/profile_not_found', :status => :not_found - end +``` ruby +# GET /p/:name +def show + @profile = Profile.find(params[:name]) +rescue + render :template => 'application/profile_not_found', :status => :not_found +end +``` You can now create `app/views/applicaiton/profile_not_found.html.haml` and give a nice custom error message to your user. @@ -42,21 +46,25 @@ The above example only works for the specific profile `show` action. It's also p Your `show` action still looks like this: - # GET /p/:name - def show - @profile = Profile.find(params[:name]) - end +``` ruby +# GET /p/:name +def show + @profile = Profile.find(params[:name]) +end +``` Then, in your `app/controllers/application_controller.rb` add this: - class ApplicationController < ActionController::Base - rescue_from ActiveRecord::RecordNotFound, :with => :rescue_not_found +``` ruby +class ApplicationController < ActionController::Base + rescue_from ActiveRecord::RecordNotFound, :with => :rescue_not_found - protected - def rescue_not_found - render :template => 'application/not_found', :status => :not_found - end - end + protected + def rescue_not_found + render :template => 'application/not_found', :status => :not_found + end +end +``` Whenever an `ActiveRecord::RecordNotFound` exception is thrown (and not handled by the action itself), it will be handled by your `ApplicationController`. @@ -64,24 +72,29 @@ Whenever an `ActiveRecord::RecordNotFound` exception is thrown (and not handled It's possible to throw your own custom exceptions and handle them in different ways. Like this: - # Define your own error - class MyApp::ProfileNotFoundError < StandardError - end +``` ruby +# Define your own error +class MyApp::ProfileNotFoundError < StandardError +end - # GET /p/:name - def show - @profile = Profile.find_by_name(params[:name]) - raise MyApp::ProfileNotFoundError if @profile.nil? - end +# GET /p/:name +def show + @profile = Profile.find_by_name(params[:name]) + raise MyApp::ProfileNotFoundError if @profile.nil? +end +``` And add this to your `ApplicationController`: - rescue_from MyApp::ProfileNotFoundError, :with => :profile_not_found +``` ruby +rescue_from MyApp::ProfileNotFoundError, :with => :profile_not_found +``` Optionally, if you don't want to write that custom `profile_not_found` method, you may also supply a block: - rescue_from MyApp::ProfileNotFoundError do |exception| - render :nothing => "Profile not found.", :status => 404 - end - - +``` ruby +rescue_from MyApp::ProfileNotFoundError do |exception| + render :nothing => "Profile not found.", :status => 404 +end +``` + diff --git a/content/posts/2011-10-22-automatically-switch-between-ssl-and-non-ssl-with-nginx-unicorn-rails.md b/content/posts/2011-10-22-automatically-switch-between-ssl-and-non-ssl-with-nginx-unicorn-rails.md index 6ec84ed..09ac21a 100644 --- a/content/posts/2011-10-22-automatically-switch-between-ssl-and-non-ssl-with-nginx-unicorn-rails.md +++ b/content/posts/2011-10-22-automatically-switch-between-ssl-and-non-ssl-with-nginx-unicorn-rails.md @@ -1,9 +1,10 @@ -+++ -date = "2011-10-22" -title = "Automatically switch between SSL and non-SSL with Nginx+Unicorn+Rails" -tags = ["Rails", "rails3", "unicorn", "nginx", "ssl"] -slug = "automatically-switch-between-ssl-and-non-ssl-with-nginx-unicorn-rails" -+++ ++++ +date = "2011-10-22" +title = "Automatically switch between SSL and non-SSL with Nginx+Unicorn+Rails" +tags = ["Rails", "rails3", "unicorn", "nginx", "ssl"] +slug = "automatically-switch-between-ssl-and-non-ssl-with-nginx-unicorn-rails" ++++ + _Scroll down for setup instructions. Or, read this bit about SSL in the real world first._ SSL or Secure Socket Layer is a nice way to secure sensitive parts of your Rails application. It achieves to goals. @@ -25,9 +26,11 @@ In the example above Rabobank uses an [EV SSL Certificate][evssl]. EV stands for The cost for such an EV SSL Certificate is $200 - $1000 per year. You probably don't need it for your site. ## SSL for you and me + When you are looking to secure the back-end of your site (where you login etc.), you only require the encryption part of SSL. There are two routes you can take ### Self signed SSL + You are able to create a working SSL certificate yourself. This will give you encryption, but no identity validation. When you use a self-signed SSL certificate all browsers will warn you about this. * Encryption @@ -38,6 +41,7 @@ You are able to create a working SSL certificate yourself. This will give you en For me, that's a reason not to use self signed SSL for any other than development and testing purposes. ### Standard SSL + Most SSL authorities provide you with a _Standard SSL_ product. These certificates only check if you own the domainname. They also offer encryption and work (without warnings) in your browser. You can get one of these for as little as $9 a year. * Encryption @@ -46,6 +50,7 @@ Most SSL authorities provide you with a _Standard SSL_ product. These certificat * Cheap ($10 - $20) ## Setting up SSL for your Rails application + Setting up SSL is a web server thing. It does not involve your Rails appliation directly (but more on that in a moment). If you followed my [nginx+unicorn][nu] guide, you'll have Nginx and Unicorn setup already. @@ -56,13 +61,15 @@ If you followed my [nginx+unicorn][nu] guide, you'll have Nginx and Unicorn setu First you need to create a private key. Do this on you server. The following command will generate a 2048 bit key. When it asks you to set a passphrase, do so. - $ openssl genrsa -des3 -out example.com.key 2048 - Generating RSA private key, 2048 bit long modulus - ..................................+++ - .................................................................................+++ - e is 65537 (0x10001) - Enter pass phrase for example.com.key: - Verifying - Enter pass phrase for example.com.key: +``` shell +$ openssl genrsa -des3 -out example.com.key 2048 +Generating RSA private key, 2048 bit long modulus +..................................+++ +.................................................................................+++ +e is 65537 (0x10001) +Enter pass phrase for example.com.key: +Verifying - Enter pass phrase for example.com.key: +``` ### Creating a key and Certificate Sign Request (csr) @@ -78,27 +85,29 @@ Okay, you now have your key. Next step, create the Certificate Sign Request. The Here's the full version: - $ openssl req -new -key example.com.key -out example.com.csr - Enter pass phrase for example.com.key: <Do not rebase if you already pushed your branch to Github. Read why.
- git checkout fix_for_this_or_that - git rebase master +``` shell +git checkout fix_for_this_or_that +git rebase master +``` If any conflict arise, fix them. And continue your rebase: - git add conflicting_file - git rebase --continue +``` shell +git add conflicting_file +git rebase --continue +``` You may also abort the rebase: - git rebase --abort +``` shell +git rebase --abort +``` ## Big picture -This small guide will help you to fork repositories on Github and use them to contribute code. By using the approach you lighten the task of the project maintainer who can easily checkout your specific changes and decide to include them into the main project or not. - +This small guide will help you to fork repositories on Github and use them to contribute code. By using the approach you lighten the task of the project maintainer who can easily checkout your specific changes and decide to include them into the main project or not. + diff --git a/content/posts/2011-11-18-deploying-a-third-party-rails-application-like-gitlab.md b/content/posts/2011-11-18-deploying-a-third-party-rails-application-like-gitlab.md index b935086..ac36597 100644 --- a/content/posts/2011-11-18-deploying-a-third-party-rails-application-like-gitlab.md +++ b/content/posts/2011-11-18-deploying-a-third-party-rails-application-like-gitlab.md @@ -1,9 +1,9 @@ -+++ -date = "2011-11-18" -title = "Deploying a third-party Rails application - like Gitlab" -tags = ["Capistrano", "github", "gitlab", "deploy"] -slug = "deploying-a-third-party-rails-application-like-gitlab" -+++ ++++ +date = "2011-11-18" +title = "Deploying a third-party Rails application - like Gitlab" +tags = ["Capistrano", "github", "gitlab", "deploy"] +slug = "deploying-a-third-party-rails-application-like-gitlab" ++++ We all know how to deploy our own Rails projects. (If not, [read this guide][1].) But how do you handle deploying a third-party application that may require some customisation on your part? A good example would be [Gitlab][gitlab] @@ -22,15 +22,19 @@ Here's how I set everything up. First, clone the official Gitlab repository and name it `upstream`. - git clone --origin upstream https://github.com/gitlabhq/gitlabhq.git my_git_server +``` shell +git clone --origin upstream https://github.com/gitlabhq/gitlabhq.git my_git_server +``` Next I made all the changes I want. I updated `config/gitosis.yml` and `unicorn` to `Gemfile` and setup Capistrano. I then pushed this to my own git server. This is the same server Capistrano will use to pull changes from. - git remote add origin git@git.ariejan.net:my_git_server.git - git push origin master - cap deploy +``` shell +git remote add origin git@git.ariejan.net:my_git_server.git +git push origin master +cap deploy +``` That's all there is to deploying Gitlab from my own repository. @@ -38,18 +42,24 @@ That's all there is to deploying Gitlab from my own repository. Now, the Gitlab crew is pushing out new features at an amazing rate. So, how do I get those new features (and the occasional bug fix) into my copy of Gitlab for deploying? - git fetch upstream +``` shell +git fetch upstream +``` Remember how we named the official Gitlab repository `upstream` earlier? With this `fetch` we get all changes from their repository (but we don't apply them to anything yet). Then, merge the upstream changes with your own branch. - git merge upstream/master +``` shell +git merge upstream/master +``` There may be merge conflicts, just resolve them and commit your merge. Then again to deploy: - git push origin master - cap deploy +``` shell +git push origin master +cap deploy +``` ## Why do this? @@ -61,5 +71,5 @@ The reason I use this approach is that it's easy to merge upstream changes and h [3]: http://nepalonrails.tumblr.com/post/12603081685/setup-gitlab-github-clone-using-vagrant-and-chef [4]: http://ariejan.net/2011/11/09/contributing-to-open-source-with-github - - + + diff --git a/content/posts/2011-11-22-upgrade-postgresql-8-4-to-postgresql-9-1-on-debian.md b/content/posts/2011-11-22-upgrade-postgresql-8-4-to-postgresql-9-1-on-debian.md index 8b70646..dce51d4 100644 --- a/content/posts/2011-11-22-upgrade-postgresql-8-4-to-postgresql-9-1-on-debian.md +++ b/content/posts/2011-11-22-upgrade-postgresql-8-4-to-postgresql-9-1-on-debian.md @@ -1,29 +1,35 @@ -+++ -date = "2011-11-22" -title = "Upgrade postgresql-8.4 to postgresql-9.1 on debian" -tags = ["Ubuntu", "debian", "dba", "postgres", "postgresql"] -slug = "upgrade-postgresql-8-4-to-postgresql-9-1-on-debian" -+++ ++++ +date = "2011-11-22" +title = "Upgrade postgresql-8.4 to postgresql-9.1 on debian" +tags = ["Ubuntu", "debian", "dba", "postgres", "postgresql"] +slug = "upgrade-postgresql-8-4-to-postgresql-9-1-on-debian" ++++ Today I upgraded a production PostgreSQL 8.4 database to version 9.1. This was on a Debian server. ~ The first step is to make a full dump of your data. I personally like to store that dump somewhere safe before upgrading. As root: - su - postgres - pg_dumpall > dump.sql - exit - cp ~postgres/dump.sql /root/ +``` shell +su - postgres +pg_dumpall > dump.sql +exit +cp ~postgres/dump.sql /root/ +``` Now you can safely remove the postgresql-8.4 and install postgresql-9.1: - aptitude purge postgresql-8.4 - aptitude install postgresql-9.1 +``` shell +aptitude purge postgresql-8.4 +aptitude install postgresql-9.1 +``` Next check the postgresql configuration in `/etc/postgresql/9.1/main`. If you make any changes, make sure to restart postgres with `/etc/init.d/postgresql restart`. Postgresql 9.1 is now up and running, let's import our data back into it. - su - postgres - psql < dump.sql +``` shell +su - postgres +psql < dump.sql +``` + +That's all. You're now fully upgraded to PostgreSQL 9.1. -That's all. You're now fully upgraded to PostgreSQL 9.1. - diff --git a/content/posts/2011-12-13-recursively-fixing-file-and-directory-permissions.md b/content/posts/2011-12-13-recursively-fixing-file-and-directory-permissions.md index 23f3bb8..4c16bf2 100644 --- a/content/posts/2011-12-13-recursively-fixing-file-and-directory-permissions.md +++ b/content/posts/2011-12-13-recursively-fixing-file-and-directory-permissions.md @@ -1,26 +1,28 @@ -+++ -date = "2011-12-13" -title = "Recursively fixing file and directory permissions" -tags = ["Linux", "BASH", "git", "sh", "file permissions"] -slug = "recursively-fixing-file-and-directory-permissions" -+++ ++++ +date = "2011-12-13" +title = "Recursively fixing file and directory permissions" +tags = ["Linux", "BASH", "git", "sh", "file permissions"] +slug = "recursively-fixing-file-and-directory-permissions" ++++ While working on a [Gitlab][1] installation I noticed that all repository file permissions were off. Fixing recursive file and directory permissions can be quite hard. Or so I thought. Using the following commands (in plain Bash) allow you to recursively set permissions for files and directories. So, to fix the proper read permissions on your Gitlab repositories you can use this: - # Go to your git repositories directory (as git or the gitlab user) - cd /home/git/repositories +``` shell +# Go to your git repositories directory (as git or the gitlab user) +cd /home/git/repositories - # Fix ownership - sudo chown -R git:git * +# Fix ownership +sudo chown -R git:git * - # Fix directory permissions - sudo find -type d -exec chmod 770 {} \; +# Fix directory permissions +sudo find -type d -exec chmod 770 {} \; - # Fix file permissions - sudo find -type f -exec chmod 660 {} \; +# Fix file permissions +sudo find -type f -exec chmod 660 {} \; +``` After this, your Gitlab should have no trouble accessing your code (e.g. in the tree browser). -[1]: http://gitlabhq.com/ - +[1]: http://gitlabhq.com/ + diff --git a/content/posts/2012-04-14-decorating-devise-s-current_user-with-draper.md b/content/posts/2012-04-14-decorating-devise-s-current_user-with-draper.md index 9a8caf7..baaca6d 100644 --- a/content/posts/2012-04-14-decorating-devise-s-current_user-with-draper.md +++ b/content/posts/2012-04-14-decorating-devise-s-current_user-with-draper.md @@ -1,20 +1,22 @@ -+++ -date = "2012-04-14" -title = "Decorating Devise's current_user with Draper" -tags = ["Rails", "devise", "draper", "decorators"] -slug = "decorating-devise-s-current_user-with-draper" -+++ ++++ +date = "2012-04-14" +title = "Decorating Devise's current_user with Draper" +tags = ["Rails", "devise", "draper", "decorators"] +slug = "decorating-devise-s-current_user-with-draper" ++++ I've become a big fan of decorators, especially [Draper](https://github.com/jcasimir/draper). Decorators allow you to move view related functionality for your models in to separate decorator classes. This keeps both your models and views clean and readable. Anyway, if you use Devise you're provided with a `current_user` helper. However, this helper returns an instance of `User` - without your decorators. To enable decorators for your `current_user` by default, simple add this to `app/controllers/application_controller.rb`: - def current_user - UserDecorator.decorate(super) unless super.nil? - end +``` ruby +def current_user + UserDecorator.decorate(super) unless super.nil? +end +``` Now, anywhere in your views where you call `current_user` you'll get a decorated version instead. -[Check here to see how to use Draper with Sorcery](http://ariejan.net/2012/11/02/decorating_sorcery_current_user_with_draper) - +[Check here to see how to use Draper with Sorcery](http://ariejan.net/2012/11/02/decorating_sorcery_current_user_with_draper) + diff --git a/content/posts/2012-05-22-ruby-regex-scanning-in-a-case-statement.md b/content/posts/2012-05-22-ruby-regex-scanning-in-a-case-statement.md index fd240c9..ff219d9 100644 --- a/content/posts/2012-05-22-ruby-regex-scanning-in-a-case-statement.md +++ b/content/posts/2012-05-22-ruby-regex-scanning-in-a-case-statement.md @@ -1,17 +1,19 @@ -+++ -date = "2012-05-22" -title = "Ruby: regex scanning in a case statement" -tags = ["Ruby", "snippet"] -slug = "ruby-regex-scanning-in-a-case-statement" -+++ ++++ +date = "2012-05-22" +title = "Ruby: regex scanning in a case statement" +tags = ["Ruby", "snippet"] +slug = "ruby-regex-scanning-in-a-case-statement" ++++ Here's a handy ruby snippet that might come in handy one day. When the regex matches (input should end with " today"), you can directly grab the matched value using the special `$1` variable. - case input - when /(.*)\stoday$/i then - puts "Today: #{$1}" - end +``` ruby +case input +when /(.*)\stoday$/i then + puts "Today: #{$1}" +end +``` + +I think you can see how you can bend this to your own needs. -I think you can see how you can bend this to your own needs. - diff --git a/content/posts/2012-05-24-seo-is-bullshit.md b/content/posts/2012-05-24-seo-is-bullshit.md index a5b0875..c04bbcb 100644 --- a/content/posts/2012-05-24-seo-is-bullshit.md +++ b/content/posts/2012-05-24-seo-is-bullshit.md @@ -1,9 +1,9 @@ -+++ -date = "2012-05-24" -title = "SEO is bullshit" -tags = ["Opinion", "seo", "rant"] -slug = "seo-is-bullshit" -+++ ++++ +date = "2012-05-24" +title = "SEO is bullshit" +tags = ["Opinion", "seo", "rant"] +slug = "seo-is-bullshit" ++++ @@ -42,8 +42,10 @@ If your content is good, readers will find it. Link to it. Tweet about it. And c No, that's not whaty I'm saying. META tags _do_ prodide information to crawlers, you should not assume they use that information in any way. For example, Ariejan.net has these META-tags: - - +``` html + + +``` In Google, this results in a view like this: @@ -55,5 +57,5 @@ Do note that the posts listed are considered popular by Google. Those are the po If you get an email, promising you that for $200 you're site will be ranked nr. 1 for specific keywords: throw it away. -The best SEO is writing awesome content people want to read. - +The best SEO is writing awesome content people want to read. + diff --git a/content/posts/2012-06-18-search-and-replace-in-multiple-files-with-vim.md b/content/posts/2012-06-18-search-and-replace-in-multiple-files-with-vim.md index ba80278..6f27977 100644 --- a/content/posts/2012-06-18-search-and-replace-in-multiple-files-with-vim.md +++ b/content/posts/2012-06-18-search-and-replace-in-multiple-files-with-vim.md @@ -1,43 +1,56 @@ -+++ -date = "2012-06-18" -title = "Search and Replace in multiple files with Vim" -tags = ["Rails", "vim"] -slug = "search-and-replace-in-multiple-files-with-vim" -+++ -I recently learned a nice VimTrick™ when paring with [Arjan](http://arjanvandergaag.nl). We upgrade an app to Rails 3.2.6 and got the following deprecation message: ++++ +date = "2012-06-18" +title = "Search and Replace in multiple files with Vim" +tags = ["Rails", "vim"] +slug = "search-and-replace-in-multiple-files-with-vim" ++++ - DEPRECATION WARNING: :confirm option is deprecated and will be removed from Rails 4.0. - Use ':data => { :confirm => 'Text' }' instead. +I recently learned a nice VimTrick™ when pairing with [Arjan](http://arjanvandergaag.nl). We upgrade an app to Rails 3.2.6 and got the following deprecation message: + +``` text +DEPRECATION WARNING: :confirm option is deprecated and will be removed from Rails 4.0. +Use ':data => { :confirm => 'Text' }' instead. +``` Well, nothing difficult about that, but we have quite a few `:confirm` in this app. Firstly we checked where we used them (note we use ruby 1.9 hash syntax everywhere): - $ ack -l "confirm:" app +``` shell +ack -l "confirm:" app +``` Now you have a listing of all the files that contain the `:confirm` hash key. You can leave out the `-l` option to get some context for each find. Now, we need to open Vim with those files: - $ ack -l "confirm:" app | xargs -o vim +``` shell +ack -l "confirm:" app | xargs -o vim +``` Vim will open the first of these files. Here's a snippet of what you may find: - = link_to "Delete", something_path, confirm: "Are you sure?" +``` haml += link_to "Delete", something_path, confirm: "Are you sure?" +``` Now, search and replace is easy: - :%s/confirm: ".*"/data: { & }/g +``` vim +:%s/confirm: ".*"/data: { & }/g +``` This will surround the current confirm with the `data` hash. Just the way Rails likes it. The `&` character will be replaced with whatever text matched the search pattern. You could repeat this for every file manually. But, you're using Vim. - :argdo %s/confirm: ".*"/data: { & }/g | update +``` vim +:argdo %s/confirm: ".*"/data: { & }/g | update +``` This will perform the search and replace on each of the supplied arguments (in this case the files selected with `ack`) and update (e.g. save) those files. Now you can quit Vim and enjoy the glory of all the disappearing deprecation warnings. -Note: to do this with the ruby 1.8 hash syntax, just update the search and replace texts accordingly. - +Note: to do this with the ruby 1.8 hash syntax, just update the search and replace texts accordingly. + diff --git a/content/posts/2012-07-11-vpn-too-complicated-use-a-ip-over-ssh-tunnel-instead.md b/content/posts/2012-07-11-vpn-too-complicated-use-a-ip-over-ssh-tunnel-instead.md index d67be40..00a90c8 100644 --- a/content/posts/2012-07-11-vpn-too-complicated-use-a-ip-over-ssh-tunnel-instead.md +++ b/content/posts/2012-07-11-vpn-too-complicated-use-a-ip-over-ssh-tunnel-instead.md @@ -1,16 +1,18 @@ -+++ -date = "2012-07-11" -title = "VPN too complicated? Use a IP-over-SSH tunnel instead" -tags = ["ssh", "vpn", "hacks", "tunnel"] -slug = "vpn-too-complicated-use-a-ip-over-ssh-tunnel-instead" -+++ ++++ +date = "2012-07-11" +title = "VPN too complicated? Use a IP-over-SSH tunnel instead" +tags = ["ssh", "vpn", "hacks", "tunnel"] +slug = "vpn-too-complicated-use-a-ip-over-ssh-tunnel-instead" ++++ Some times you find yourself in a place where your Mac is safely tucked away behind a firewall. That's great, but sometimes it is annoying as hell, because you _need_ to access resources over FTP or contact people who're on IRC. The normal solution would be to setup a VPN with one of your servers elsewhere and connect to the outside world that way. Unfortunately, in all their wisdom, sys admins have probably closed up the proper ports to access your VPN server as well. As a last resort you might consider setting up a SSH Tunnel for a specific service like this: - ssh -N user@server -L 3306:127.0.0.1:3306 +``` shell +ssh -N user@server -L 3306:127.0.0.1:3306 +``` But, this only works for a single port, and thus application. It may help, but it can become tedious pretty quickly. You also have to rewrite any configuration you had for connection to a remote host to use your localhost, most likely on some strange port. @@ -22,11 +24,15 @@ Besides giving you access to all the services you need, you also encrypt (e.g. h Installing sshuttle on your Mac is a breeze - $ brew install sshuttle +``` shell +brew install sshuttle +``` Then you can setup an IP-over-SSH connection to any remote server you have SSH access to. You'll need your local admin password in order to setup routing properly. - $ sshuttle -r username@server 0/0 -vv +``` shell +sshuttle -r username@server 0/0 -vv +``` This routes all traffic over the tunnel towards `server`. Use on of those online ip checkers to see that you're actually using your `server`'s IP address. @@ -36,25 +42,33 @@ The one thing this does _not_ do is DNS. DNS is still done using your locally co Not to worry, you can go 'full stealth' with the `--dns` options, which also routes DNS over to the remote server: - $ sshuttle --dns -r username@server 0/0 -vv +``` shell +sshuttle --dns -r username@server 0/0 -vv +``` To stop using your IP-over-SSH connection, simply press CTRL-C twice and sshuttle should restore your normal networking connections. If sshuttle does not restore the connection properly, you can do so manually: - $ sudo ipfw -q -f flush +``` shell +sudo ipfw -q -f flush +``` I've already create a few aliases in my `~/.zshrc`: - alias tunnel='sshuttle -r ariejan@server 0/0 -vv' - alias tunnel_dns='sshuttle --dns -r ariejan@server 0/0 -vv' - alias reset_tunnel='sudo ipfw -q -f flush' +``` shell +alias tunnel='sshuttle -r ariejan@server 0/0 -vv' +alias tunnel_dns='sshuttle --dns -r ariejan@server 0/0 -vv' +alias reset_tunnel='sudo ipfw -q -f flush' +``` So, no need to setup complicated VPN contraptions, just use plain old SSH and off you go. Bonus: you can also connect to a non-standard SSH port, in case port 22 has been blocked in the firewall as well: - $ sshuttle --dns -r username@server:port 0/0 -vv +``` shell +sshuttle --dns -r username@server:port 0/0 -vv +``` + +[sshuttle]: https://github.com/apenwarr/sshuttle/ -[sshuttle]: https://github.com/apenwarr/sshuttle/ - diff --git a/content/posts/2012-08-14-move-your-latest-commits-to-a-separate-branch.md b/content/posts/2012-08-14-move-your-latest-commits-to-a-separate-branch.md index 5452160..219ad5a 100644 --- a/content/posts/2012-08-14-move-your-latest-commits-to-a-separate-branch.md +++ b/content/posts/2012-08-14-move-your-latest-commits-to-a-separate-branch.md @@ -1,27 +1,35 @@ -+++ -date = "2012-08-14" -title = "Move your latest commits to a separate branch" -tags = ["git", "protip"] -slug = "move-your-latest-commits-to-a-separate-branch" -+++ ++++ +date = "2012-08-14" +title = "Move your latest commits to a separate branch" +tags = ["git", "protip"] +slug = "move-your-latest-commits-to-a-separate-branch" ++++ The situation is pretty straightforward. You have been making commits for that new feature in your `master` branch. Naughty you! Let's assume you want to have this: - A - B - (C) - D - E - F +``` text +A - B - (C) - D - E - F +``` `C` was the last commit you pulled from `origin` and D, E and F are commits you just made but should have been in their own branch. This is what you wanted: - A - B - (C) - \ D - E F +``` text +A - B - (C) + \ D - E F +``` Step 1: Assuming you're at `F` on `master`, create a new branch with those commits: - git branch my_feature_branch +``` shell +git branch my_feature_branch +``` Then, still on `master`, reset back to commit `C`. This is 3 commits back. - git reset --hard HEAD~3 +``` shell +git reset --hard HEAD~3 +``` + +Okay, you're `master` is now back at `C`, which you lasted pulled, and the `my_feature_branch` includes D, E and F. Just checkout `my_feature_branch` and continue work as usual. I'm sure no one saw what you just did. -Okay, you're `master` is now back at `C`, which you lasted pulled, and the `my_feature_branch` includes D, E and F. Just checkout `my_feature_branch` and continue work as usual. I'm sure no one saw what you just did. - diff --git a/content/posts/2012-08-27-getting-started-with-arduino.md b/content/posts/2012-08-27-getting-started-with-arduino.md index b1ef214..a930629 100644 --- a/content/posts/2012-08-27-getting-started-with-arduino.md +++ b/content/posts/2012-08-27-getting-started-with-arduino.md @@ -1,9 +1,9 @@ -+++ -date = "2012-08-27" -title = "Getting started with Arduino" -tags = ["arduino"] -slug = "getting-started-with-arduino" -+++ ++++ +date = "2012-08-27" +title = "Getting started with Arduino" +tags = ["arduino"] +slug = "getting-started-with-arduino" ++++ I'm a software engineer. I don't do hardware. Well, that used to be the case. I did build some PC's back in the day, but that's where my involvement with electronics hardware ended. That's all changed after I purchased an [Arduino][1]. @@ -40,21 +40,23 @@ For those a bit tech-savvy, here's the electrical schematic for the Blink tutori With the following, relatively simple code, you can make that LED blink. - int led = 13; // This refers to pin 13. +``` arduino +int led = 13; // This refers to pin 13. - // setup() is run once during start-up - void setup() { - // initialize the digital pin as an output. - pinMode(led, OUTPUT); - } +// setup() is run once during start-up +void setup() { + // initialize the digital pin as an output. + pinMode(led, OUTPUT); +} - // the loop routine runs over and over again forever: - void loop() { - digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) - delay(1000); // wait for a second - digitalWrite(led, LOW); // turn the LED off by making the voltage LOW - delay(1000); // wait for a second - } +// the loop routine runs over and over again forever: +void loop() { + digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) + delay(1000); // wait for a second + digitalWrite(led, LOW); // turn the LED off by making the voltage LOW + delay(1000); // wait for a second +} +``` After making this first step you'll get to know more components and features of Arduino. You'll start using sensors (buttons, light sensors, sound sensors, GPS, magnetometers, gas sensors) and you'll start using actuators (motors, steppers, relais, LED matrixes). The possibilities are endless. @@ -89,5 +91,5 @@ _Images have been taken from [arduino.cc][1] with not so much permission._ [3]: http://arduino.cc/en/Tutorial/blink [4]: http://www.instructables.com/id/Arduino-RC-Lawnmower/ [5]: http://ariejan.net/posts/tagged/arduino -[6]: http://arduino.cc/en/Main/Buy - +[6]: http://arduino.cc/en/Main/Buy + diff --git a/content/posts/2012-08-28-rails-migrations-decimal-precision-and-scale.md b/content/posts/2012-08-28-rails-migrations-decimal-precision-and-scale.md index 4ab4300..0189a41 100644 --- a/content/posts/2012-08-28-rails-migrations-decimal-precision-and-scale.md +++ b/content/posts/2012-08-28-rails-migrations-decimal-precision-and-scale.md @@ -1,14 +1,16 @@ -+++ -date = "2012-08-28" -title = "Rails migrations: decimal precision and scale" -tags = ["Rails", "migrations", "postgresql"] -slug = "rails-migrations-decimal-precision-and-scale" -+++ ++++ +date = "2012-08-28" +title = "Rails migrations: decimal precision and scale" +tags = ["Rails", "migrations", "postgresql"] +slug = "rails-migrations-decimal-precision-and-scale" ++++ I'm always confused when using `decimal` in a Rails migration. Normally I need to store a value that has 2 or 3 numbers behind the comma (or dot), or decimals. Let's say you have a `Product` model with a `discount_percentage` attribute. This attribute is currently an integer, only allowing non-decimal values. To allow 2 digit decimal values (e.g. `12.54`), you can mak the following migration: - change_column :products, :discount_percentage, :decimal, precision: 5, scale: 2 +``` ruby +change_column :products, :discount_percentage, :decimal, precision: 5, scale: 2 +``` This will allow you to store values like `80.00`, `99.99` and `100.00`. There are five digits in the entire number and of those five, two decimals. @@ -16,5 +18,5 @@ It's not necessary so specify `precision` and `scale` as your database will then Read more about the `decimal` data type in PostgreSQL here: [http://www.postgresql.org/docs/9.1/static/datatype-numeric.html][1] -[1]: http://www.postgresql.org/docs/9.1/static/datatype-numeric.html - +[1]: http://www.postgresql.org/docs/9.1/static/datatype-numeric.html + diff --git a/content/posts/2012-09-04-git-interactive-revert.md b/content/posts/2012-09-04-git-interactive-revert.md index aaa0125..196c9cd 100644 --- a/content/posts/2012-09-04-git-interactive-revert.md +++ b/content/posts/2012-09-04-git-interactive-revert.md @@ -1,9 +1,9 @@ -+++ -date = "2012-09-04" -title = "Git: Interactive Revert" -tags = ["git", "protip"] -slug = "git-interactive-revert" -+++ ++++ +date = "2012-09-04" +title = "Git: Interactive Revert" +tags = ["git", "protip"] +slug = "git-interactive-revert" ++++ I recently made a commit in a project that, mistakenly, included changes to `db/schema.rb`. My local schema was out of date and this could cause trouble for the others in my team. Luckily we use [a successful git branching model][1] so my changes were still up for review by the team. @@ -18,19 +18,27 @@ Now, there's `git add -i` which allows you to selectively stage chunks for the n Well, let's say you want to revert changes you made in commit `f1e11c`. Go to your feature branch and revert your changes for that commit but do not commit them yet, hence the `-n` option: - git revert -n f1e11c +``` shell +git revert -n f1e11c +``` Your working copy now contains staged changes to revert the entire `f1e11c` commit. You don't want to revert everything, so unstage all those changes. - git reset +``` shell +git reset +``` The key now is to interactively stage the changes you want to revert. You can do this like this: - git add -p +``` shell +git add -p +``` or - git add -i +``` shell +git add -i +``` Choose whichever suits you. @@ -38,13 +46,17 @@ In my case I staged only the chunks that related to the changes in `db/schema.rb With your reverting changes staged, commit them. - git commit +``` shell +git commit +``` You're now left with reverting changes you didn't want to make. Just throw them away. - git reset --hard +``` shell +git reset --hard +``` And that's all. You have now selectively reverted a commit. -[1]: http://nvie.com/posts/a-successful-git-branching-model/ - +[1]: http://nvie.com/posts/a-successful-git-branching-model/ + diff --git a/content/posts/2012-10-01-migrate-git-repositories.md b/content/posts/2012-10-01-migrate-git-repositories.md index 0fead35..fd2f8c0 100644 --- a/content/posts/2012-10-01-migrate-git-repositories.md +++ b/content/posts/2012-10-01-migrate-git-repositories.md @@ -1,21 +1,25 @@ -+++ -date = "2012-10-01" -title = "Migrate git repositories" -tags = ["git"] -slug = "migrate-git-repositories" -+++ ++++ +date = "2012-10-01" +title = "Migrate git repositories" +tags = ["git"] +slug = "migrate-git-repositories" ++++ Sometimes you have to move your git repository to another host. In this case I want to move a privately hosted git repository to a brand spanking new github repository. These are four easy steps to get that done: - $ git clone --bare git@yourserver.com:project.git - $ cd project.git - $ git push --mirror git@github.com:ariejan/project.git - $ cd .. && rm -rf project.git +``` shell +git clone --bare git@yourserver.com:project.git +cd project.git +git push --mirror git@github.com:ariejan/project.git +cd .. && rm -rf project.git +``` That's it. Don't forget to update the `remote` of your working copy accordingly: - $ git remote set-url origin git@github.com:ariejan/project.git +``` shell +git remote set-url origin git@github.com:ariejan/project.git +``` + +Of course, this works with any git server or service, not just Github, although Github is awesome and you should use it. -Of course, this works with any git server or service, not just Github, although Github is awesome and you should use it. - diff --git a/content/posts/2012-11-02-decorating_sorcery_current_user_with_draper.md b/content/posts/2012-11-02-decorating_sorcery_current_user_with_draper.md index 55d103e..9e0a80f 100644 --- a/content/posts/2012-11-02-decorating_sorcery_current_user_with_draper.md +++ b/content/posts/2012-11-02-decorating_sorcery_current_user_with_draper.md @@ -8,9 +8,11 @@ I already [wrote][1] about how to apply your decorator to the `current_user` whe Instead of being `nil` when no user is signed in, Sorcery uses an explicit `false` value, no `nil`. In your `ApplicationController` at `app/controllers/application_controller.rb` add this: - def current_user - UserDecorator.decorate(super) unless super == false - end +``` ruby +def current_user + UserDecorator.decorate(super) unless super == false +end +``` I'm using the most recent version of [Draper][4] by the way. diff --git a/content/posts/2012-11-22-customac.md b/content/posts/2012-11-22-customac.md index 6a24cdf..7907351 100644 --- a/content/posts/2012-11-22-customac.md +++ b/content/posts/2012-11-22-customac.md @@ -1,9 +1,10 @@ -+++ -date = "2012-11-22" -title = "CustoMac" -tags = ["osx", "hacks", "customac", "osx86"] -slug = "customac" -+++ ++++ +date = "2012-11-22" +title = "CustoMac" +tags = ["osx", "hacks", "customac", "osx86"] +slug = "customac" ++++ + Ever since Apple decided to put Intel processors in their Macs there have been attempts by enthusiasts to run Mac OS X on commodity hardware – with mixed results. The key to installing Mac OS X on a non-Mac computer is using the right hardware. If your hardware is a close to Apple kit as possible, you have the best chance to succeed. @@ -137,23 +138,26 @@ _Note: this works for my XFX ATI Radeon HD 6870 card. There may be subtle differ In `/Extra/org.chameleon.Boot.plist` make sure you have the following entries: -