MyFitBuddy.com Launched!

Posted about 7 years back at Shane's Brain Extension

MyFitBuddy.com logo

I’m pleased to announce the launch of MyFitBuddy.com, a workout tracking tool with social networking features. It allows you to log your workouts at the gym, sports training, your run in the park, or any other type of physical activity, and see the improvement over time. You can add your workout buddies as friends, and keep in touch with their workouts as well.

I mainly built this site for myself, as I wanted a super simple way to keep a record of my workouts and see graphs of my improvement. I thought it would be a great idea for a social site, as many studies have shown that people exercise more when they have a workout buddy or do it as part of a group. In MyFitBuddy.com, you will be motivated to exercise by seeing the activity of your friends and others on the site.

Some of the other interesting features on the site include user generated exercise information from Wikipedia, and videos of exercise form from YouTube. Soon I’ll be adding weight and calorie tracking, as well as the ability to SMS text in your workouts from your mobile phone. The site is currently completely free to use.

Give it a spin and help me knock off some bugs. I’d love to hear feedback and any suggestions.

Update: KillerStarups, a sort of digg for startups, is the first to review MyFitBuddy.com. If you are in a generous mood, please vote for it.

MyFitBuddy.com Launched!

Posted about 7 years back at Shane's Brain Extension

MyFitBuddy.com logo

I’m pleased to announce the launch of MyFitBuddy.com, a workout tracking tool with social networking features. It allows you to log your workouts at the gym, sports training, your run in the park, or any other type of physical activity, and see the improvement over time. You can add your workout buddies as friends, and keep in touch with their workouts as well.

I mainly built this site for myself, as I wanted a super simple way to keep a record of my workouts and see graphs of my improvement. I thought it would be a great idea for a social site, as many studies have shown that people exercise more when they have a workout buddy or do it as part of a group. In MyFitBuddy.com, you will be motivated to exercise by seeing the activity of your friends and others on the site.

Some of the other interesting features on the site include user generated exercise information from Wikipedia, and videos of exercise form from YouTube. Soon I’ll be adding weight and calorie tracking, as well as the ability to SMS text in your workouts from your mobile phone. The site is currently completely free to use.

Give it a spin and help me knock off some bugs. I’d love to hear feedback and any suggestions.

Update: KillerStarups, a sort of digg for startups, is the first to review MyFitBuddy.com. If you are in a generous mood, please vote for it.

Outsmarted by Edge Rails

Posted about 7 years back at Alloy Code - Home

One of the cool things about starting new applications based on Edge Rails (as opposed to a stable gem version) is that I get access to all the awesome new features right away. Sure, there are a few panic moments when I get hit with unexpected bugs, and I don’t use SVN externals to link to the Rails trunk any more [1], but every now and then, I’m pleasantly surprised by something that I hadn’t previously read about.

I was in the process of adding counter_cache support to an application which had some very deep parent-child relationships, and I needed to generate a migration to add the _count column.

script/generate migration add_widgets_count_to_product

Imagine my surprise when I opened up the newly-created migration file in Textmate, and saw the following:

 class AddWidgetsCountToProduct < ActiveRecord::Migration
    def self.up
      add_column :products, :widgets_count, :type, :null => :no?, :default => :maybe?
    end

    def self.down
      remove_column :products, :widgets_count
    end
  end

After a little digging, I found this in the Rails Trac: Automatically generate add/remove column commands in specially named migrations. It would seem that Ryan Davis has put together some REGEX magic along with some meta-programming to help out people like me who give their migrations very literal names about what the migration will do.

This is a great little timesaver, but now it has me wondering what other neat features have slipped without my noticing them. It looks like it may be time for me to add the Trac timeline RSS feed to my reader, so I can keep a sharper eye out for these sorts of treats.

[1]: These days, when I start a new project, I freeze a version of edge Rails into the application, that way, I get most of the cutting edge features, and a much lower chance of introducing unexpected trouble every time I type ‘svn up.’ Periodically, I review what’s changed in trunk since I started, and if there’s some gotta-have-it feature, I’ll re-freeze.

Outsmarted by Edge Rails

