5minutenpause

father and developer from Berlin

Comprehensive guide to deploying Rails applications with Mina

| Comments

I have this small SaaS web application. It has no homepage and it has no signup form or signup site. It has no marketing campaign and people only hear about it from current users. I manually onboard new users and show them around, personally. From face to face. To put it short: “I do things that don’t scale”.
The people using my software depend on it for its purpose, though. They earn real money using it and they are serious about it. They have feature requests and get annoyed when something doesn’t work — for good reason. That’s why whenever I develop a new feature or roll out a security update or fix a bug, it is really important that I don’t mess things up. It is okay to have a few minutes of downtime when the app restarts, there is no need for deployments with zero downtime. But other than that, the software and all things the users got comfortable using should work as intended.

To achieve this there are a few things in place that make this easier for me. Let me tell you about them. I test things on a staging server before deploying to production. I host my web applications, and this site, with the guys from uberspace.de. My production and my staging site sit on different servers using different user accounts. That’s okay for my purposes. The staging environment gets a duplication of the production database, although infrequently. This is not done as a backup but rather to test the staging environment with real data and real amounts of data. The environments use the same ruby version (2.1.2 at the moment) and the same rails version (4.1.1 as of writing). Of course I deploy both from the same git repository. I usually only deploy the master branch, but there may be a new feature or something specific sitting in a different branch that needs deployment to staging. Then this branch gets deployed.

But generally I prefer deploying the master branch so I know it works as intended and is without bugs. You often find the idea that “(the) master (branch) should always be ready to deploy” and I really try to develop by this. If done correctly you have the can always deploy and don’t have to worry about things that might go wrong. And there are always enough things that can go wrong.

Deployment

For deploying to staging or production there are a few things you need. Of course you need the code you want to deploy. This is achieved with your distributed version control system (if you ask me use git or mercurial). You need your server you want to deploy to. And you need a script or something similar to do the deployment. It should be as easy as opening a terminal, navigate to the path of your working copy and type $ [helper software] deploy.

I use Mina for deployment. In the past I used capistrano as well, but right now Mina serves my needs just fine. It is simple, easily configurable, I can read and change the source code and just like it. It feels right to me.
My commands for deploying look like this:

1
2
3
4
5
# deploy to staging
$ mina deploy -f config/deploy_staging.rb

# deploy to production
$ mina deploy

As I type this I realize that I should probably change that around. Deployment to staging happens more frequently than deployment to production and should be easier to do. And if I have to specify the configuration file for the environment (this is done with the -f option) I should ideally do this for production. That way — by typing more — I make sure that I only deploy to production when I really mean to and not by accident. I will change that.

Configuration

Mina is quite easy to configure, I guess you can probably figure it out faster that I did. But I will show my configuration files nevertheless. Perhaps it’s of use to someone. I will give a short description after the scripts.

Production

deploy_production.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
require 'mina/bundler'
require 'mina/rails'
require 'mina/git'
require 'mina/rbenv'  # for rbenv support. (http://rbenv.org)
# require 'mina/rvm'    # for rvm support. (http://rvm.io)

# Basic settings:
#   domain       - The hostname to SSH to.
#   deploy_to    - Path to deploy into.
#   repository   - Git repo to clone from. (needed by mina/git)
#   branch       - Branch name to deploy. (needed by mina/git)

set :domain, 'productionhost.uberspace.de'
set :deploy_to, '/home/production_user/appname'
set :repository, 'git@github.com:5minpause/app_repo.git'
set :branch, 'master'

# Manually create these paths in shared/ (eg: shared/config/database.yml) in your server.
# They will be linked in the 'deploy:link_shared_paths' step.
set :shared_paths, ['config/database.yml', 'log', 'config/initializers/secret_token.rb']

# set_default :bundle_options, lambda { %{--without development:test --path "#{bundle_path}" binstubs bin/ --deployment} }

# Optional settings:
set :user, 'production_user'    # Username in the server to SSH to.
#   set :port, '30000'     # SSH port number.

# set :bundle_bin, "~/.gem/ruby/2.1.0/bin/bundle"

# This task is the environment that is loaded for most commands, such as
# `mina deploy` or `mina rake`.
task :environment do
  # If you're using rbenv, use this to load the rbenv environment.
  # Be sure to commit your .rbenv-version to your repository.
  invoke :'rbenv:load'

  # For those using RVM, use this to load an RVM version@gemset.
  # invoke :'rvm:use[ruby-1.9.3-p125@default]'
end

