Configuring CapGun

October 10th, 2009

I’ve long been a fan of Capistrano, the Ruby deployment tool that is typically used for deploying Rails applications. And I’ve also been impressed by the work of Glenn Vanderburg and his colleagues at Relevance. So I took notice when I recently read about CapGun, which is useful for sending email notifications whenever a project is deployed.

The point of this post is that very recently I had the opportunity to install and configure CapGun for a client. The blurb on github told me how to install and configure CapGun. Under the heading of Usage I was encouraged to read the first paragraph:

Good news: it just works.

Well, almost. CapGun does “just work” once you’ve configured it correctly. Included in the config sample to be added to deploy.rb was:

# define the options for the actual emails that go out -- :recipients is the only required option
set :cap_gun_email_envelope, { :recipients => %w[joe@example.com, jane@example.com] }

Unfortunately this was not quite complete enough for CapGun to work. Instead it died deep in the bowels of net/smtp.rb:

/usr/local/lib/ruby/1.8/net/smtp.rb:930:in `check_response': 555 5.5.2 Syntax error. 7sm1592402qwb.55 (Net::SMTPFatalError)
	from /usr/local/lib/ruby/1.8/net/smtp.rb:899:in `getok'
	from /usr/local/lib/ruby/1.8/net/smtp.rb:828:in `mailfrom'
	from /usr/local/lib/ruby/1.8/net/smtp.rb:653:in `sendmail'
	from /usr/local/lib/ruby/gems/1.8/gems/actionmailer-2.3.4/lib/action_mailer/base.rb:684:in `perform_delivery_smtp'
	from /usr/local/lib/ruby/1.8/net/smtp.rb:526:in `start'
	from /usr/local/lib/ruby/gems/1.8/gems/actionmailer-2.3.4/lib/action_mailer/base.rb:682:in `perform_delivery_smtp'
	from /usr/local/lib/ruby/gems/1.8/gems/actionmailer-2.3.4/lib/action_mailer/base.rb:523:in `__send__'
	from /usr/local/lib/ruby/gems/1.8/gems/actionmailer-2.3.4/lib/action_mailer/base.rb:523:in `deliver!'
	from /usr/local/lib/ruby/gems/1.8/gems/actionmailer-2.3.4/lib/action_mailer/base.rb:395:in `method_missing'
	from ./vendor/plugins/cap_gun/lib/cap_gun.rb:70

The lesson was that the :cap_gun_email_envelope needed to be configured with :from as well as :recipients. And the good news is that the people at Relevance have just accepted my documentation patch.

And the even better news is that now CapGun does “just work”. It’s a very handy tool for keeping everyone in a team informed about deployments in an automated and timely manner.

Tags: deployment capistrano capgun ruby rails | Comments (0)

Rails Camp 5 and Sydney RORO Meetup

June 11th, 2009

I think it’s time I gave a brief update about a couple of professional events within the Australian Ruby community that I’ve recently enjoyed.

Rails Camp 5

Last month over an extended weekend the fifth Australian Rails Camp was held in the Queensland Gold Coast Hinterland. The venue was superb, much fun was had and a great deal of thanks is due to the Brisbane contingent who organised the event.

Having started the weekend working on my own to improve my iPhone development skills, particularly with respect to using ObjectiveResource to integrate an iPhone app with a Rails backend, I was actually very pleased that I didn’t continue on this path beyond Saturday afternoon. From Saturday evening onwards I teamed up with Martin Stannard and Michael Koukoullis to develop a Heroku-like tool called Bivouac. I thoroughly enjoyed our collaboration and learnt much from it. For anyone else considering attending a future Rails Camp I thoroughly recommend getting involved in a team project rather than working alone.

More on Bivouac in a later post. Meanwhile, you can find the source on github.

Sydney June RORO Meeting

Earlier this week the monthly Sydney RORO (Ruby on Rails Oceania) meeting featured a dozen lightning talks. In one of my talks I shared a technique for providing XML in a legacy format via REST, XML Builder and a presenter object. Whilst the example is contrived, the technique is one that I used to handle a requirement for a client recently.

Here are the slides:

In fairness, I must give credit to Obie Fernandez for his coverage of XML Builder in his book, The Rails Way, which gave me a head start.

Tags: railscamp collaboration rails ruby xml rest | Comments (0)

ActionWebService with Rails 2.2

February 8th, 2009

I encountered a trick for young players the other day when providing XML-RPC web service support within a Rails application.

Since Rails 2.0 was introduced, RESTful web services via ActiveResource have been supported in preference to SOAP or XML-RPC web services. Indeed, ActionWebService was dropped from Rails when version 2.0 was released.

However, there are times when the need to provide an interface to another application mandates the use of SOAP or XML-RPC. Recently I had a need to provide an XML-RPC web service server within a Rails application. Fortunately, a version of ActionWebService has been kept up to date on GitHub together with instructions for implementing it.

As I was developing my support for XML-RPC calls, I found chapter 25 of Thomas and Hansson’s “Agile Web Development with Rails” (second edition) invaluable.

For simplicity’s sake, let’s say my controller was:

class BackendController < ApplicationController
  wsdl_service_name 'Backend'
  web_service_api BackendApi
  web_service_scaffold :invoke if Rails.env == 'development'

  def foo_bar(args)
    # method code goes here
  end
end

And here is an XML-RPC test client:

require 'xmlrpc/client'
require 'pp'

server = XMLRPC::Client.new2("http://example.com/backend/api")
result = server.call("FooBar", ["arg1", "arg2", "arg3"])

pp result

Notice that the call is to a method called “FooBar” whereas the method within the Rails controller is called “foo_bar”. If you’re like me you will have originally fallen into the trap of assuming that the remote call will have the same name as the controller method rather than the camel case equivalent.