Posted about 7 years back at Alloy Code - Home

One of the cool things about starting new applications based on Edge Rails (as opposed to a stable gem version) is that I get access to all the awesome new features right away. Sure, there are a few panic moments when I get hit with unexpected bugs, and I don’t use SVN externals to link to the Rails trunk any more [1], but every now and then, I’m pleasantly surprised by something that I hadn’t previously read about.

I was in the process of adding counter_cache support to an application which had some very deep parent-child relationships, and I needed to generate a migration to add the _count column.

script/generate migration add_widgets_count_to_product

Imagine my surprise when I opened up the newly-created migration file in Textmate, and saw the following:

 class AddWidgetsCountToProduct < ActiveRecord::Migration
    def self.up
      add_column :products, :widgets_count, :type, :null => :no?, :default => :maybe?
    end

    def self.down
      remove_column :products, :widgets_count
    end
  end

After a little digging, I found this in the Rails Trac: Automatically generate add/remove column commands in specially named migrations. It would seem that Ryan Davis has put together some REGEX magic along with some meta-programming to help out people like me who give their migrations very literal names about what the migration will do.

This is a great little timesaver, but now it has me wondering what other neat features have slipped without my noticing them. It looks like it may be time for me to add the Trac timeline RSS feed to my reader, so I can keep a sharper eye out for these sorts of treats.

[1]: These days, when I start a new project, I freeze a version of edge Rails into the application, that way, I get most of the cutting edge features, and a much lower chance of introducing unexpected trouble every time I type ‘svn up.’ Periodically, I review what’s changed in trunk since I started, and if there’s some gotta-have-it feature, I’ll re-freeze.

Applying CPR to Mephisto

Posted about 7 years back at Mephisto - Home

I’ve just added the over eager Mark Dagget to the Mephisto Core Team. He’s the author the open source project RAM (Ruby Asset Manager), as well as Pledgie. His main task is keep Mephisto on life support, starting with adding his unreleased but excellent Exception Notifier plugin.

Sending SMS messages from your Rails application

Posted about 7 years back at Luke Redpath - Home

Something I’ve seen come up on the Ruby/Rails mailing lists/google groups from time to time is how to send SMS messages from your Rails app. In this article, I’ll introduce you to my Ruby Clickatell library and how to use it to send SMS messages from your Rails application in no time.

When it comes to sending an SMS using Ruby there are two approaches you can take. The first – and more complicated – is to use your own hardware and something like the ruby-sms library to communicate with the hardware. This set-up is time consuming, a pain to maintain and probably not very scalable.

The second option is to take the much easier route and use an existing SMS gateway service. There are many SMS gateways out there that offer APIs (ranging from HTTP/FTP based to email and COM-based); one such provider is Clickatell who are one of the bigger providers out there with a range of services whose customers include Barclays Bank, the BBC and CNN.

Getting started with the Ruby Clickatell gem

Before you can start sending SMS messages from your Rails app, you’ll need a Clickatell account. You can sign up for an account (Clickatell Central API) on their website. Once you have signed up you can log into your account centre and add an HTTP service to your account – this will give you an API key that you will need to use in your code.

Once you’ve signed up, you need to install the Ruby Clickatell gem. I’ve just released version 0.4 and its fast approaching being stable for production use – all it needs is some users to test it out a bit more extensively. So install it and give it a go:

$ sudo gem install clickatell

The gem also comes with a handy command-line utility, “sms”, which can be used to send SMS messages directly from the command line. For more information, simply run:

$ sms --help

More information can be found on the website.

Integrating with Rails

For our basic example application, which will use REST-ful conventions, we will expose a single resource – sms – which we can POST to to send an SMS to a specified recipient. First of all, lets create a simple wrapper around the Clickatell API which will act as our “resource” that takes a hash containing our username/password/api-key and has an ActiveRecord-style create method.

require 'clickatell'

class SMS
  def initialize(config)
    @config = config
  end
  
  def create(recipient, message_text)
    api.send_message(recipient, message_text)
  end
  
  private
    def api
      @api ||= Clickatell::API.authenticate(
        @config[:api_key],
        @config[:username],
        @config[:password]
      )
    end