# Put any custom mkdir's in here for when `mina setup` is ran.
# For Rails apps, we'll make some of the shared paths that are shared between
# all releases.
task :setup => :environment do
  queue! %[mkdir -p "#{deploy_to}/shared/log"]
  queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"]

  queue! %[mkdir -p "#{deploy_to}/shared/config"]
  queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"]

  queue! %[touch "#{deploy_to}/shared/config/database.yml"]
  queue  %[echo "-----> Be sure to edit 'shared/config/database.yml'."]
end

desc "Deploys the current version to the server."
task :deploy => :environment do
  deploy do
    # Put things that will set up an empty directory into a fully set-up
    # instance of your project.
    invoke :'git:clone'
    invoke :'deploy:link_shared_paths'
    invoke :'bundle:install'
    invoke :'rails:db_migrate'
    invoke :'rails:assets_precompile'

    to :launch do
      queue "svc -du ~/service/run-app_production"
    end
  end
end

# For help in making your deploy script, see the Mina documentation:
#
#  - http://nadarei.co/mina
#  - http://nadarei.co/mina/tasks
#  - http://nadarei.co/mina/settings
#  - http://nadarei.co/mina/helpers

Staging

deploy_staging.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
require 'mina/bundler'
require 'mina/rails'
require 'mina/git'
require 'mina/rbenv'  # for rbenv support. (http://rbenv.org)
# require 'mina/rvm'    # for rvm support. (http://rvm.io)

# Basic settings:
#   domain       - The hostname to SSH to.
#   deploy_to    - Path to deploy into.
#   repository   - Git repo to clone from. (needed by mina/git)
#   branch       - Branch name to deploy. (needed by mina/git)

set :domain, 'staginghost.uberspace.de'
set :deploy_to, '/home/staging_user/appname'
set :repository, 'git@github.com:5minpause/app_repo.git'
set :branch, 'master'

# Manually create these paths in shared/ (eg: shared/config/database.yml) in your server.
# They will be linked in the 'deploy:link_shared_paths' step.
set :shared_paths, ['config/database.yml', 'log', 'config/initializers/secret_token.rb']

# set_default :bundle_options, lambda { %{--without development:test --path "#{bundle_path}" binstubs bin/ --deployment} }

# Optional settings:
set :user, 'staging_user'    # Username in the server to SSH to.
#   set :port, '30000'     # SSH port number.

# set :bundle_bin, "~/.gem/ruby/1.9.1/bin/bundle"

# This task is the environment that is loaded for most commands, such as
# `mina deploy` or `mina rake`.
task :environment do
  # If you're using rbenv, use this to load the rbenv environment.
  # Be sure to commit your .rbenv-version to your repository.
  invoke :'rbenv:load'

  # For those using RVM, use this to load an RVM version@gemset.
  # invoke :'rvm:use[ruby-1.9.3-p125@default]'
end

# Put any custom mkdir's in here for when `mina setup` is ran.
# For Rails apps, we'll make some of the shared paths that are shared between
# all releases.
task :setup => :environment do
  queue! %[mkdir -p "#{deploy_to}/shared/log"]
  queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"]

  queue! %[mkdir -p "#{deploy_to}/shared/config"]
  queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"]

  queue! %[touch "#{deploy_to}/shared/config/database.yml"]
  queue  %[echo "-----> Be sure to edit 'shared/config/database.yml'."]
end

desc "Deploys the current version to the server."
task :deploy => :environment do
  deploy do
    # Put things that will set up an empty directory into a fully set-up
    # instance of your project.
    invoke :'git:clone'
    invoke :'deploy:link_shared_paths'
    invoke :'bundle:install'
    invoke :'rails:db_migrate'
    invoke :'rails:assets_precompile'

    to :launch do
      queue "svc -du ~/service/run-app_stage"
      #      queue "touch #{deploy_to}/tmp/restart.txt"
    end
  end
end

# For help in making your deploy script, see the Mina documentation:
#
#  - http://nadarei.co/mina
#  - http://nadarei.co/mina/tasks
#  - http://nadarei.co/mina/settings
#  - http://nadarei.co/mina/helpers

Description

In line 4 you can see I use rbenv for managing my rubies. This works well for me in development and any other environment. Once you get used to its workflow it really shines. I recommend it for anyone who’s looking for a ruby (version) manager. If you already use something else (rvm? something home-grown?) you can set it up here.
The basic settings are pretty self-explanatory, I set up my domains, the path, the repository and the branch. I anonymized the sensitive parts. If I want to deploy a different branch than master I change it right there in the script itself. As I don’t do this very often that’s okay for me.
Mina offers variables to tune your script to your needs right from the command line. So you could change your branch setting like this:

branch-setting
1
2
3
4
set :branch, ENV['branch'].present? ? ENV['branch'] : 'master'

# call mina deploy like this:
$ mina deploy branch=new-feature-branch

This should set the branch to your new-feature-branch and everything works as expected.

