Subscribe

  • Hip Like Heroku

    Usually I deploy projects on my physical server, located at the server park called “former bedroom at my parents’”. This allows me to see how a project develops and migrate to a better server (which costs more money) if it’s successful. This is also the case for hiplikejapie.nl.

    I’ve been deploying a couple of experiments to Heroku and the platform really appeals to me. Deploying itself is a breeze and the “add-ons” model is pretty cool. Also, it’s free if you can manage with a 5mb database, 1 dyno en 0 workers. Projects in a developing stage usually do. I’ve never launched a project from it though. Primarily because I don’t want the to run into insane hosting costs if something like Please Rob Me happens. In any case the ability to scale a project and not worrying about server setup and stuff is awesome.

    Hip Like Japie hasn’t really took off (yet?), but is doing mildly ok with a bunch of visitors every day. It being a finished product made it interesting for me to see how well it would deploy.

    I’ve got Heroku’s command line tool installed, but if you haven’t install it like this:

    $ sudo gem install heroku
    

    Next you need to setup a Git repository for your project if you haven’t already.

    $ git init
    $ git add .
    $ git commit -m 'initial import'
    

    Let Heroku add it’s remote.

    $ heroku create
    

    Login with your Heroku credentials and you’re done setting up!

    This would usually be the point where you start developing your application, but Hip Like Japie being already done allows me to skip directly to deploying.

    $ git push heroku master
    

    Did you see what they did there? They just added a new remote, super nice. Anyway, this should start deploying the app. After it’s done, migrate the database.

    $ heroku rake db:migrate
    

    I thought about looking online for correct settings to Heroku’s database setup, but decided to just run rake and see what happens. Turns out that Heroku just made it work. My production setup was set to use Sqlite3, but Heroku automatically changed it to their PostgreSQL database.

    Technically I was done, but opening the website would give me an error. Crap, something went wrong. You can check the server’s log by issuing the following command:

    $ heroku logs
    

    This showed me that a database query failed, due to running on PostgreSQL instead of Sqlite3. I applied a dirty little patch.

    if ActiveRecord::Base.connection.instance_values["config"][:adapter] == 'postgresql'
      @comparisons = Comparison.find_by_sql(
          "SELECT * FROM (SELECT DISTINCT ON (username) * FROM comparisons ORDER BY username, id DESC) foo ORDER BY id DESC LIMIT 10"
          )
    else
      @comparisons = Comparison.all(
          :order => "id DESC", :limit => 10, :group => 'username'
          )
    end
    

    After that the site worked fine: hiplikejapie.heroku.com. There’s an add-on that allows you to hook up your custom domain name to the project. It’s conveniently called “Custom Domains” and can be used via the command line.

    $ heroku addons:add custom_domains
    

    This may prompt you to verify your account, by entering your creditcard details (on Heroku’s website, not the command line). After that you’re ready to add your domain names.

    $ heroku domains:add www.hiplikejapie.nl
    $ heroku domains:add hiplikejapie.nl
    

    I added both the domain and the www. sub-domain. To activate this, you need to change your domain’s DNS settings. It comes down to adding three A records and a CNAME.

    @ A 75.101.163.44
    @ A 75.101.145.87
    @ A 174.129.212.2
    www CNAME proxy.heroku.com.
    

    That’s it, hiplikejapie.nl points directly to Heroku, awesome!

    EDIT:

    The website failed if the worker would spin down. The error logs showed that Compass couldn’t compile the Sass files. Which is obvious as Heroku is read-only. This line in config/environments/production.rb fixes it:

    Compass.configuration.sass_options={:never_update=>true}
    
  • Improve Javascript code quality with JSLint

    Created a tiny project on GitHub with a simple piece of Javascript to see what JSLint does.

    “JSLint is a JavaScript program that looks for problems in JavaScript programs. It is a code quality tool.” – JSLint.com

    Pretty cool and something I’ll definitely incorporate in deploy scripts. Checkout the example website here and the GitHub repo here.

  • When POSTs suddenly turn into 301 redirects in Rails

    Everything worked fine in my development environment, but when I ran the application from my server every POST would just show the page it was suppost to POST to via GET. Displaying a 301 redirect in Chrome’s developers tools.

    After some fiddling around, I commented line 351 in the .htaccess file:

    <IfModule mod_rewrite.c>
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/|#(.*))$
      #RewriteRule ^(.*)$ /$1/ [R=301,L] # <-- this one
    </IfModule>
    

    After that everything worked as expected. Weird..

  • Girrst displays your Gists as RSS

    Do you use GitHub’s Gists? Then you might like this.

    Sharing code among co-workers and friends is quite easy using various ‘code snippit’ sharing websites. I personally like GitHub’s Gists. To make sharing even easier and keep everybody up to date of what’s being shared, I wanted to create a feed out of my Gists. Of course I could just use GitHub’s own RSS feeds, but that would screw up my reason to do something with App Engine.

    App Engine

    Using Python and App Engine I threw together a script that will take your GitHub username and turn all your Gists into a convenient RSS feed. You can then use the feed to include it anywhere, like your favorite RSS reader or your blog.

    To make things even easier, use the GitHub bundle for TextMate to be able to create Gists from your favorite editor. Don’t forget to setup your GitHub username and token:

    $ git config --global github.user username
    $ git config --global github.token 0123456789yourf0123456789token
    

    Try it: girrst.appspot.com

  • The Delicious API access over Yahoo OAuth in Ruby on Rails adventure

    I spent a little time today getting Yahoo’s OAuth implementation to work with Omniauth. This seems pretty straightforward, but it isn’t.

    First, what I tried to accomplish:

    1. Have a user sign in with his/her Delicious account
    2. Use the Delicious username to retrieve a bunch of feeds

    Step 1 might seem unnecessary as Delicious’ API only requires authentication to post/update stuff, but I want to store some user settings and stuff. OAuth allows me to use their existing data, instead of creating my own registration process.

    I continued to setup a project in rails, init a Git repo and fill my Gemfile with the gems required for using omniauth plus some extra:

    Gems

    Touch omniauth.rb in config/initializers and the basics for using the Yahoo OAuth provider. Yahoo isn’t supported by default, so we’ll be creating our own strategy later in lib/oauth-strategies/yahoo.rb.

    module OmniAuth
      module Strategies
        autoload :Yahoo, 'lib/oauth-strategies/yahoo'
      end
    end
    
    Rails.application.config.middleware.use OmniAuth::Builder do
      provider :yahoo, 'consumer key', 'consumer secret'
    end
    

    Visit Yahoo’s developer page and create a new project. Choose standard and fill out the rest of the form to match your application. Pay extra attention to Application Domain, enter a url that’s accessible to the outside world. You’ll see why when you’ve completed the form. I’m building a Delicious app so I specified that I require extra user data and choose to have read/write access to Delicious.

    Yahoo Projects

    When you press the Get API Key button, you’re required to upload a file to your server, accessible via the url you’ve just entered under Application Domain. There are three buttons, one of which falsely suggests that you can skip this step. Pressing it will only tell you that you have to do it anyway.. nice. This still gave me the impression that this the whole Application Domain thing was optional, though. Mistake.. I’ll tell you why in a minute.

    Alright, so we’ve completed the form and are presented with our consumer key and consumer secret. Add them to the omniauth.rb configuration.

    Create the folder lib/oauth-strategies and touch yahoo.rb. I tried the default OAuth implementation, didn’t work. After some research on GitHub. I found that there was already a pull request waiting with a Yahoo OAuth strategy, neato. Paste the code into your yahoo.rb strategy file. At this point I was pretty confident that this wouldn’t be a hassle after all. Run bundle install and start your server. Now visit the yahoo auth url at http://localhost:3000/auth/yahoo. The first thing you’ll run into happens when you’re an oldskool Delicious user. This means you’re account is not yet hooked up to your Yahoo account and you’ll get an error saying that you’re login is incorrect. After merging my Delicious and Yahoo accounts, I hoped I had fixed the issue and tried again. Aaaand BAM: “401 Forbidden”. Stumped me at first, but after checking the full response Yahoo told me this: “Custom port is not allowed or the host is not registered with this consumer key”. So I thought I was clever and started the WEBRick server on port 80. No effect, same error.

    Forbidden

    This is when I remembered the Application Domain field.. Yahoo apparently does not like you developing on your localhost, while every other OAuth provider works fine, fuck. So, I setup the whole thing on my server and ran the thing again. Success! It redirects to Yahoo and asks for permission. The callback doesn’t go too well, though. Use this guide to add the route to a custom callback, even though it’s not working yet.

    I started debugging by overriding the callback_phase method and checking out where things started failing. The standard callback_phase method uses name.to_sym to get the name of the provider (yahoo in this case). This didn’t work, so I hardcoded it. Calling super also caused trouble. Long story short, it needed a lot of tweaking.

    Eventually I got it to work, but noticed that the nickname Yahoo OAuth returns is not the one from Delicious.. crap! Luckily Delicious adds the username to it’s authenticated post feeds. Allowing me to grab it and add it to the user profile. The full yahoo.rb now looks like this:

    module OmniAuth
      module Strategies
        class Yahoo >; OmniAuth::Strategies::OAuth
        unloadable
    
        def initialize(app, consumer_key, consumer_secret)
            super(app, :yahoo, consumer_key, consumer_secret,
                  :site               => "https://api.login.yahoo.com",
                  :request_token_path => "/oauth/v2/get_request_token",
                  :authorize_path     => "/oauth/v2/request_auth",
                  :access_token_path  => "/oauth/v2/get_token"
            )
          end
    
          def callback_phase
            request_token = ::OAuth::RequestToken.new(consumer, session[:oauth][:yahoo].delete(:request_token), session[:oauth][:yahoo].delete(:request_secret))
            @access_token = request_token.get_access_token(:oauth_verifier => request.params['oauth_verifier'])
    
            @env['omniauth.auth'] = auth_hash
            call_app!
    
          rescue ::OAuth::Unauthorized => e
            fail!(:invalid_credentials, e)
          end
    
          def auth_hash
            OmniAuth::Utils.deep_merge(super, {
              'uid' => @access_token.params[:xoauth_yahoo_guid],
              'user_info' => user_info,
              'extra' => {'user_hash' => user_hash}
            })
          end
    
          def user_info
            user_hash
            profile = user_hash['profile'] || {}
            username = Nokogiri::XML::parse(@access_token.get("http://api.del.icio.us/v2/posts/recent?count=1").body).root['user']
            {
              'nickname'    => username,
              'name'        => "%s %s" % [profile['givenName'], profile['familyName']],
              'location'    => profile['location'],
              'image'       => (profile['image'] || {})['imageUrl'],
              'description' => nil,
              'urls'        => {'Profile' => profile['uri']}
            }
          end
    
          def user_hash
            @user_hash ||= MultiJson.decode(@access_token.get("http://social.yahooapis.com/v1/user/#{@access_token.params[:xoauth_yahoo_guid]}/profile?format=json").body)
          end
    
       end
      end
    end
    

    Alright, everything is setup to work marvelously with ASCIIcast’s guide, which explains how to allow users to sign in with OAuth and remain logged in until they decide to sign out. Thanks to Yahoo for adding some pitfalls (some of which I probably forgot to describe) here and there to keep things interesting.

    *note to self: install pretty code plugin for WordPress.. EDIT: Done!