Tags: xml-rpc actionwebservice rails | Comments (0)

Rails Camp in the Adelaide Hills

November 23rd, 2008

I think I’ve just about recovered from last weekend’s Rails Camp in the Adelaide Hills. Whether I was hacking or socialising, as the hour got later each evening it just seemed easier to ignore the fact that I was going to pay later for the lack of sleep.

It was worth it though. This was the best attended Rails Camp yet with about 70 Rails developers converging from different parts of Australia. One of the aspects I like about these events is their self-organising nature. The unconference style encourages learning within small groups for much of the event. In my case I was determined to practice using Cucumber, Webrat and Machinist and benefited from the fact that several others were also cutting their teeth on Cucumber.

There are also plenty of opportunities to share with the whole group. At this camp I was fortunate that Pete Yandell, the author of Machinist, was one of those who spoke. I also thoroughly enjoyed the lengthy discussion which was precipitated by Pat Allan’s talk about Freelancing.

Quite apart from the learning opportunities, I appreciated catching up with other Rails developers I hadn’t seen for a while and making new friendships. I’m looking forward to my next Rails Camp already. Hopefully the number of attendees doesn’t increase. I think it has reached its limit for a good unconference.

Tags: railscamp rails unconference | Comments (1)

Dynamic CSS with Rails

October 24th, 2008

I’ve sometimes wondered why CSS isn’t more dynamic.

Take, for example, the styles applied to the sub-menu on the services page of this site. To achieve the highlighting of the current service, I combine a Rails view and CSS as follows:

The Rails View

<div id="<%= @current_service.name %>">
  <div id="secondaryNav">
    <ul>
      <% @services.each do |service| %> 
        <li class="<%= service.name %>"><%= link_to service.heading, service_path(service) %></li>
      <% end %>
    </ul>	
  </div>
</div>

The CSS

#agileweb #secondaryNav .agileweb a,
#java #secondaryNav .java a,
#coaching #secondaryNav .coaching a,
#mentoring #secondaryNav .mentoring a,
#overview #secondaryNav .overview a,
#advice #secondaryNav .advice a {
  color: #99CC00;
  text-decoration: underline;
}

Handling a new service

That does the trick nicely until I decide to add a new service. Wouldn’t it be nice to have that CSS regenerated dynamically whenever I create, update or delete a service?

Enter a new Ruby module:

# lib/dynamic_css.rb
module DynamicCss
  def generate_services_nav_links_css
    return if RAILS_ENV == "test"
    FileUtils.cd File.expand_path("public/stylesheets", RAILS_ROOT)
    File.open("servicesnav.css", "w") do |out|
      service_names = []
      services = Service.find :all
      services.each { |s| service_names << s.name }
      service_names.each_with_index do |name, i|
        out.print "##{name} #secondaryNav .#{name} a"
        if i + 1 < service_names.size
          out.puts ","
        else
          out.puts " {"
        end
      end  
      out.puts "  color: #99CC00;"
      out.puts "  text-decoration: underline;"
      out.puts "}"
    end
  end
end

Then a small adjustment to invoke the css regeneration via a filter in my admin services controller:

class Admin::ServicesController < AdminLayoutController
  include DynamicCss
  
  after_filter :generate_services_nav_links_css, :only => [:create, :update, :destroy]

# remainder of controller

end

Lastly, to ensure that the servicesnav.css file exists by the time one of the public services pages is requested:

# config/initializers/services_nav_css.rb

include DynamicCss

generate_services_nav_links_css

Admittedly this is a specific case, but this example shows that it is relatively straightforward to dynamically generate CSS within a Rails app if required.

Tags: rails css | Comments (3)

Code Syntax Highlighting

October 17th, 2008

Having just implemented code syntax highlighting in this blog in addition to Textile formatting, I thought I’d share how I did it.

After a little research, I decided that Arya Asemanfar’s tm_syntax_highlighting plugin looked the most promising. Arya’s blog post about it was particularly helpful.

Prerequisites

Install the oniguruma system library (see link in the plugin README).

Install the ultraviolet gem, which will also install the textpow and oniguruma gems.

sudo gem install ultraviolet

1. Install the Plugin

./script/plugin install git://github.com/arya/tm_syntax_highlighting

2. Copy all themes from ultraviolet:

./script/generate syntax_css

3. Create defaults initializer

# config/initializers/tm_syntax.rb
TmSyntaxHighlighting.defaults = {:theme => "mac_classic", :line_numbers => false, :lang => "ruby"}

4. Create an application helper method to parse the Textile and code:

Note: I have used “c0de” instead of “code” here just to enable this code to be parsed!

# app/helpers/application_helper.rb
def parse_textile_and_code_syntax(text)
  text_pieces = text.split(/(<c0de>|<c0de lang="[A-Za-z0-9_-]+">|<c0de lang='[A-Za-z0-9_-]+'>|<\/c0de>)/)
  in_pre = false
  language = nil
  text_pieces.collect do |piece|
    if piece =~ /^<c0de( lang=(["'])?(.*)\2)?>$/
      language = $3
      in_pre = true
      nil
    elsif piece == "</c0de>"
      in_pre = false
      language = nil
      nil
    elsif in_pre
      code(piece.strip, :lang => language, :theme => "mac_classic")
    else
      RedCloth.new(piece.strip).to_html
    end
  end
end

5. Use the helper in the views

<%= parse_textile_and_code_syntax(@blog_post.post) %>

6. Add CSS for horizontal scrolling

pre {
  margin: 10px 10px;
  padding: 10px 10px;
  line-height: 15px;
  overflow: auto;
  font-family: "Monaco", "Courier New", courier;
  font-size: 12px;
}

Tags: ruby rails syntax highlighting | Comments (0)