The rest of the script doesn’t deviate too much from the original script files. I only queue a command to relaunch the application after a successful deployment. This command is specific to my hoster and you probably need something different for your hosting environment.

If you want to try out deploying with mina please follow the links to their site. Installation and setup are really well described. If you have any problems or questions you can probably find some answers in the documentation and guides on their site. Otherwise go to Github and open an issue. Any comments or questions about my setup? Please write a comment on my site, down below.

As always thank you for reading and make sure to subscribe to my newsletter so you don’t miss my next articles. Also I really like to connect with my readers and the newsletter is a perfect place for that. I am interested in your specific problems regarding web development. After joining you can reach me directly via email and ask your questions.

Enter: comments

| Comments

After having people ask me for it and considering the benefits, I will enable comments on my blog. Right now I’ll use disqus.com for this purpose. I am in the middle of creating my own comment system — based on Github issues — but that’s still a work-in-progress and I don’t know when I’ll be able to finish that. So please try commenting if that’s your thing.

Thank you.

Start hacking

| Comments

Some people learn programming because they want to fulfill a wish. Perhaps the wish is to get a (new) job. Or they want to take on a career where you can be creative and get paid well. Some learn programming because they have an idea for a piece of software, an app or a service.
Once they’ve completed the introductory course, you often see them stumble and wait. They aren’t sure what to do next, afraid to not know enough to get started with their idea. They go hunting for even more lessons on programming. Hoping the next course will teach them the things they don’t know yet.
Well here’s the secret: You already know enough. Just start creating. Sit down, take the simplest possible implementation of your idea and start developing it. Yes, you will hit road blocks. The code will be stupid and ugly. Guess what, you’ll make many mistakes as well. But at the end of the week you’ll have created something you’re proud of. You will have learned more from your mistakes and questions, then from the next 5 tutorials combined.
If you don’t know how to proceed with your next problem, if there’s a programming issue, a question on how to implement something: hit google or go to stackoverflow.com. Find people online and ask them. But google first. I’ve never met a programmer who liked to answer questions, where the person asking them never even tried to find a solution first.
Don’t be afraid to make these mistakes. Your first and only goal should be to make something that works and does what you intended it to do. It doesn’t have to be the most sophisticated version, it just has to work. Preferably without errors or bugs, but that’s step two.
I followed this advice and it worked well for me. Let me tell you the story of how I started my career as a software engineer.
My first »professional« software was called TeaTimer. I like to drink tea, mostly green and black teas. I boiled the water, put in the tea and let it steep. But too often I sat at the computer and forgot about the tea. That’s a crucial error if you drink black and green teas. They become bitter and I don’t like that taste. That’s why I developed a small utility app for OS X that counts down and notifies you when the time is up. It had three slots for preset times—teas you drank often for example. It was nothing fancy, just a simple timer. I put it on the Mac App Store. I would have been happy to get even one sale. I made it for myself, that was the premise. If there was even one other person that found it useful enough to pay money for it, that would have meant a world to me. I priced it at about 3.99$ (I don‘t remember the precise amount, but that’s about right. It wasn’t 0.99$ in the beginning). Well what can I say, I made around 60 sales in the first 12 months. The price declined and ended up at 0.99$ eventually and I didn’t get rich off of it. But it made enough in the first year to cover my expenses for the Mac development program. What’s the story here? I made something simple and it worked and people payed me for that. That was one of the most rewarding experiences of my professional life.
Was it a good piece of software? Well, no. As my experience developing software grew, I quickly realized the many mistakes I had made. As the second year on the Mac App Store approached, I had to make a decision: Pay the yearly fee and keep trying to sell TeaTimer or don’t pay the fee take it off the store? It was clear to me, that I would have to upgrade the app. After all I had clients and feature requests from them and some wishes on my own. But I couldn’t go on developing this app in its current state. I would have had to make a rewrite or refactor and optimize it a lot. But I knew I wouldn’t find the time. So I refrained from renewing my developer program and took it off the store.
In the end I learned tons of stuff. I had software people bought and I could put on my resume. TeaTimer even helped me get a job as a developer, because I could prove that I write software that people pay for. That’s a great feeling.
So please, young, inexperienced developer. Sit down, open up your text editor and hack away. Create something small, solve a (business) problem you (and other people) have and put it up for sale. When you get your first sale, I guarantee you: It’ll be one of the best feelings you can have in your professional life.

Submit remote forms with jQuery in Rails

| Comments

The other day I had created a form without a submit button. It is a simple checkbox, which toggles if a user is admin for a project.
It looks like this:

Controller

Ticking the box should toggle the state for the user. So I created a controller action:

1
2
3
4
def toggle_admin_state
  @project = Project.find(params[:id])
  @result = ProjectAdministrationPolicy.new(current_user, @project).create? && ProjectAdministration.toggle!(params[:user_id], @project.id)