end

The above wrapper isn’t strictly necessary but it helps to keep our controller as skinny as possible.

For convenience, we’ll want to keep our Clickatell credentials in a YAML file in the config folder of our Rails app:

# config/clickatell.yml
api_key: abcdefghi123
username: joebloggs
password: secret

We’ll also want to access this config within our Rails app easily:

# config/environments/production.rb
CLICKATELL_CONFIG = YAML.load(File.open(File.join(RAILS_ROOT, 'config', 'clickatell.yml')))

h3. Bringing it altogether

Now we’ll want to configure our routing to expose our SMS resource:

ActionController::Routing::Routes.draw do |map|
  map.resource :sms
end

Next, we’ll create our form under app/views/sms/new.rhtml:

<% form_tag '/sms', :method => :post do -%>
  <label>Enter the recipients mobile number:</label>
  <%= text_field_tag "recipient" %>
  <label>Enter your message:</label>
  <%= text_area_tag "message_text" %>
  <%= submit_tag "Send SMS" %>
<% end %>

Finally, all we have to do is create our controller’s create method to handle the form submission.

class SmsController < ApplicationController
  def create
    sms = SMS.new(CLICKATELL_CONFIG)
    sms.create(params[:recipient], params[:message_text])
    flash[:notice] = "Message sent succesfully!"
    redirect_to :back
  rescue Clickatell::API::Error => e
    flash[:error] = "Clickatell API error: #{e.message}"
    redirect_to :back
  end
end

And thats all there is to it. Of course, in a real application you might want to think about things such as validation of required attributes and message length. I’ll leave that as an exercise to the reader.

For more information:

* Ruby Clickatell API Website * Ruby Clickatell Documentation * Rubyforge project page * Clickatell Gateway information

PGR4 event ? Atoms ? .. so close yet so far.

Posted about 7 years back at work.rowanhick.com

Oh the humanity of it all! On my way to work this morning I was stopped in my tracks by two Ariel Atoms parked outfront of an events place just round the corner. Instant parallel thought trains rocked through my mind, how the hell are they road legal in Canada ? and how the hell do I get myself in the passenger seat ?. Then a 360 Modena rocks up, along with a Porker. What's going on ? Finally I look out of my Atom induced haze to see the XBox 360 signage everywhere. Aha. Makes sense...Project Gotham Racing 4. Righto so I rock back to the office. Get dressed so I look more professional than bike courier, rock back and start talking to various people. 5 mins later I'd managed to wangle a potential ride later in the day after telling my true tale of woe that I left New Zealand when an Atom track day was going down and missed out on the drive of my life. The clock strikes 4 (after hearing the Ferrari opening it up many times during the afternoon... Torture! Torture I tell you...). I jump up, grab camera, rock round the corner. "Oh No" The Police. (with a heavy weighting on the period there) Who would've thought that would've happened? No cars were going anywhere. Period. However the silver lining is at least I'm on the list for a track day for next summer, which gives me a good 10 months to work out how to justify the money for it to my S.O.

Goodbye MediaTemple

Posted about 7 years back at work.rowanhick.com

Okay, I'm not one to publicly rant but really, I've given up with the performance of MediaTemple's GridServer implementation. More to the point the marketing and statements simply do not measure up to what actually has happened with this blog at Mediatemple. It's not high load at all, never been dugg, slashdotted or anything else that might bring ill fate to a web site, however it's been subject to outages last week and weekend. Maybe someone had tried deploying a facebook app using the same grid server cluster my site was on ? Who knows. But whatever happened to the "no single point of failure" and "rapid scaling"... ? My particular favourite piece of copy is the "Guaranteed Resources" bit. Couple that with a sub par customer support response and the plug was pulled. I do know personally of one other with a media temple account (who I had recommended MT), he's serving static pages only and experiencing no troubles, so credit where credit is due. If you're backing it with a database, be prepared... Of course, now I've setup Murphy to come bit me in the ass with his law on my new host!.

helpful Ruby idioms (to me)

Posted about 7 years back at Mike Mondragon

