Articles tagged 'coding'

Announcing Dotplan Feb 18

I've re-focused how I keep track of notes and thoughts for ideas and plans, and in so doing, given an update to an old concept.

In Masters of Doom, it details how John Carmack, genius progrmamer at id software, used .plan files to keep track of his todos and work plans when building out classic games like Wolfenstein 3d, Doom, and Quake. He eventually started to make these public, as a way of feeding back to his community and fanbase, exactly what he was up to.

Introducing Dotplan, a very simple content system based upon the excellent Middleman framework used for Ruby content management. It's a default Middleman blog style setup, allowing unlimited plans to be created. You can simply clone it and hit the ground running, and write all your plans in Markdown - build the site into HTML, and ship to your favourite static host or CDN. Or keep it all to yourself, and simply run it locally as a journal to keep you sane!

There are two ways of utilising Dotplan - if you like the idea of just writing, then clone the repository and do just that. All the plans content is by default excluded from the source control, meaning you can continue to pull down Dotplan updates as it changes, and you won't have to worry about merging or conflicts. Just make sure to back up your content through some other means - perhaps using Dropbox or another similar solution. It's a clean separation of the code to power the tool, and your content.

Alternatively, fork the repo and clone your fork, then feel free to remove the line in .gitignore which stops plans from being included. You can then check them into source control to make sure they are safe. The advantage is you can more easily track changes to your content, roll things back etc - the downside is it may make it slightly harder to pull down upstream Dotplan changes going forward.

However you do it, Dotplan is a simple way to start getting organised - or at the least, get all of those creative thoughts out of your head and down somewhere. That gives you the headspace to prioritize and focus, and makes sure you can always refer back to them in the coming weeks or months.

Check out Dotplan here.

Comments

Tic-Tac-Toe with Vue.js Jan 17

Following on from our look at setting up the Vue.js and React frameworks in Rails 5.1, this post will look at building a small little component in Vue.js, strictly on the client-side (just HTML, JS and CSS, no backend Rails app!).

We're going to implement our own little version of the classic Tic-Tac-Toe game, called Tic-Tac-Vue.

Setup

We'll start by creating our structure - create a folder, an HTML page, a JS file, and a stylesheet.

mkdir tic-tac-vue
cd tic-tac-vue
touch index.html
touch app.js
touch app.css

Our HTML file is going to be very basic, let's run through our initial markup:

<html>
  <head>
    <title>Tic Tac Vue</title>
    <script src="http://unpkg.com/vue"></script>
    <link rel="stylesheet" href="./app.css" />
  </head>
  <body>
    <script src="./app.js" type="text/javascript"></script>
  </body>
</html>

This sets up our page, brings in Vue.js, our CSS and our own JS file (both currently empty).

Next up, we're going to add a root element for our app to live - this goes in our HTML body, above our script reference to our JS file:

<div id="app"></div>

And now we need the markup for our game grid itself, which we're going to put in a script tag with a special template type - this too goes in our body, and above our JS file script ref:

<script type="text/x-template" id="grid">
  <div class="grid">
    <div class="row" v-for="row in rows">
      <div class="column" v-for="column in row">
        {{column}}
      </div>
    </div>
  </div>
</script>

Let's run through that so it's clear - our grid is made up of rows and columns, fairly simple. It'll be based on a 2D array representing that data, and so we're looping through our rows data, which is an array of arrays, and then looping through each individual array, which contains the values for our individual columns. We'll be expecting three rows, and three columns for Tic-Tac-Toe of course. The column values will either be blank (unplayed), or an x or an o if someone has played in that space. That's it!

Quick note: Why do we separate the markup like this? You could include that markup within the #app div directly when the app is so simple, however there are still a couple of downsides to this. The first is that you have to then be careful which markup you're using - the browser will process that as HTML within the DOM long before Vue gets to it, meaning that if you then start to use any markup specific to how Vue works (like referencing components with tags) that isn't HTML5 compliant, the browser could end up stripping it out, or doing odd things with it that'll affect how your app works. Additionally, most apps are going to have enough complexity to have at least one component (rather than defining the app as just a root Vue app), so it makes sense to define that as such from the beginning, as it's neater and clearer to follow, as well as more cleanly allowing for expansion as the need arises. We've separated our page container markup (to host our client-side app) from the app itself, which is comprised of our specific Vue markup template, and the JavaScript we'll be writing to implement the functionality itself.

With our HTML out of the way, let's format our grid so it looks like one - here is our CSS:

.row {
  clear: both;
}
.column {
  border: 1px solid #000;
  width: 50px;
  height: 35px;
  float: left;
  text-align: center;
  padding-top: 15px;
}

Fairly simple - we're floating each column and having them on the same row, with each row clearing the float to move on to the next row - we setup a border for the grid itself, set a specific height and width, and make sure that if a text value is shown (x or o) it looks nice within the box for that space on the game grid.

Now we get to the fun part - our JavaScript! We have two tasks now to get our initial grid functional - we have to create and define our grid as a component, and we then have to create our Vue app with our grid component being rendered into our #app empty div above.

First, we define our grid component:

var Grid = Vue.component('grid', {
  template: '#grid'
});

This is easy enough to follow - we define a component, named Grid, using the template with id grid, and store it as Grid for reference elsewhere.

We're going to need to set our initial data for the component though - the rows and columns that the template renders:

data: function() {
    return {
      rows: [
        ['', '', ''],
        ['', '', ''],
        ['', '', '']
      ]
    };
  }

As we described above for our template, rows is a 2D array, an array of arrays, each array representing a row, and each value within representing a column in that row - and we're starting with them all blank and unplayed.

Next up, let's define our App:

var App = new Vue({
  el: '#app',
  components: {
    Grid
  },
  render: function(createElement) {
    return createElement(Grid);
  }
});

Here we specify the element our app will reside in, so #app, and then the components we need to use - we just have one, our Grid component. Lastly, as we don't have any markup within our #app element to tell our app how and what to render, we do it with a custom render method, referencing our game grid component.

Open up index.html now in a browser and you'll see our grid! That's great, but it doesn't do a lot. Let's start making it so we can play the spaces, and get a game going!

Game on

First of all, we want the user to be able to select a space, and if it's empty, it'll place an x or an o in it, depending upon whose turn it is. Let's add a variable to our data to determine whose go it is, and which one is next:

  data: function() {
    return {
      rows: [
        ['', '', ''],
        ['', '', ''],
        ['', '', '']
      ],
      next: 'x'
    };
  },

So we've just added that next attribute with a default value of x to our component data.

Now we'll add a method to our component definition, that'll handle when a space is tapped:

methods: {
  tap: function(e) {
    if (e.target.innerText == '') {
      e.target.innerText = this.next;
      this.next = (this.next == 'x' ? 'o' : 'x');
    }
  }
}

So it only works if the space is free, sets the space, and then toggles which player is next. Reload our page, tap a space, and… nothing. That's because we have one final step - we need to hook up tapping on the game grid spaces to that method we just wrote!

Change the markup in our #grid component template, so it's like this:

<div class="column" v-for="column in row" v-on:click="tap">
  {{column}}
</div>

The v-on:click attribute is added, which adds an event handler for the click event to the component, pointing at the tap method. Try reloading again now, et voila! Tapping on spaces sets the next player character in the space, with no overwriting involved. Pretty neat, and not a lot of code either!

Data binding

We have our action in place, but we can't do much with spaces played as we're not updating our data based on the user input - we're just directly updating the UI. Instead, let's update our data array, and have that reflect to the UI, which is a much better way to handle things.

In our markup, we'll alter our Grid component template as follows:

<script type="text/x-template" id="grid">
  <div class="grid">
    <div class="row" v-for="(row, row_index) in rows">
      <div class="column" v-for="(column, column_index) in row" v-on:click="tap" v-bind:data-row="row_index" v-bind:data-column="column_index">
        {{column}}
      </div>
    </div>
  </div>
</script>

Specifically, we're keeping track of the row and column index in our two-dimensional array looping, and then binding it as row and column data variables to reference when a space is played.

Over to our tap method now:

tap: function(e) {
  if (e.target.innerText == '') {
    let rows = this.rows;
    rows[e.target.attributes['data-row'].value][e.target.attributes['data-column'].value] = this.next;
    this.rows = rows.slice(0);
    this.next = (this.next == 'x' ? 'o' : 'x');
  }
}

Here we are grabbing the data rows, then updating the value of our column, using the data-row and data-column bindings present on the element tapped to find the right location in the array. The reason we do a slice(0) is because the way that the data binding works in Vue, the rows property in our data is reactive (meaning it is being watched for changes), but individual changes within the array won't trigger that watcher, and therefore a re-render. Instead we're using a local rows variable, and then effectively copying the whole array back into our data, which triggers our reaction and an update of the UI using our template (rather than us modifying the element directly).

So now we have our app data binding correctly, we can implement logic based on the current rows/columns data to check for win criteria!