end

ProjectAdministrationPolicy is about authorization. I use the Pundit gem for these tasks.
ProjectAdministration.toggle!(params[:user_id], @project.id) toggles the admin? state for the given user. I return a boolean representing the outcome of the action. Perhaps there was an error of some kind, or the current_user isn’t allowed to change the admin state for the given user. Either way we get a true/false result, which we use in our view.

View

There are two views at play here. The first is the view with the form itself. The other view is what gets rendered after the form was submitted. Let’s start with the view that contains the form.

1
2
3
4
5
<%= form_tag toggle_admin_state_path, method: :post, remote: true, id: 'toggle_admin_form' do %>
  <%= hidden_field_tag :authenticity_token, form_authenticity_token %>
  <%= hidden_field_tag :user_id, membership.user_id %>
  <%= check_box_tag 'user_id', "#{membership.user_id}", ProjectAdministration.where(user_id: membership.user_id, project_id: membership.project_id).any?, class: 'admin_checkbox', id: "user_#{membership.user_id}" %>
<% end %>

The important parts of the form are the options to the form itself. method: :post makes sure, we use the right HTTP action. remote: true makes this a form which we can submit via javascript. The other form elements are just standard rails form tags. A little trick you’re perhaps not aware of: If you use checkboxes in your form, the checkbox’ value only gets submitted, if it is checked. We need the value (the user id) all the time, to actually find the user and toggle its admin state. That’s why we always submit the user_id using a hidden_field. This makes sure, we always have the value, no matter the state of the checkbox.

Next up the view for the action. As the action should only respond to javascript I created the following view:

1
2
3
4
5
6
7
8
9
<% if @result %>
  $('#main-content').prepend("<div id='flash_notice' style='overflow: hidden;'>Change successful.</div>");
<% else %>
  $('#main-content').prepend("<div id='flash_warning' style='overflow: hidden;'>You are not allowed to do that or there was an error.</div>");
<% end %>

setTimeout(function() {
  $('#flash_notice, #flash_warning').hide(400);
}, 1500, false);

This adds a <div> at the top of the page, just below the topbar. This is where I show my warnings and notices. It’s of course up to you to decide where you want to show this flash message. Or you don’t show it at all.
The last three lines set a timeout of 1.5 seconds. After the countdown completes the warning or notice is hidden with a little animation, courtesy of jQuery. I set the speed for the hide animation to 400ms.

Route

As we use toggle_admin_state_path in our form, and because we defined the controller action, we need to set up a route for this to work. That’s easy:

1
post 'projects/:id/toggle_admin_state' => 'projects#toggle_admin_state', as: 'toggle_admin_state'

Submitting the form

The final step is submitting the form. The naive way (read: the way I tried first) is to use an event handler and just call submit() on the form. It may look like this:

1
$('form#toggle_admin_form').submit();

This actually works. Only problem is, it’s not submitted as JS, but as HTML:

1
2
Started POST "/projects/3/toggle_admin_state" for 127.0.0.1 at 2014-03-28 13:03:51 +0100
Processing by ProjectsController#toggle_admin_state as HTML

If you want to submit as a truely remote form, and use your .js.erb view, you have to do things a little differently.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$('.admin_checkbox').bind('change', function() {
  $.ajax({
    url: $(this).parents('form')[0].action,
    headers: {
      Accept : "text/javascript; charset=utf-8",
      "Content-Type": 'application/x-www-form-urlencoded; charset=UTF-8'
    },
    type: 'POST',
    data: {
      'user_id': $(this).siblings('[id*=user_]').val(),
      'authenticity_token': $(this).siblings('#authenticity_token').val()
    }
  });
});

Let’s take it from the top:
Line 1 binds to the change event of this checkbox. If you check or uncheck it, the function is called.
Line 2 uses jQuery to make an asynchronous HTTP request
Line 3 the url for the request

These were basic options. Now we have to set the correct headers.
Line 5 Set the accept header. By default it depends on the dataType. But if you set the dataType to script, your POST request get submitted as a GET request. Which doesn’t work for us.
Line 6 Set the content-type. This is important. Otherwise your form parameters won’t be submitted in a way that your server understands and processes them.

Line 8 make sure this is a POST request
Line 9 get the form data and set it as request data (body)

Now if we toggle the checkbox, the request is sent as a JS request:

1
2
Started POST "/projects/3/toggle_admin_state" for 127.0.0.1 at 2014-03-28 13:32:41 +0100
Processing by ProjectsController#toggle_admin_state as JS

This wraps it up. I hope you’re successful with your remote forms. This time there won’t be a Github repository. The content of this post is quite specific to my app. I believe you can implement your remote forms quite easily wih the right jQuery asynchronous HTTP request syntax.