Before coming to Ruby I had spent a lot of time coding Java and some C/C++ . Like any programmer I spend a lot of time working with data structures (and now blocks in Ruby). I would often fall back to idioms concerning data structure size in those legacy languages but in Ruby they are bad habits.

The Enumerable module that is mixed in to Array, Hash, and others is your friend. Use its idioms to tell you the state of your data structure rather raw details as in Java that imply state. For instance in Java, we test for elements in a collection with.size() (like myhash.size() == 0), but in Ruby having elements (or not) is more statefully conveyed with .any? and .empty?

Some goodies in Enumerable :

  • any? – do we have any elements?
  • empty? (in Array class) – are we void of elements?
  • detect – return the first element that matches the criteria in the block
  • select – return all the elements that match the criteria in a block
  • each_with_index – enumerate over elements in the data structure AND automatically give me an index (which means I don’t have to predefine one)

And example in an irb session:

mike@butch 10001 ~$ irb
irb(main):001:0> a = ['hello', 'ruby-20', 'ruby']
=> ["hello", "ruby-20", "ruby"]
irb(main):002:0> a.detect{|v| v =~ /foo/}
=> nil
irb(main):003:0> a.detect{|v| v =~ /hello/}
=> "hello" 
irb(main):004:0> a.detect{|v| v =~ /ruby/}
=> "ruby-20" 
irb(main):005:0> a.select{|v| v =~ /ruby/}
=> ["ruby-20", "ruby"]
irb(main):006:0> a.empty?
=> false
irb(main):007:0> a.any?
=> true
irb(main):008:0> a.each_with_index{|v,i| puts "index: #{i}, val #{v}"}
index: 0, val hello
index: 1, val ruby-20
index: 2, val ruby
=> ["hello", "ruby-20", "ruby"]

helpful Ruby idioms (to me)

Posted about 7 years back at Mike Mondragon

Before coming to Ruby I had spent a lot of time coding Java and some C/C++ . Like any programmer I spend a lot of time working with data structures (and now blocks in Ruby). I would often fall back to idioms concerning data structure size in those legacy languages but in Ruby they are bad habits.

The Enumerable module that is mixed in to Array, Hash, and others is your friend. Use its idioms to tell you the state of your data structure rather raw details as in Java that imply state. For instance in Java, we test for elements in a collection with.size() (like myhash.size() == 0), but in Ruby having elements (or not) is more statefully conveyed with .any? and .empty?

Some goodies in Enumerable :

  • any? – do we have any elements?
  • empty? (in Array class) – are we void of elements?
  • detect – return the first element that matches the criteria in the block
  • select – return all the elements that match the criteria in a block
  • each_with_index – enumerate over elements in the data structure AND automatically give me an index (which means I don’t have to predefine one)

And example in an irb session:

mike@butch 10001 ~$ irb
irb(main):001:0> a = ['hello', 'ruby-20', 'ruby']
=> ["hello", "ruby-20", "ruby"]
irb(main):002:0> a.detect{|v| v =~ /foo/}
=> nil
irb(main):003:0> a.detect{|v| v =~ /hello/}
=> "hello"
irb(main):004:0> a.detect{|v| v =~ /ruby/}
=> "ruby-20"
irb(main):005:0> a.select{|v| v =~ /ruby/}
=> ["ruby-20", "ruby"]
irb(main):006:0> a.empty?
=> false
irb(main):007:0> a.any?
=> true
irb(main):008:0> a.each_with_index{|v,i| puts "index: #{i}, val #{v}"}
index: 0, val hello
index: 1, val ruby-20
index: 2, val ruby
=> ["hello", "ruby-20", "ruby"]

mms2r 1.1.7 Released

Posted about 7 years back at Mike Mondragon

mms2r version 1.1.7 has been released!

http://mms2r.rubyforge.org/

DESCRIPTION:

MMS2R is a library that decodes the parts of an MMS message to disk while
stripping out advertising injected by the cellphone carriers. MMS messages are
multipart email and the carriers often inject branding into these messages. Use
MMS2R if you want to get at the real user generated content from a MMS without
having to deal with the cruft from the carriers.

If MMS2R is not aware of a particular carrier no extra processing is done
to the MMS other than decoding and consolidating its media.