Winner winner

To check for a winner, we need to check each row for three matching values, each column for three matching values, and the two diagonal paths for three matching values. If any of those are true, we have a winner! We can boil this down to the following:

checkWinner: function() {
  return (
    this.checkValues(this.rows[0]) ||
    this.checkValues(this.rows[1]) ||
    this.checkValues(this.rows[2]) ||
    this.checkValues([this.rows[0][0], this.rows[1][0], this.rows[2][0]]) ||
    this.checkValues([this.rows[0][1], this.rows[1][1], this.rows[2][1]]) ||
    this.checkValues([this.rows[0][2], this.rows[1][2], this.rows[2][2]]) ||
    this.checkValues([this.rows[0][0], this.rows[1][1], this.rows[2][2]]) ||
    this.checkValues([this.rows[0][2], this.rows[1][1], this.rows[2][0]]));
},
checkValues: function(values) {
  return (values[0] != '' && values[1] != '' && values[2] != '' && (values[0] === values[1]) && (values[1] === values[2]));
}

Add those methods to our component underneath our tap definition.

checkValues is easy enough - we expect an array of three values, we make sure all the values are not blank, and that they are the same. checkWinner then calls checkValues for all of our different possible value arrays - firstly checking each of the three rows (each of those is already an array with three elements), then the three columns, and then lastly, the two diagonals.

With our win logic in place, we now just need to hook it up. We'll add an additional property, finished, to our data:

data: function() {
  return {
    rows: [
      ['', '', ''],
      ['', '', ''],
      ['', '', '']
    ],
    next: 'x',
    finished: false
  };
},

We'll then reference that to make sure that you can't keep playing once we're finished - at the top of the tap method:

tap: function(e) {
  if (!this.finished && e.target.innerText == '') {

Lastly in terms of logic, we just need to amend the end of our tap method:

if (this.checkWinner()) {
  this.finished = true;
} else {
  this.next = (this.next == 'x' ? 'o' : 'x');
}

So we only go to our next player if we've not found a winner - if we have found a winner, we mark the game as finished.

Playing the game now, we'll see that if one player wins, you can't continue playing. But some kind of feedback to indicate that the game is over (and to say who has won!) would be good. Easy! We can do that with a single additional line in our template - at the bottom within our .grid div, below the rows & columns, add:

<div class="status" v-if="finished">Finished! {{next}} wins!</div>

Add the following to app.css to make sure our message sits underneath the grid:

.status {
  clear: both;
}

Now when someone wins and the game stops, you can see who has won!

Whose turn?

It'd be good if we could show whose turn it is next, in case the players lose track. We already have the data, and as you can probably guess from how we displayed the finish state, it's fairly easy to do - change our .status text div to the following:

<div class="status">
  <span v-if="finished">Finished! {{next}} wins!</span>
  <span v-else>Next go: {{next}}</span>
</div>

Here we're making use of v-if and v-else to make sure only one shows - either we're showing whose turn is next, or we show the finished/winner text as the game is over!

Replayability

We're almost there with our incredible take on Tic-Tac-Toe, but rather than having to refresh the page after every game to go again, wouldn't it be cool if we could just press a restart button instead?

We're going to move our code to determine the next player into its own method, so we can re-use it:

nextPlayer: function() {
  this.next = (this.next == 'x' ? 'o' : 'x');
},

Next up, we'll change the tap method to use that function - so for the winner check or next player logic:

if (this.checkWinner()) {
  this.finished = true;
} else {
  this.nextPlayer();
}

Now, we'll implement our restart method:

restart: function(e) {
  this.rows = [
    ['', '', ''],
    ['', '', ''],
    ['', '', '']
  ];
  this.finished = false;
  this.nextPlayer();
},

This just resets the rows, makes sure the game is no longer finished, and triggers the next player. Let's hook that up to something in the template now:

<div class="status">
  <div v-if="finished">
    <p>Finished! {{next}} wins!</p>
    <a v-on:click="restart">Restart</a>
  </div>
  <span v-else>Next go: {{next}}</span>
</div>

Our restart link shows when the game is finished, and tapping it resets our game accordingly!

Stalemate

The last thing we need to handle, is the dreaded stalemate. When two world class Tic-Tac-Toe players are locked together, head-to-head, neither willing to budge an inch, we could end up with a tied game. What then? The game doesn't get marked as finished, but there are no more moves to make. The games cannot continue!

So let's add a check for that state, and handle it accordingly. We'll start by refactoring our checkValues method, so we can re-use the blank check within it for checking if all the spaces have been played:

checkValues: function(values) {
  return this.checkValuesPresent(values) && this.checkValuesMatch(values);
},
checkValuesPresent: function(values) {
  return (values[0] != '' && values[1] != '' && values[2] != '');
},
checkValuesMatch: function(values) {
  return (values[0] === values[1]) && (values[1] === values[2]);
}

As you can see, we've separated the two parts of checkValues into a check for whether the specified values are all present (checkValuesPresent) and whether the values all match (checkValuesMatch). Now we can use the checkValuesPresent check in our stalemate logic - add the following method:

checkStalemate: function() {
  return !this.finished &&
    (this.checkValuesPresent(this.rows[0]) &&
    this.checkValuesPresent(this.rows[1]) &&
    this.checkValuesPresent(this.rows[2]));
},

We're just making sure that the game isn't yet finished, and all of the rows have values present - then it must be a stalemate!

We'll add an additional property to track stalemates, so add the default value to our data:

next: 'x',
finished: false,
stalemate: false

And then we'll update our tap method to account for checking for stalemates:

if (this.checkWinner()) {
  this.finished = true;
} else if (this.checkStalemate()) {
  this.stalemate = true;
  this.finished = true;
} else {
  this.nextPlayer();
}

We have to check for a stalemate after a win, because there might be a winner on the very last space! If it is a stalemate, the game is finished, but also the stalemate property is set.

We can now use this on the frontend within the template to display something more relevant:

<div class="status">
  <div v-if="finished">
    <p v-if="stalemate">It's a draw! Stalemate!</p>
    <p v-else>Finished! {{next}} wins!</p>
    <a v-on:click="restart">Restart</a>
  </div>
  <span v-else>Next go: {{next}}</span>
</div>

We're either displaying our draw statement for stalemates, or the winner text, and the restart button either way so a new game can start. The only thing left, is to make sure our stalemate flag is reset on restart:

restart: function(e) {
  this.rows = [
    ['', '', ''],
    ['', '', ''],
    ['', '', '']
  ];
  this.finished = false;
  this.stalemate = false;
  this.nextPlayer();
},

Now win, lose or draw, players can continue playing!

Wrapping up

So our Tic-Tac-Toe game is pretty much feature complete, at least in terms of a basic game two people can play on a single computer. It saves on paper and drawing, and we've done it all with just a little HTML + CSS, and a bit of fun JavaScript, all thanks to Vue.js!

This is one way to build a Vue.js app, and is better suited for small, self-contained ideas like this. In a future post we'll look at going back to Webpack and using vue-cli, so that we can do things like having each component of our app (template HTML and JS logic) in its own .vue file, that's pre-processed accordingly to build the JS for our page. As projects increase in complexity, that helps to give them structure and keep them maintainable.

Check out the full code for this post at https://github.com/ejdraper/tic-tac-vue, and you can play the game itself below!

Comments

Frontend Fun with Rails 5.1 and Webpacker Jan 8

Client side frameworks for more responsive web apps are en vogue, and have been for a number of years now. The frameworks themselves change in popularity - to begin with it was Backbone, then Ember and Angular - more recently, frameworks like Vue and React have become the most popular choices.

Let it never be said that Rails doesn't move with the times though, as Rails 5.1 introduced the Webpacker gem, providing a smarter interface to allow you to use Webpack config for bundling JavaScript packages on the client side of your Rails web app. This means easier access to stable versions of client side frameworks, and easier maintainability for those dependencies going forward. It's a separate gem too, allowing you to also use it in Rails 4.2+ apps if needed.

Let's take a look at just how easy it is in Rails 5.1 now to setup Vue.js and React. Make sure you have the latest version of Rails installed, and then we'll setup a new empty app:

rails new frontend-fun

You can also specify to use webpack as part of this command and skip the next couple of steps:

rails new frontend-fun --webpack

However, if you're looking to add this to an existing Rails app, these next two steps will allow you to add Webpacker ready to use.

Within the app, add the webpacker gem to Gemfile:

gem "webpacker"

Then run bundle from a terminal in the root directory of the project to install the gem:

bundle install

At this point, we'll now have some additional commands available to us courtesy of the webpacker gem, to install frontend packages. We'll get things rolling with the initial command to prep our webpacker config:

 bin/rails webpacker:install

With that done, we should probably setup a basic page for testing, so create a new controller app/controllers/site_controller.rb, with the following Ruby code in it:

class SiteController < ApplicationController
end

Then we'll create a template for our content, at app/views/site/index.html.erb:

<h1>FrontendFun</h1>

Finally, in our config/routes.rb file, we'll add a reference for the root of our app to the new controller and action:

Rails.application.routes.draw do
  root "site#index"
end

If you test our app now, you'll see the FrontendFun header. Last thing we now need to do is hook in our webpacker JS, with a reference from our layout template. In app/views/layouts/application.html.erb, below the javascript_include_tag reference in the <head>, add:

<%= javascript_pack_tag 'application' %>

Now if you reload the page, and look in the JavaScript console, you should see:

Hello World from Webpacker

Webpacker - it's alive!

Vue.js

To install Vue.js, run the following commands:

bin/rails webpacker:install:vue
bin/yarn install

This will install the Vue.js packages. We'll then hook up the Hello Vue pack that is setup by default, by modifying our javascript_pack_tag line in app/views/layouts/application.html.erb:

<%= javascript_pack_tag 'application', 'hello_vue' %>

Reload our page, and you'll now see Hello Vue! in our page body, which is coming directly from Vue.js!

React

Now, in a production application, you're unlikely to want to use more than one frontend framework, unless you were transitioning from one to another. But, this is FrontendFun, so we're going to add React too!

By now, this should be fairly straightforward, we run:

bin/rails webpacker:install:react
bin/yarn install

This will install the React packages now, and setup a base HelloReact component similar to our HelloVue. So we'll just need to modify our javascript_pack_tag one more time to reference our React pack:

<%= javascript_pack_tag 'application', 'hello_vue', 'hello_react %>

Once more, reload our page, and behold - Hello Vue! and Hello React!.

Two frontend frameworks, setup very easily, co-existing in the same HTML page in our Rails app. The possibilities are practically endless!

Next steps

From here, you can edit either app/javascripts/packs/hello_vue.js and app/javascripts/app.vue if you want to use Vue.js, or app/javascripts/hello_react.jsx for React, adding new components and interactions to build out your frontend, and integrate it with whatever backend functionality your Rails app might offer. You can check out the simple demo Rails app that we've just built up here.

Comments

Adventures in Merb Mar 17

I decided to give Merb a go, and after doing a fair bit of reading up on it, I took the plunge. It’s a little rough around the edges, but that’s probably to be expected given it’s youth - however there are a number of cool features and benefits to using it, and it’s getting better and better as it’s being refactored. I did however come across a few interesting issues getting up and running, so I thought I’d share these to try and make the process easier for others.



I installed the gems from http://merbivore.com, by doing the following:



sudo gem install merb --source=http://merbivore.com --include-dependencies

This gave me the merb-core gem, along with merb-more. However, to get up and running with a database, we really need a database plugin - let’s try DataMapper.



sudo gem install datamapper --source=http://merbivore.com --include-dependencies
sudo gem install merb_datamapper --source=http://merbivore.com --include-dependencies

Now you’d think that a dependency for merb_datamapper would be datamapper itself, however it doesn’t get included, and so you need to download that as a gem, and then download merb_datamapper. We then need a few other gems, including one specific to the database you’ll be connecting to:



sudo gem install data_objects --source=http://merbivore.com
sudo gem install do_sqlite3 --source=http://merbivore.com

As you can see, I chose to install do_sqlite3 for accessing a sqlite3 database. However you could install “do_mysql”, or “do_postgres” to access MySql or PostgreSql databases respectively, and I’m sure there are others. Sqlite users using Mac OS X 10.4 (Tiger) should bear in mind an issue I came across, whereby a strange error is received when attempting to do any database related activity with the do_sqlite3 gem and the default native sqlite3 version that comes with the operating system. This manifested itself as a couple of different strange errors (including a “DataMapper constant not found” error when starting Merb), however the solution was simply to grab the latest sqlite source from www.sqlite.org, build it, and install it. Then try re-installing the do_sqlite3 gem as above, and you should find that they play together much better!



We can now proceed with creating a Merb app to play with:



merb-gen testapp

Looking in the “testapp” folder now shows us the initial structure Merb uses, which is fairly similar to how Rails applications are structured. The main differences that you’ll need to know straight away are that routes are defined in the “router.rb” file within the “config” directory, and that the main settings and application initialization stuff is within “init.rb” in the “config” folder. Let’s setup our app to use DataMapper by changing the “init.rb” file. Find the following lines:



### Uncomment for DataMapper ORM
# use_orm :datamapper

### Uncomment for ActiveRecord ORM
# use_orm :activerecord

### Uncomment for Sequel ORM
# use_orm :sequel

and uncomment the datamapper line, like this



### Uncomment for DataMapper ORM
use_orm :datamapper

### Uncomment for ActiveRecord ORM
# use_orm :activerecord

### Uncomment for Sequel ORM
# use_orm :sequel

This then tells our application to use and load the DataMapper database plugin. Further down in that file you’ll see something similar for testing, and you can choose whether to use rspec, or test_unit. Using rspec is the default. After we change the database settings, we run:



merb-gen

to get it to generate database config. This will create the file “database.sample.yml” in the “config” folder, which we can rename to “database.yml”, and configure correctly. Here is a sample development configuration set to use sqlite3:



:development: &defaults
:adapter: sqlite3
:database: db/testapp_development.sqlite3

Remember to create the “db” directory. Now to finish off our test application, we can create a dummy controller and views, to see our application in action.



merb-gen resource person first_name:string last_name:string date_of_birth:date

Now we need to migrate the data to take into account the new model. Note there are no migration files like in Rails, however there is a Rake task to migrate the data based on the DataMapper definitions with the model classes:

rake dm:db:automigrate

That should now create the database file (“db/testapp_development.sqlite3”), and we should now be able to play around with the model within our application. First, let’s run the application via the console, and inspect the new model:



merb -i
>> Person.count

This will display a count of 0, as there are no people in the database yet. Let’s create one:

>> Person.create({:first_name => "test", :last_name => "dude", :date_of_birth => Time.now})

Only this returns an error!



DataObject::QueryError: Your query failed.
table people has no column named date_of_birth

For some reason, the migrations within DataMapper tend to be a bit erratic - there is a console command you can run however that will often fix issues and sync the model definitions to the database more accurately:



>> DataMapper::Persistence::auto_migrate!

Running our create command from before should now work as expected, with a Person object returned and saved with an ID of 1. You can check to ensure that there is a Person object:



>> Person.count
=> 1
>> Person.all
=> [#Person]
>> Person.first
=> #Person
>> Person[1]
=> #Person

The above queries show how to retrieve all Person instances within the database, just the first, or a specific Person by ID. In this case, the same (and only) Person instance is returned (it’s returned as an array with a single element in the “Person.all” query). But now let’s check out the real deal, and see the web interface - fire it up by just running:



merb

This will start the server, and you can now browse to http://localhost:4000 to see the application. This will show a Merb error page, saying that no route matches the request “/”. This is because while we have a single resource within the application, it’s setup to be exposed by default at http://localhost:4000/people. Browse to that url, and you’ll see the default Merb generated view. Let’s hook this up to the root of the application so it’s accessible at the easier to remember url http://localhost:4000. Within the “router.rb” file in the “config” folder, look for the following lines:



# Change this for your home page to be available at /
# r.match('/').to(:controller => 'whatever', :action =>'index')

and change the second line to read the following (uncommenting it, and changing the controller to our “people” controller):



r.match('/').to(:controller => 'people', :action =>'index')

Now browsing to http://localhost:4000 will show you the same default view for the “people” index as it would if you were browsing http://localhost:4000/people. You can now customize these views to display and interact the models, in a similar fashion as you would do in Rails!



One other thing to bear in mind is that Merb apps default to port 4000 - however running different apps on that default port at differing times will cause issues because of the way the secret session key is managed. This will most likely be fixed in due course, but at the minute running a second app on the same port at a later date will often result in a secret key error - you can run each app on a different port, or simply find the cookie that represents the “lock” on that port by a specific application, and remove it; then a different application won’t have issues using that port. You may well find that re-using a Merb app port with a Rails app also causes an issue, again removing the cookie should fix this.



So that’s pretty much it - a very basic Merb app, some potential pitfalls found and sidestepped, and a powerful, lightweight web application framework at your fingertips. While it’s obvious Merb is a work in progress, it’s also obvious just how useful this framework might become, especially for those looking to create more streamlined, better performing applications.

Comments

Git A Load Of This Mar 12

So it’s already made the rounds on a number of blogs, but having switched to Git about five weeks ago for all my code, I’ve now been using GitHub for the last three or so weeks, and it’s a really great service. The user interface is brilliant, and the integration with Git is incredibly simple. The fact that it’s still in beta means there’s lots more to come, and they’ve been very active at adding in new features over the last few weeks too, including most recently the beginnings of an API! I’m running a number of private repos at GitHub and it’s been nothing but a joy to use. They just announced their pricing plans for when they come out of beta, and it’s more than reasonable for the service they provide. Great job guys!

Comments

iPhone SDK Mar 6

So today was another Apple event, the ‘iPhone roadmap’, and as expected, the SDK was outlined in some depth. To break it down, it basically looks like:

  • The SDK is available, for free, from today (free Apple Developer Connection account required before download)
  • The SDK will require Mac OS X 10.5 Leopard
  • The SDK will provide extensions/additions to XCode/Interface Builder to create iPhone apps, as well as an iPhone simulator, and a remote iPhone debugger
  • The 'App Store’, used to distribute iPhone applications direct to the iPhone and iPod Touch, will debut in June as part of the iPhone 2.0 firmware update - it’ll be available from today for select beta users
  • There is an iPhone developer program, currently US only (expanding soon), that costs $99 to register, that presumably will put you first in line to be one of the select beta users to get hold of and test the iPhone 2.0 update before June
  • Free apps will be just that, free to distribute through the 'App Store’
  • Commercial apps will have price points set by the developer, with 70% kept by the developer, and 30% of the revenue going to Apple
  • Apple already have a number of partners who have been working on iPhone apps, including EA, Sega, Salesforce.com and AOL
It’s hard to get too many more details about the SDK direct from Apple’s iPhone developer site (http://developer.apple.com/iphone) right now, as it’s getting hammered. Hopefully more details will trickle out shortly.

Comments

Ruby link round-up Feb 24

I’ve seen a number of great Ruby articles, tutorials and discussions recently (and not so recently), as well as some interesting projects, so I thought I’d write a quick round-up of links to some of the most interesting stuff. It’s split by category, with a miscellaneous list for stuff that didn’t seem to fit anywhere else.

  • Merb
    • Tutorial on getting up and running with Merb 0.9.0.
    • A list of great Merb articles.
    • An article from Ezra, the guy who created Merb, on using Merb’s integration with Rack to write handlers that run close to the http processing pipeline, while remaining webserver agnostic.
  • Amazon EC2 + S3
    • An article on using Amazon web services, Lucene and Ruby for web crawling.
    • This gem enables really easy setup of EC2 boxes for use with Rails. I’ve tried it. And it rocks.
  • iPhone
    • An article on hosting iPhone subdomains within your Rails app, to display iPhone specific versions of web applications.
    • This article goes into even greater detail on iPhone specific versions of Rails apps.
  • Books
    • Another post from Ezra, who happens to be one of the authors of ‘Deploying Rails Applications’. This post says that the book is now at the final beta stage, and includes some more advanced content such as Apache/Nginx scaling, and Xen setups. I’ve just ordered up the beta PDF, and will be receiving the paperback too when it ships in May. Hoping to do an initial review once I give the beta a read, looks very interesting though.
  • Tools and projects
    • Heroku, online Rails application creation and hosting. Very cool tool for creating or collaborating on a hosted Rails application, all through your browser.
    • Rush, a Ruby based shell, from one of the guys behind Heroku. Interesting concept, along the same sort of lines as Windows Powershell - but because it’s Ruby, it has a much better syntax :-)
    • An article about the usage of Beanstalk, a messaging queue system, to power the Nuby on Rails blog.
    • Hot off the presses, a new Capistrano preview, with some cool features such as better role definitions, and better git integration.
  • Miscellaneous
    • An article on generating feeds using microformats within html.
    • Good post from 37signals about building a web app, and making sure you get it right - even if it means starting over.
    • An article on using Ruby for scripting tasks on Mac OS X.
    • Interesting article on tackling master/slave database setups with Rails.
    • Great screencast on PeepCode about git, a source control tool that is all the rage at the minute. Really good introduction to the tool.
OK so that wasn’t such a quick round-up - but that was the best of the best from the articles and links I’ve come across over the last few months.

Comments

rsync Jan 14

Switched to using rsync to deploy this blog now. Since I re-wrote the blogging software to generate a simple static html site, I needed an easy way to deploy. I was using a Capistrano-esque method of deploying the entire site to dated directories (‘200801142252’, for example), and then I was simply symlinking the public web directory to the most recent release. This has the benefit of being able to quickly roll-back to previous releases (handy when doing major template changes etc), but having to re-deploy the entire site every time I wrote a post wasn’t really very efficient. So I’ve changed it to use the rather brilliant rsync to maintain the site on the webserver now. From my ruby code, I just shell out to rsync as follows:

`rsync -avzr -e ssh #{LOCAL_PATH}/* #{REMOTE_USER}@#{REMOTE_HOST}:#{REMOTE_PATH}`

This runs rsync in verbose, archive mode, using compression, and runs recursively. It specifies the local path, and the remote path for use over ssh (I was using scp over ssh before anyway). It’ll prompt for the password on the command line (although you could setup and specify a key to use with the ssh connection to avoid that). This solution will then keep the local and remote paths in sync, and will mean I can update the blog much more easily and quickly. Hopefully that’ll mean a few more regular posts coming soon… :-)

Comments

Hot Routes Feb 10

Last day or so I’ve come up against a couple of intriguing Rails problems while trying to knock up some plugins for an app I’m writing. I’ll write up the second of the two problems later, but here goes the first…

Put simply, I wanted to define a route within my plugin. My plugin implemented a controller (and also contained a view for that controller, see one of the latest features to hit edge Rails ahead of Rails 2.0).

I searched to try and see if anyone had come up against a similar task, but didn’t see any concrete answers. My testing led me to realise that every time a call to ActionController::Routing::Routes.draw is made, it completely clears and re-generates routes based on the block passed to that method. So simply calling draw with a new block containing my required route wouldn’t work; it’d overwrite other routes, or end up getting overwritten by other routes later in the chain.

I then figured it was time to get cracking with some meta-programming, and that I was going to have to re-define and extend the draw method in order to be able to map the routes I want, and do it in a way that’d be flexible and fair to the original Rails routes file, and other plugins that wanted to toy around with routing. I came up with the following:


module ActionController
    module Routing
        class RouteSet
            alias draw_old draw
            def draw
                draw_old do |map|
                    map.connect "controller/action", :controller => "mycontroller", :action => "myaction"
                    yield map
                end
            end
        end
    end
end


Let’s give this a quick run-through… I’m re-opening the ActionController::Routing module, and specifically the RouteSet class where the draw method exists. I’m using alias to copy the existing draw method to a method name “draw_old”, before re-defining the draw method itself. Within my version of the draw method, I’m calling the old one and passing it a block that firstly defines the routes I wanted to add to the application, and that then yields the appropriate mapper object back to any block passed in to the draw method itself. Dependent on where you want your route to appear in the scheme of things, you could always map your plugins custom routes after you yield the mapper to the calling block, so that they appear after any other routes. Another tweak would be to alias the existing draw method to something like “draw_old_APPNAME”, where APPNAME is the name of your application. This would ensure that if multiple plugins implemented something similar, that they then wouldn’t clash.

There may be a better way to tackle the problem, but after half an hour of working the problem over (mad props to my boy Mike for helping me tweak the solution into something useful and re-usable), I think I came up with a pretty solid answer, and with a bit more time, something that could probably be wrapped up into a module or plugin all of its very own. Bottom line? Ruby as a language rocks, the dynamic nature and meta-programming features opens whole new doors of functional programming to me, and I’m having to really think outside of the box to see some of the amazing things you can do with it.

Comments

Debuggering Feb 5

This is a pretty nice idea, and looks like a really useful tool. It’s in a fairly early stage, but it is shaping up to be quite nice. Think I’ll grab it, take a look, and see if I can help out somehow…

Comments

Get your geek on Feb 2

Mentioning nerd cred in the last post reminded me, my boy Mike recently launched a pet project of his, Geekiverse. It’s a site where you can add your swag, such as CDs, DVDs and games, and review them, and then other nerds can also review the same or similar items. It’s a place to meet other geeks with similar interests, and it’s generally just a really cool site.

Of course, maybe I’m bias - I’m going to be helping Mike and the guys at Geekiverse out with some new features and improvements (in fact, I’ve already tackled one new feature). So check it out, sign up, and share your swag - it’s a site for geeks, by geeks.

Comments

Mac Daddy Sep 24

So I’ve recently got a MacBook Pro, and it’s fucking awesome. For a start, it’s quick, and secondly, I’m finally, after numerous attempts in the past, enjoying the Mac OS X experience. I’m not sure what it is this time around, but I think working on a Mac just feels right in laptop form. I’m running Parallels for all my Windows needs (damn you, VS2005 and C#), and while I’m tempted to also give Boot Camp a go for the gaming aspects (have you seen Company of Heroes? and apparently HL2 runs real nice on the MBP too!), for now I’m sticking with the virtualisation solution.

But I’m also learning TextMate, and man oh man is that a sweet program to use. I’m a little overwhelmed by all the add-ins (sorry, bundles) and shortcuts there are, but at least it’s prettier than emacs :-)

Comments

Page 1 of 3 | Next page