Happy coding.

I am just like you.

| Comments

I have a list in my simplenote app that contains ideas, headline and snippets for possible future blog posts. Right now there are about ten entries. It’s hard to tell how many exactly, because some are just a headline for a kind of mini series about something. Some of these possible posts are about ruby/rails technologies. Some are about workflows (e.g. deployment). One or two are about things I did earlier in my career, so they are something about funny or interesting anecdotes, or just for reliving and remembering things. Some ideas are even about me.
But all these posts have one thing in common: They are for me. Every single post would eventually be written by me for me. What I mean is, that these topics are things I have a personal interest in. Let me make an example:

Comparison of Rails cloud hosting and deployment

There are quite many cloud hosting solutions for Ruby on Rails applications on the market. I don’t know very many. I know Heroku and some smaller ones, especially from Germany. But I don’t know which one would be the best choice for a specific project. One could look for differences in data security, location and other things. Group this in a table to make it easily accessible.
I would like to know this and read an article about it. You would probably be interested as well.
So you see: These topics are certainly interesting for a lot of people and would drive my traffic numbers upwards. But this is not the reason to write them. The reason is that I want to know this stuff. Other topics are about things I want to learn. Take a look into my archives. You will see that I write down, what I learn. Partly for me to reference in the future. But mostly to share my knowledge and help other people who might want to know this as well.

That’s what I mean when I say I am just like you. That is the reason I write my articles. I want to learn. I want you to learn. I want to share. And it’s just a lot of fun. People often use the end of the year to reflect on what they did during that year. For me it was a whole lot of things (I became a father of a wonderful little girl besides other things…). But one of these things was my desire to blog about what I learn and share it with the world. So that’s why I write, in a nutshell.

It’s your turn?

If you want to take a swing at one of my broader topics, here is the list. Please send me a link to your article when you are finished or need a second opinion/an editor.

List of topics

  • Comparison of Rails cloud hosting and deployment
  • Compare deployment with capistrano, vlad and mina
  • Authorization from scratch with puppet
  • Real world examples and stories about refactoring code (one can learn a ton from these)

If you write these, or find them online somewhere please tell me on Twitter (@5minpause).

Thank you for reading.

So, he doesn’t know this, huh?

| Comments

You and I, we develop software. The things we create run inside browsers and on smartphones. They run on computers and on servers. They serve the need of some, and sometimes the needs of hundreds. Or thousands. Or, if we are lucky or have the right setting, millions use our software or parts of it. The systems we develop and write have many moving parts. They consist of a lot of different technologies. Depending on what you develop, you have to be a generalist, more than a specialist. But it depends.

Evolution

A thing that is the same no matter what you do is the constant evolution of our tools. On any given day I need at least two applications to do my job: a text editor (my choice is vim) and a browser. Most of my days I use emails to communicate with colleagues. I do development of frontend code for websites, I write code in Objective-C. I extend functionality for users or optimize older code in Ruby projects. I create command-line scripts or tools to optimize my workflow. I even use Photoshop (it came pre-installed with the Mac my employer gave me) to crop or manipulate images. I test my software and code in an array of various environments (Internet Explorers 6-10, Chrome, Firefox, Opera, Safari and MobileSafari, Windows and Mac OS, iOS and sometimes Android). These techonologies are just off the top of my head what I have to use on a day to day basis. Now as I said earlier: these tools and technologies are constantly evolving (yes, even you, Internet Explorer!). You have to keep up with the latest developments. You have to know these tools, even though you don’t need to know everything by heart. But you have to read up on the latest technology. You have to know how the latest public release of an operation system—millions of people use everyday—works. If you don’t read up on the latest developments in your chosen field, you fall behind. There are many many young developers who are eager to step into your shoes and do your work. There are many people who realize the opportunity of changing into a profession you chose yourself some years ago. These people have a need. They have a desire to become successful as a developer. They have a burning passion. And they will do what it takes to make their dreams come reality.

We’ve always done it this way

Sadly, the phrase “We’ve always done it this way.” is the worst thing you can use but it gets said way too often. Especially in a field where your tools evolve, you just cannot keep doing things the way you did them 10 years ago. I mean I get it. You are a seasoned developer. Your code stood the test of time. Your old C routines still run and you know how to do memory management on iOS ‘the old way’. Guess what: Thousands of other people do as well. But that doesn’t make it the best way. If all you have is a hammer, everything looks like a nail. Perhaps it’s time to head to the hardware store and acquire some other tools.

Resources

If you are keen on learning new stuff, broadening your horizont and trying new things I want to give you a small list of places to look for material and inspiration.

Blogs