Contact the author to add additional carriers to be processed by the
library. Suggestions and patches appreciated and welcomed!

Corpus of carriers currently processed by MMS2R:

  • AT&T => mms.att.net
  • AT&T/Cingular => mmode.com
  • Cingular => mms.mycingular.com
  • Cingular => cingularme.com
  • Dobson/Cellular One => mms.dobson.net
  • Helio => mms.myhelio.com
  • Nextel => messaging.nextel.com
  • Orange (Poland) => mmsemail.orange.pl
  • Sprint => pm.sprint.com
  • Sprint => messaging.sprintpcs.com
  • T-Mobile => tmomail.net
  • Verizon => vzwpix.com
  • Verizon => vtext.com

Changes:

== 1.1.7 / 2007-08-25 (Adam Nergal, friend of Skwisgaar, but not Pickles)

  • Added suport for Orange of Poland Orange mmsemail.orange.pl (Zbigniew
    Sobiecki)
  • Cleaned up documentation modifiers
  • Cleaned out non-Ruby code idioms

http://mms2r.rubyforge.org/

mms2r 1.1.7 Released

Posted about 7 years back at Mike Mondragon

mms2r version 1.1.7 has been released!

http://mms2r.rubyforge.org/

DESCRIPTION:

MMS2R is a library that decodes the parts of an MMS message to disk while stripping out advertising injected by the cellphone carriers. MMS messages are multipart email and the carriers often inject branding into these messages. Use MMS2R if you want to get at the real user generated content from a MMS without having to deal with the cruft from the carriers.

If MMS2R is not aware of a particular carrier no extra processing is done to the MMS other than decoding and consolidating its media.

Contact the author to add additional carriers to be processed by the library. Suggestions and patches appreciated and welcomed!

Corpus of carriers currently processed by MMS2R:

  • AT&T => mms.att.net
  • AT&T/Cingular => mmode.com
  • Cingular => mms.mycingular.com
  • Cingular => cingularme.com
  • Dobson/Cellular One => mms.dobson.net
  • Helio => mms.myhelio.com
  • Nextel => messaging.nextel.com
  • Orange (Poland) => mmsemail.orange.pl
  • Sprint => pm.sprint.com
  • Sprint => messaging.sprintpcs.com
  • T-Mobile => tmomail.net
  • Verizon => vzwpix.com
  • Verizon => vtext.com

Changes:

== 1.1.7 / 2007-08-25 (Adam Nergal, friend of Skwisgaar, but not Pickles)

  • Added suport for Orange of Poland Orange mmsemail.orange.pl (Zbigniew Sobiecki)
  • Cleaned up documentation modifiers
  • Cleaned out non-Ruby code idioms

http://mms2r.rubyforge.org/

Episode 68: OpenID Authentication

Posted about 7 years back at Railscasts

Ever wonder how to implement OpenID authentication in your Rails app? This episode will show you how to add it to a site with an existing authentication system.

Moving to Nginx and Cap2.0

Posted about 7 years back at zerosum dirt(nap) - Home

So a few months back I started using nginx on my staging server, front-ending for Mongrel, and just recently I’ve stated migrating some production stuff over to it. It’s pretty great as a lightweight Apache replacement. Incredibly simple syntax, very quick and close to the bone. Most of my production stuff still runs on Apache, but that may soon be changing. I also finally made the leap to Capistrano 2.0. Loving the new namespaced task hierarchy.

Anyway, here’s a simple alternative maintenance page recipe for Capistrano’s deploy:web:disable target and the corresponding Nginx config to make use of it. In case you’re unfamiliar with it, the disable web task basically redirects all requests to a maintenance page until deploy:web:enable is run, which returns things to normal. This recipe assumes you’ve created your own (static) maintenance.html page in public/maintenance.html and that it makes use of existing stylesheets and images — meaning that you don’t want to rewrite those requests.

in config/deploy.rb:

