The Talking Rails Application

Posted almost 7 years back at Spejman On Rails

After a long time without publishing anything, I have finished an example of what you can do with festivaltts for Ruby: A Ruby on Rails application that talks!

You can test it at: http://thetalkingrailsapp.sergioespeja.com/

I hope it gives you ideas for your RoR applications!

Episode 69: Markaby in Helper

Posted almost 7 years back at Railscasts

Do you ever need to generate HTML code in a helper method? Placing it directly in Ruby strings is not very pretty. Learn a great way to generate HTML through Markaby in this episode.

Using ActiveResource to consume web-services

Posted almost 7 years back at The Rails Way - all

Today I’m reviewing Joe Van Dyk’s monkeycharger application, which is a web-service for storing and charging credit cards. I loved looking at this app, because its only interface is a RESTful web service: there is no HTML involved. (If you’ve never written an app that only exposes a web-service UI, you ought to. It’s a blast.)

In general, Joe has done a fantastic job with keeping the controllers slim and moving logic to models. The only significant gripe I had with the application is that it is not ActiveResource compatible.

For those of you that are late to the party, ActiveResource is the newest addition to the Rails family. It lets you declare and consume web-services using an ActiveRecord-like interface…BUT. It is opinionated software, just like the rest of Rails, and makes certain assumptions about the web-services being consumed.

  1. The service must understand Rails-style REST URLs. (e.g. “POST /credit_cards.xml” to create a credit card, etc.)
  2. The service must respond with a single XML-serialized object (Rails-style).
  3. The service must make appropriate use of HTTP status codes (404 if the requested record cannot be found, 422 if any validations fail, etc.).

It’s really not much to ask, and working with ActiveResource (or “ares” as we affectively call it) is a real joy.

However, monkeycharger tends to do things like the following:

1
2
3
4
5
6
7
8
9
10
class AuthorizationsController < ApplicationController
  def create
    @credit_card   = Authorizer.prepare_credit_card_for_authorization(params)
    transaction_id = Authorizer::authorize!(:amount => params[:amount], :credit_card => @credit_card)
    response.headers['X-AuthorizationSuccess'] = true
    render :text => transaction_id
  rescue AuthorizationError => e
    render :text => e.message
  end
end

Three things: the request is not representing an “authorization” object, the response is not XML, and errors are not employing HTTP status codes to indicate failure.

Fortunately, this is all really, really easy to fix. First, you need (for this specific example) an Authorization model (to encapsulate both the the XML serialization and the actual authorization).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Authorization
  attr_reader :attributes

  def initialize(attributes)
    @attributes = attributes
  end

  def credit_card
    @credit_card ||= Authorizer.prepare_credit_card_for_authorization(attributes)
  end

  def authorize!
    @transaction_id = Authorizer.authorize!(:amount => attributes[:amount],
      :credit_card => credit_card)
  end

  def to_xml
    { :transaction_id => @transaction_id }.to_xml(:root => "authorization")
  end
end

Then, we rework the AuthorizationsController to use the model:

1
2
3
4
5
6
7
8
class AuthorizationsController < ApplicationController
  def create
    authorization = Authorization.new(params[:authorization])
    authorization.authorize!
    render :xml => authorization.to_xml, :status => :created
  rescue AuthorizationError => e
    render :xml => "<errors><error>#{e.message}</error></errors>", :status => :unprocessable_entity
  end

(Note the use of the “created” status, which is HTTP status code 201. Other verbs just use “ok”, status code 200, to indicate success. Also, with an error, we return an “unprocessable_entity” status, which is HTTP status code 422. ActiveResource will treat that as a failed validation.)

With that change, you could now use ActiveResource to authorize a credit card transaction:

1
2
3
4
5
6
7
8
9
10
11
12
class Authorization < ActiveResource::Base
  self.site = "http://my.monkeycharger.site"
end

auth = Authorization.new(:amount => 15, :credit_card_id => 1234,
  :remote_key => remote_key_for_card)

if auth.save
  puts "success: #{auth.transaction_id}"
else
  puts "error: #{auth.errors.full_messages.to_sentence}"
end

It should be mentioned, too, that making an app ActiveResource-compatible does nothing to harm compatibility with non-ActiveResource clients. Everything is XML, both ways, with HTTP status codes being used to report whether a request succeeded or not. Win-win!

Obviously, real, working code trumps theoretical whiteboard sketches every time, and Joe is to be congratulated on what’s done. Even though ActiveResource-compatibility can buy you a lot, you should always evaluate whether you really need it and implement accordingly.

Rimuhosting...singing their praises

Posted almost 7 years back at Luke Redpath - Home

I don’t usually post this kind of thing on my blog but when somebody experiences a level of customer service that seems to be so lacking these days, one feels the need to shout about it.

I’ve been hosting this blog on RimuHosting for about a year now – a basic 160MB VPS setup running nginx and one mongrel to power this blog and lighty on my second IP for PHP apps (like Mint Stats and RoundCube Webmail. The VPS also acts as a home to my mail and Subversion repositories.

In all the time I’ve been with RimuHosting I’ve experienced good uptime with problems being sorted out quickly and efficiently. I’ve not had much need to trouble their support team but having just purchased a shiny copy of Warehouse I needed some more RAM to handle a second mongrel instance. I submitted a support ticket asking for a quote, indicating that if it should cost less than an extra $10 a month that they should proceed.

In the time it took me to purchase and download a copy of Warehouse, scp it to my server and untar the thing, my VPS was restarting with its extra memory. All in all, about 5 minutes from the time I submitted my ticket. On a holiday weekend. On a Sunday. That is true customer service.

So, if you are in the market for a personal geek-friendly VPS at a decent price with great support then consider this an obligatory plug for RimuHosting. Tell ’em Luke sent ya!

Update: Warehouse is now up and running.

MyFitBuddy.com Launched!

Posted almost 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 almost 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 almost 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 almost 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 almost 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 almost 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 almost 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 almost 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 almost 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 almost 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 almost 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/