Perhaps an obvious thing are blogs. I mean, you are reading one right now and I teach things. So you made the first step. A really good one I want to add. Here are some other blogs that I read myself and can recommend:

  • Giant robots smashing into other giant robots – Thoughbot is an agency doing Ruby and iOS contract work. They write about best practices in OO software design, testing and using your tools (e.g. vim) properly. And they have the best name for a blog.
  • Inessential.com – Brent Simmons is one of the good guys and one of the more experienced. But he doesn’t use the phrase “I’ve always done it this way.” He tries new stuff and writes about his experiences. Mostly iOS/Mac OS. Recently he has a series about synching between client/server.
  • Peter Steinberger – Peter blogs very infrequently about Objective-C. But when he writes a new post it is highly informative, technically demanding and really interesting. I don’t always understand everything he writes. It’s sometimes too low-level for me, but you can almost always take something away from it.
  • Dave Winer – Scripting News – Dave Winer invented RSS. And did many other great things. He writes about his learning about recent web technologies and his point of view on the world (of tech).
  • iOS App Dev Libraries – A collection of (new) libraries, controls and other open source software useful for iOS developers.
  • NSHipster – A journal of the overlooked bits in Objective-C and Cocoa.

Websites

These are no blogs but websites with regular articles and/or screencasts:

  • Practicing Ruby – Monthly lessons about software and Ruby things.
  • Ruby Tapas – Short screencasts for intermediate to advanced Ruby developers.
  • Vimcasts – Free screencasts about Vim. Drew Neil really has the most soothing screencast voice I’ve ever heard.
  • Railscasts – Over 400 screencasts about many things for Ruby on Rails developers. Currently on hiatus, but still worth it.
  • Objc.io – A high quality periodical about Objective-C/iOS.
  • Ray Wenderlich – He came out of nowhere some years ago and made many many many tutorials for iOS developers. Now he is one of THE best sources for beginners and advanced developers for all things Objective-C/iOS/Mac OS.
  • 24Ways – An advent calendar for web geeks. Each day throughout December you get something interesting about web dev and/or design. (Relevant since it’s Xmas soonish.)

Newsletters

You can get newsletters to almost every possible topic these days. Here are some that are relevant to developers:

  • iOSDevWeekly - Hand picked iOS development links with sections on News, Tools, Code, Design and Business.
  • Ruby Weekly – A free round-up of Ruby news and articles.
  • node weekly - A round-up of Node.js news and articles.
  • HTML5 Weekly – You guessed it: A round-up of HTML5 and browser technology news and links.

I could give you even more links to websites and blogs that teach stuff and have really interesting content, but this is supposed to be a rather short list. It is still really long I think and should give you a starting point for learning. Now you don’t have an excuse if you’re stuck with the old ways of doing things. Read, listen, watch and learn and then go out and teach others. The developers of tomorrow will thank you for it.

Thank you for reading.

Website analytics and statistics for Github repositories

| Comments

If you use Github.com and have some popular repositories you might want to know where your traffic comes from. Github doesn’t offer anything to track visitors so you completely in the dark. The only way to track the popularity of your repository is to count the stargazers. This didn’t satisfy me.

Enter Bitdeli

If you search around the web for a solution you stumble upon Bitdeli. Bitdeli offers “Analytics for GitHub”. All you have to do is sign in with your Github account and authorize Bitdeli to access your repositories. They then fork your repo and send you a pull request. This pull request inserts a bitdeli.com badge into your repos readme file. With this badge they count your repositories visitors and track their origins. On the Bitdeli website you get a nice grahical overview for your repository and a timeline to track visitor count over a longer period. So this is a really quick and simple solution for this problem.

Use custom solution with Piwik

As I use Piwik for visitor statistics on this blog, I wanted to create my own solution to track my visitors. I use Piwik for counting my RSS subscribers (thanks to Felix Schwenzel(in german)) and now I use the same technique for my Github repository. Here’s how to do it:

  1. Go to your Settings -> Websites, click Add a new website

  2. Enter the appropriate settings for your repository

  3. Click ‘View Tracking Code’ Copy your image tracking code and insert it into your project’s readme file. This could look like this: You have to make sure the protocol is https for the link. Github changes http links and makes your image tracker link useless. The only way to make it work is to make sure you specify its url as https.

1
2
3
4
5
6
7
8
<!-- Piwik Image Tracker -->
<noscript>
<img src="https://yoursite.com/piwik/piwik.php?idsite=site-ID&rec=1" style="border:0" alt="" />
</noscript>
<!-- End Piwik -->

// Rest of Readme ommitted for brevity
// ...

Google Analytics