namespace :deploy do
  desc "Disable requests to the app, show maintenance page"
  web.task :disable, :roles => :web do
    run "cp #{current_path}/public/maintenance.html  #{shared_path}/system/maintenance.html"
  end

  desc "Re-enable the web server by deleting any maintenance file"
  web.task :enable, :roles => :web do
    run "rm #{shared_path}/system/maintenance.html"
  end
end

in nginx.conf (within your server block definition):

# allow requests for images, js, css, and icons to go through
# even if cap has been used to disable the site
if ($request_filename ~* /(images|javascripts|stylehseets)/) { break; }
if ($request_filename ~* \.ico$) { break; }

# for cap's deploy:web:disable task
if (-f $document_root/system/maintenance.html) {
    rewrite ^(.*)$ /system/maintenance.html last;
    break;
}

On updating vs. editing.

Posted about 7 years back at The Hobo Blog

We recently had some great posts on the forum from larryk. I was just replying to Larry, and, what with the cup of rather fine Darjeeling, and an indulgently large pile of mini gingerbread-man biscuits, I got into the swing of it until I thought - this is a blog post!

Quick background – Larry has a model with 60(!) fields, and he has a page with <editor> tags for all of them. He’s discovered an O(n^2) problem because each call to <edit> calls updatable_by? which has to check all 60 fields to see what has changed.

Not pretty.

First of all, some background on the rationale behind the design of editable_by and updatable_by.

The Hobo permission system serves two totally different roles:

  1. Policing POST and PUT requests from the client
  2. Automatically adjusting the view rendering so people see only what is appropriate for them.

For 1, we have to cope with the fact that a single request can change many fields, so we have the moethod updatable_by? which is responsible for allowing/denying the overall change to the object. We know what the old state is, we know what the new state is, so we ask “is this change ok?”

For 2, we want to know something entirely different – is a user allowed to edit a specific field? For that (as spotted by Matt in that same thread) you can write a method editable_by? which takes the user and the name of the field they want to edit. There’s no “new” value in this case, because how do we know what the user will do?

Hang on though – the hobo_model generator doesn’t even create a stub for editable_by?. Why not?

Well although editable_by? and updatable_by? are quite different questions, the underlying application logic is always going to be the same. updatable_by? has to cover every eventuality, so in theory it should be possible to somehow derive editable_by? from updatable_by?.

In theory.

Well it turns out there’s a clever trick that does something along those lines.

Hmmm. Clever trick. Clever tricks can be good and they can be veeeeeery bad. Right now I’m still leaning towards liking this particular trick, but I’m not totally sure yet.

It goes like this. Hobo defined an extremely volatile type Hobo::Undefined. If you so much as look at one of these it goes BANG! (raises a Hobo::UndefinedAccessError). When Hobo needs to know if field ‘foo’ is editable by user Fred, it looks for the editable_by? method. If that’s not there the clever trick comes into play. Hobo creates a “hypothetical” new object, exactly the same as the current one, but field ‘foo’ has the value Hobo::Undefined. Hobo can now ask if the object is updatable_by? the current user, passing this tricky little thing as the new state of the object.

Now if your updatable_by? method depends on the value of ‘foo’ in any way - BANG! Hobo catches the exception and says nope – not editable.

It’s not fool-proof, but it gives the correct results in many situations, and if it lets you down, well you’ll just have to write your editable_by? method. Make the common things easy, keep the uncommon things possible.

Back to Larry’s problem, editable_by? will generally be quicker than updatable_by? as it doesn’t have to check for all the many things that might have been done to an object. So defining editable_by? should improve things a lot.

We’ve been thinking about the whole morph-the-view-to-the-user thing though, and we’ve come to a conclusion that should make things even faster. The behaviour of <editor> where it automatically degrades to a view is pretty nifty, and very useful in some situations, but in our apps at least 95% of the calls to <editor> are always going to result in an editor. The overhead of going to the permission system is really undesirable.

So we’ll probably make the auto-degrade feature optional, and the default will be off. If you want an editor that will degrade to a view when the user has no edit permission, you’ll need to do something like:

<editor or_view/>

I actually prefer that as it says more clearly what you’re getting – an editor, or possibly a view.

We can do something similar for the few tags that render nothing when the user is not allowed to perform the action in question, e.g.

<delete_button if_allowed/>