Sharing Data With Gestures: Rails & Heroku Setup

In part I of this series, you saw how we made a simple mobile app in the Corona framework that responds to a "bump" like action (called a "thump") to send a message to another mobile device. The communication between the two mobile devices occurs between an intermediary server process that matches two "thumped" devices by both timestamp and distance. In this tutorial, we will setup the intermediary server process with Ruby on Rails.

Let's start by creating our project. Since we will be using the geokit plugin to help with our geospatial calculations, we have to create this project in Rails 2.3.5 as the plugin is not 3.0 compatible.

After logging into your server/hosting account (in our case we're using Heroku), type the following:

The above statements will create a directory and start a new rails project inside of it. If you have 3.0 installed on your development machine, you might need to install RVM and create a separate gemset for this project. However, doing this is outside the scope of the tutorial. Now let's install the geokit plugin.

Once this completes, we need to add our gem to the project inside the Rails::Initializer.run do |config| block of our environment.rb file:

Now that this plugin has been added to the project, we need to run a rake command to make sure all the required gems are installed in our system.

Geokit relies on the database to do some rather sophisticated distance calculations. Because of this, the default SQLite database that a rails project comes with will not work. Geokit requires that we use either a mysql or postgres db to store our data. Even though heroku uses postgres by default, it is more common for development machines to have mysql installed. The beauty of using Rails and ActiveRecord is that it doesn't matter. We can develop our app with MySQL and it will work seamlessly with postgres.

Now we'll update our database.yml file to point at our newly created development database "thumpserver".

Finally our project creation process is complete. We can start coding the logic inside our thumpserver.

Rails has a simple generator method that creates a REST based resource for data CRUD. If that last sentence didn't make any sense, I suggest you google "rails restful resources" to find out more. Essentially with one command we can create a database table, model, controller and routes inside the project.

Our resource is called thump, so by generating it in this fashion, it will be available at the url /thump once our server is running. We specified 5 fields to be created for our database table:

deviceid: the mobile device's UID
lat: latitude provided by the location service
lng: longitude
message: the message that will be transmitted to the users who have thumped
received: this is a boolean to mark once a message has been received so it can't be sent again

Rails will "automagically" create timestamp fields called created_at and updated_at. We will use created_at later on in our example.

When we generated our resource, a rails database migration file was created in the "db" folder of the project. The filename should appear to be something like this: TIMESTAMP_create_thumps.rb

We need to modify this file to ensure that our location can be stored with enough decimal places. To do this simply replace these two lines:

With the following lines:

This will ensure that our latitude and longitude fields can contain at most 8 decimal places.

Also, to avoid having the "received" field in our database be NULL, we need to add a setting so that it's value is false by default. Again we can do this by replacing this line:

With this line:

Now that our migration is setup, we can run the rake command that will actually create the table inside the database:

To take inputs for our data, we will be using the "create" action in our thump controller. In addition to this, we need a "search" action that will take some parameters and search through the database to match the two thumped devices. We need to modify our routes.rb in the config directory to respond to the URL /thump/search on a GET request. We can do this by replacing this line:

With this line

Next up, let's add the following lines to our thump.rb file inside app/models.

The first line makes our model "mappable". This gives us some extra query methods to help calculate the distance between two coordinate sets. The next line adds some simple validations to our thump data model to ensure that when we get a thump message it contains the proper fields.

Finally, we get to create our actions for creating and searching data in our controller. Thanks to the beauty and simplicity of ActiveRecord, our "create" action is rather simple:

In the case that our validations fail, we will return a json object with :success=>false. In part III of the tutorial we will expand our mobile app to account for this.

Our search "action" is slightly more complex as it uses some of the query helpers from geokit:

Let's break this down:

Essentially we are querying for our "thump" match in the database. A device will send along its own latitude and longitude which will be our origin point. Our conditions ensure that we don't accidentally find our own device by excluding our own deviceid from the result set. We also only want to search thumps where the "received" field is false. To find the closest match in both distance and time, we will order our results by distance between the 2 points in ascending order (i.e. closest) and time created or created_at in descending order to find the most recent. It is obviously an unlikely event that there will be any conflicting "thumps" for our test app, but this kind of query could hold up to a multi-user application if we wanted it to.

The raise command will bump our code progression into the rescue block which will return :success=>false if we can't find a matching thump. This will ensure that our mobile app will at least receive something back in the event of an error. If the object does exist, we will set the "received" field to true to ensure that this message will not be matched in a subsequent data request. Our render statement will return a JSON object that the device receiving the "thump" will interpret.

To test this out, we can run a command in the Rails console to create a sample record with an origin point of New York City:

In order to get a "thump" match, or a successful return, we can first start our server on the default port 3000:

And then hit the following URL:

http://localhost:3000/thumps/search?thump[deviceid]=A&thump[lat]=40.7141667&thump[lng]=-74.0063889

If all goes well, the browser should display the following:

This simulates a device called "A" receiving a "thump" message from device B. And there we have it!

Next Time. . .

Stayed tuned for part III of this series, where we will push the server app to Heroku and upgrade our mobile app to communicate with the server.

Tags:

Comments

Related Articles