Unfortunately it seems as Google removed the option of image tracking codes for Google Analytics. If you browse their help sites, you come across a solution for older mobile phones.
This solution requires the use of PHP on your server. If that’s something you want to use (Why would you? It’s PHP!?) check out this link: Google Analytics for Mobile Websites. Then you can generate an image tracking url and place it inside an <img> tag like shown above. As I don’t use GA anymore I can’t show you how to do it. Why don’t you try using Piwik instead?

This wraps it up. Now you can go ahead and insert tracking codes for all your repositories. Thank you for reading.

Github repository

This time I don’t have a special Github repository to show you, but you can take a look at the README files in 5minpause/multiple-file-upload or 5minpause/pixelletter for inspiration.

Free programming books

| Comments

Because one of my main themes for this blog is learning, I want to share with you a resource I just stumbled upon. It’s a collection of links to free programming books. The collection has its origin on stackoverflow but migrated to Github for collaborative updating. There are links to several languages available so you don’t necessarily read an English book. You can find the collection on Github.

Happy reading.

How to: HTML5 video that works on every browser

| Comments

tldr;

HTML5 video sucks. Flash sucks. If you want to use HTML5 video anyway you should consider using a third party library. I suggest mediaelement.js.

Introduction

Integrating HTML5 video in your website and making it work in every browser (yes, Internet Explorer as well) still is no piece of cake. As I had the ‘pleasure’ of dealing with this task in the last weeks I want to write down what I found. There are some hoops you have to jump through, surprisingly even when dealing with a modern browser like Chrome. The only ‘just works’ solution seemed to be .mp4 files with Safari. But as I am on a Mac that might just be only my point of view. So let’s get this going one browser at a time.

Safari and mp4

Safari was really the easiest one for me. Just hand it a video file encoded with h.264 with results in a .mp4 video file and Safari will happily play it for you.
An example implementation might look like this:

1
2
3
<video id='video' autoplay controls>
  <source src='videos/my-file.mp4' />
</video>

Chrome and mp4/webm

Older versions of Chrome play .mp4 files just like Safari. Recently Chrome switched to .webm format by default. This means that you might be able to play your video file using Chrome. But some users might not. Welcome to the world of HTML5 video. Now you have to start making adjustments to cater for the individual browser your users have. You could do all that yourself, but you also could take a bath in ice water. Definitely not for everyone!

Libraries

There are several libraries out there to make your life easier. Some are open source and usable free of charge even on commercial projects. Others require you to buy a license. Gerrit van Aaken and Philip Bräunlich went all the way and created a nice chart of all major (and minor) contenders. So you can just choose which one fits your needs. You can find the HTML5 video comparison chart on the website praegnanz.de

I went with mediaelement.js. It’s a solution using jQuery that offers a Flash fallback. Yes that’s right, Flash. I actually envy the developers back in the day when all they had to do was implementing a Flash player. You either had Flash and it worked or you clicked the link and downloaded it. But today it’s supposed to be better, and I didn’t really like Flash anyway. But having a Flash fallback is useful when it comes to Interner Explorer < IE9. More on that later.

Chrome (again)

mediaelement.js doesn’t really help you with your Chrome problem though. I decided it’s best to assume that Chrome users are on auto-update and will get the latest Chrome version rather sooner than later. This might not be the case for every user and you might want to check for that situation. I recommend using Modernizr:

Modernizr and video format support

Modernizr is an open source, MIT-licensed JavaScript library that detects support for many HTML5 & CSS3 features.
(source: Dive into HTML5)

The linked website also tell you how to include it. So go ahead and click that link. We’ll use Modernizr to detect for HTML5 video support in your browser and also for the special formats your browser is able to play.

detect video formats link
1
2
3
4
5
6
7
8
9
10
if (Modernizr.video) {
  // let's play some video! but what kind?
  if (Modernizr.video.webm) {
    // try WebM
  } else if (Modernizr.video.ogg) {
    // try Ogg Theora + Vorbis in an Ogg container
  } else if (Modernizr.video.h264){
    // try H.264 video + AAC audio in an MP4 container
  }
}

Now let’s adjust the code to make Chrome play that .webm file.

adjust source for chrome
1
2
3
4
5
6
7
8
if (Modernizr.video) {
  if (Modernizr.video.webm) {
    // replace the DOM node <video> and replace it with itself but only with a .webm file as source
    $('#video').replaceWith("<video id='video' autoplay controls src='videos/my-file.webm'></video>");

    [...] // I cut the rest for brevity
  }
}

So now we should be able to play on Safari and Chrome. Please note, that you have to encode the video in .webm as well as in h.264 for this wo work properly.

Firefox

Firefox doesn’t like h.264 (.mp4) encoded video files. Firefox likes something different, namely .ogg/.ogv files. Thats why you have to encode your video in a third format. Otherwise Firefox is fairly simple to handle—at least inside your HTML/JS. (Firefox supposedly also plays .webm files but I found it works best with .ogg/.ogv video files. Your mileage may vary.)

adjust video sources for Firefox
1
2
3
4
<video id='video' autoplay controls>
  <source src='videos/my-file.mp4' type='video/mp4' />
  <source src='videos/my-file.ogg' type='video/ogv' />
</video>

Sometimes Firefox doesn’t want to play your video. There’s an error message that the MIME type isn’t supported: No Video with Supported Format and Mime Type Found
The solution is to register your content type inside an .htaccess file:

register MIME types
1
2
3
AddType audio/ogg .oga
AddType video/ogg .ogv
AddType application/ogg .ogg

Now we have basic support for three major browsers. So far we didn’t need any third party library. Why should we use it then? I like mediaelement.js for its support of mobile devices and its Flash fallback. I won’t go into detail how to setup mediaelement.js. You find a very extensive documentation on their website. On to Internet Explorer land!

Internet Explorer

(I never thought I would write these words on this website, but I just did…)
Recent versions of IE(9.0+) play h.264 encoded video and can even play .webm files with a little plugin. For everything earlier you should either use a picture instead of a video or you use Flash. Mediaelement.js provides you with a flash file you can include and link to from your website. Once you configure your player to use mediaelement.js this should work well for you.

setup flash fallback for IE
1
2
3
4
5
6
7
8
9
<video id='video' autoplay controls>
  <source src='videos/my-file.mp4' type='video/mp4' />
  <source src='videos/my-file.ogg' type='video/ogv' />
  /* data and value hold the path to your .swf file */
  <object width="1080" height="720" type="application/x-shockwave-flash" data="js/flashmediaelement.swf">
    <param name="movie" value="js/flashmediaelement.swf" />
    <param name="flashvars" value="controls=true&amp;autoplay=true&amp;file=videos/my-file.mp4" />
  </object>
</video>

Please note the html encoded ampersand (&) inside the flashvars. If you set the correct paths for your .swf and .mp4 files you are set and everything should work.

Mobile devices (iOS)

iOS devices play h.264 encoded mp4 video files just alright. mediaelement.js allows you to skin your player and use custom controls which might be necessary for your website.

Mobile devices (Android)

Android plays mp4 video files as well. If you followed the advice above for the different browsers everything should work for you on Android. There might be encoding issues which prevent playback though.

So that’s it. Your video should be able to play without further problems. These solutions worked for me. There might be different steps necessary for your particular setup and different audio/video encoding might hinder playback. Thanks for reading.

Not-invented-here vs. moving

| Comments

You may have heard of ‘Not invented here’, or short NIH. NIH is called ‘not-invented-here-syndrome’ when used in relation to software development. It describes the fear or philosophy of not using already existing ideas or solutions to a problem. The reasons for that decision can be diverse. Some may think that existing solutions don’t really cover their needs. Others try to find a different solution to a problem than the ones that already exist. And some might just have other reasons. Or money. Money is always a good reason.

I usually try to use existing solutions. Be it ruby gems or software libraries for iOS projects. I find that open source software generally does what I need and I like to give back to OSS by using it and trying to enhance it. That’s why you find me writing here, and that’s why I try to open-source almost everything I code. And of course I like to concentrate on creating new and interesting things and solutions to actual business problems instead of reinventing the wheel.

Short detour: I recently moved into a new appartment. My girlfriend and I decided to do the packing and moving ourselves. We enlisted some family and friends to help us carry all the boxes and furniture onto the truck and into the new appartment. My co-workers asked me why I decided to do this myself. They would surely use a company for that. That got me thinking. There are obviously some similarities between NIH and my move.

This move was my 4th move in my adult life. I did all of them the same way – with family and friends. I know what to expect and I actually find some joy in moving when everything just works and you get over with it quickly. To sum it up: I am fast, well organized, know exactly what I want and how I want it. A company makes nothing better – only differently.

This stands in stark contrast to my attitude towards NIH. Here I intentionally decided against a ‘good enough’ solution and tried to ‘roll my own’. Why was that?
Well I believe I couldn’t gain anything by using a company and wasn’t off worse by doing everything myself. So I chose a solution that resulted in ‘having a good time with friends and family’ (sort of). At certain points throughout the day (washing machine!) I actually cursed myself and swore to the heavens that I would get a company to do it next time. But at least I learned something that day:
Don’t judge to quickly if some people try to do everything themselves. It is not neccessarily NIH that drives them to that decision. It might just be because it’s fun to them and the actually really enjoy doing it – and because of all the reasons above.

PS: I actually learned two thing that day. The second one is that when you are over thirty, your body needs more than two days to recover from ‘great ideas’ like carrying a washing machine.