Rails javascript specific layout

Recently I’ve started to favour using small snippets of js.erb for each controller action over using one monolithic javascript controller designed to run the whole application. It means you have small manageable pieces of code which are only loaded when the app needs them, this is also good for your sites security as you do not expose everything at once in a .js file.

The problem I had was that I need to make sure notices are shown on ajax requests as well as normal requests. I started out by having a block of code at the bottom of each js.erb that would show notices like so:

%('#notices').replaceWith('<% escape_javascript(render :partial => "shared/notices")%>');

Which was all well and good except it’s not DRY, and didn’t feel very rails at all. My final solution involved using application.js.erb in layouts, which I didn’t even realise was possible. Check it out:

#application.js.erb

<%= render :partial => "shared/notices" %>

<%= yield %>

#shared/notices.js.erb

if($('#notices')){
  $('#notices').replaceWith('<% escape_javascript(render :partial => "shared/notices.html")%>');
}else{
  notices = $('#header').before('<% escape_javascript(render :partial => "shared/notices.html")%>');
}

#shared/notices.html.erb

<% if flash[:notice] %>
<%= flash[:notice] %>
&lt% end %> <% if flash[:error] %>
>%= flash[:error] %>
<% end %%gt; <%= link_to "close", "#", :class => "close" %> <% javascript_tag do %> noticesTimer = setTimeout(function(){ $('#notices').slideUp()}, 5000); $('#notices .close').click(function(){$('#notices').slideUp(); return false; }); <% end %>

It will only load notices if needed, replace any #notices if it already exists and self hide afterwards.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Development, Ruby / Rails | Tagged , , , | Leave a comment

The Battery Guys, Number 1 for car batteries

I was pretty chuffed to find that after over a year of optimisation, hard work and good service one of my favourite clients thebatteryguys.co.uk have reached the top of googles search results for the term “car batteries” and are second for the term “car battery”.

This has always been a long term goal of thebatteryguys.co.uk, who started of by spending a considerable amount on CPC advertising in order to allow people to be made aware of their top class service. Their core business is next day delivery of batteries for the automative industry. I did not anticipate that in such a short period of time they would have gained this much momentum and achieved the number 1 spot, the optimisations we have made to the site have contributed towards the result, but it’s also plain to see that the amazing service these guys offer has been talked about and people have come to the site through recommendations and not just advertising. Well done guys.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Clients, Development, SEO | Tagged , , , , | Leave a comment

Acts As State Machine error handling

What is it?

Acts as state machine (AASM) is a rubygem for adding finite state machines to Ruby classes. http://github.com/rubyist/aasm. This is a widely used gem/plugin and is the de-facto standard for state management in Ruby on Rails.

Whilst working on the Technophobia Video Uploader (coming soon!!!) I hit a problem with aasm. I’ve used the gem before and think it can be overkill for certain situations but when used correctly has massive benefits.

How it works

The way acts as state machine works is by defining various states and event. The events have rules that determine which state transitions can take place and callbacks which allow functions to be executed at various stages of the transition. Take the code below for example:

 # State Machine
  aasm_column :status
  aasm_initial_state :pending

  aasm_state :pending
  aasm_state :encoded, :enter => :encode_video
  aasm_state :uploaded, :enter => :upload_video

  aasm_state :encode_failed
  aasm_state :upload_failed
  aasm_state :complete

  # State Machine Transitions
  aasm_event :encode do
    transitions :from => :pending, :to => :encoded
  end

  aasm_event :upload do
    transitions :from => :encoded, :to => :uploaded
  end

  aasm_event :complete do
    transitions :from => :uploaded, :to => :complete
  end

  aasm_event :failed do
    transitions :from => :pending, :to => :encode_failed
    transitions :from => :encoded, :to => :upload_failed
  end

This gives me 4 events that will cause the Objects state to move through 6 defined states. By calling Object.encode! I fire the encode event which will transition from the pending state to the encoded state going through any callbacks on the way. The callback method “encode_video” defined for the encode event is fired on entry into the transition. If the object state is anything other than pending I will get and InvalidStateTransition error as the encode! event should only allow pending objects to be processed.

The problem

The sequence which the callbacks and state change is called can be problematic, in the example above I use the enter callback to execute a method “encode_video”, this callback fires before the event status is changed.

    #callbacks and state change
    state.call_action(:before_enter, self)
    state.call_action(:enter, self) #our callback is executed
    self.aasm_current_state = state_name #the state is changed
    state.call_action(:after_enter, self)

This which works great unless you need to change state within the callback method, for example if the callback fails and you change the state to failed.
In my encode_video method I check to see if the process has been successful and if not I call the failed! event, this works and sets the status to the appropriate failure status. However when control is returned to the block of code above, the line “self.aasm_current_state = state_name” changes the state from my failure state to the state as defined in the transition.

The Solution

Fortunately there is a very simple solution do this. You can pass the :error option into the aasm_event method to set a callback that will be used when a StandardError is raised within one of the state callbacks. This will allow the program to keep running but will break out of the code at the correct point before the state is changed. So we change the state machine transitions like so:

  # State Machine Transitions
  aasm_event :encode, :error => :error_raised do
    transitions :from => :pending, :to => :encoded
  end

  aasm_event :upload, :error => :error_raised do
    transitions :from => :encoded, :to => :uploaded
  end

  aasm_event :complete, :error => :error_raised do
    transitions :from => :uploaded, :to => :complete
  end

Then define the error method:

  def error_raised(error)
    failed!
    logger.debug("Error raised in video_encoding #{error.message}")
  end

And finally raise the correct error class in the call back function:


  def encode_video
    begin
      encoder = VideoChimp::Encoder.new
      case encoding_profile.container
        when "mp4" then
          encoder.encode_mp4
        when "flv" then
          encoder.encode_flv
      end
      unless encoder.valid?
        raise StandardError.new("Something went wrong encoding")
      end
    rescue Exception => ex
      raise StandardError.new("Exception in encode_video #{ex.message}")
    end
  end

And thats it. More control over your state machine :D

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Development, Ruby / Rails | Tagged , , , , | Leave a comment

Unobtrusive javascript with Rails 2.3.5

This is my handy little bit of javascript to make it easier to do UJS in Rails 2.3.5. Create a file within your public/javascripts folder called ajax.js containing the following:

//unobtrusive javascript replacements
//setup for format.js block
$.ajaxSetup({
	'beforeSend': function(xhr) { xhr.setRequestHeader('Accept', 'text/javascript') }
});

//for replacing remote_form_form
$.fn.submitWithAjax = function(){
	this.live('submit',function(){
		$.ajax({
			url: $(this).attr("action"),
			type: ($(this.form).find("[name=_method]").attr('value') == undefined) ? 'post' : $(this.form).find("[name=_method]").attr('value'),
			data: $(this).serialize(),
			dataType: 'script'
		});
		return false;
	});
}

//for replacing link_to_remote
$.fn.linkWithAjax = function(){
	//add new click binding
	this.live('click',function(){
		$.ajax({
			url: this.href,
			type: $(this).is('.delete') ? 'delete' : 'get',
			dataType: 'script'
		});
		return false;
	});
}

//Bind links and forms on load
$(function(){
	$('a.remote').linkWithAjax();
	$('form.remote').submitWithAjax();
});

Then include jquery 1.4.2 min and ajax.js in your header, my javascript include line looks like this:

  javascript_include_tag 'jquery','jquery-ui','jrails','ajax', :cache => true

Then all you have to do is give the form_for or link_to tags a class of remote, if you want to delete make sure you give the link a class of delete too. Please note the ajax.js file I have created expects a script back, but you can pass expect html or text content by removing dataType: ‘script’

If you do remove the dataType: ‘script’ option you may want to add a success function. so…

     this.live('click',function(){
		$.ajax({
			url: this.href,
			type: $(this).is('.delete') ? 'delete' : 'get',
			success: function(data){
                             alert(data);
                        }
		});
		return false;
	});

Hope it helps, post a comment if you have a question.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Development, Javascript | Tagged , , , , , | Leave a comment

SRC10 – De-normalising rails applications

Presented by: Daniel Lucraft & Matt Wynne

De-normalisation is just one of many strategies to cope with the scaling requirements of an application. It is the process of devising a method to group relevant data together in an optimal way for the system to return what is required quickly.

During the talk Daniel and Matt explained how Songkick has devised a series of classes to implement a de-normalisation strategy using a key value store in a document based database (MongoDB).

They use the Model View Presenter (MVP Presenter first) design pattern to serve up content for the views on the website. Presenters are first class domain objects tailored for displaying a single page or module of information. So when looking at information on the site you are actually seeing content returned from a document store through the Presenter.

This however presents it’s own bunch of problems. The first and probably most obvious is consistency. Unlike caching, content is not expired and then re-generated on demand, content will be regenerated as and when it is created or updated.

Presenter, Soli and Silovator

A presenter is basically a model which has methods to get only the data required for the view element and store these in the specific document. A typical presenter looks like this:

class EventListingPresenter

  def initialize(event)
    @event = event
  end

  def title;            @event.artists.map(&:name).to_sentance;   end
  def image_count;      @event.images.count;                      end
  def attendance_count; @event.attending_users.count;             end

  #silo creates document on save using silo methods

  silo_method :title
  silo_method :image_count
  silo_method :attendance_count

ends

The silo_method works in a similar way to memoization. Data will attempt to return from the document store and failover to using the actual database through ActiveRecord.

Cache control

Cache expiration is controlled through asynchronous observers called Silovators. These silovators listen for events like create, update and delete on objects and run processes to generate the presenter data for any given presenter. For example:

class EventListingSilovator < AsyncObserver

  listen :create, Attendance do
    Silo.generate(presenter_for(attendance.event))
  end

  listen :update, Venue do
    venue.events.each do |event|
      Silo.generate(presenter_for(event.venue))
    end
  end
end

The silovator processes could be running on any number of machines, which creates another problem with possible race conditions. This is solved using http://github.com/songkick/mega_mutex which will ensure when a job is picked up, no other client will run that job at the same time. Megamutex uses memcache-client so your environment must be setup to use it.

Songkick have multiple background tasks which consume events and perform actions, these include ImageResizer, EmailNotifier and Silovater which all take advantage of mega_mutex to guarantee consistency.

Resources

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Conferences, Development, Ruby / Rails, SRC10 | Leave a comment

Rails3 beta3 Authlogic metaclass error

I noticed this problem when I tried to use authlogic today:
undefined method `metaclass' for Authlogic::Session::Base:Class (NoMethodError)

Turns out the fix is pretty simple bpauly posted a comment on http://railsplugins.org with the following:

metaclass has been deprecated in favor of singleton_class. http://github.com/rails/rails/commit/763f32ab47b96289a4d7b7107411a83164bf69de

The following changes should get you running for now.

callbacks.rb line 69:
if base.metaclass.method_defined?(:set_callback)
if base.singleton_class.method_defined?(:set_callback)

password.rb line 185:
if klass.metaclass.method_defined?(:set_callback)
if klass.singleton_class.method_defined?(:set_callback)

So you don’t have to mess much, I took the liberty of forking github and putting the changes in my rails3 branch, so add this to GemFile to fix:

gem ‘authlogic’, :git => ‘git://github.com/danhawkins/authlogic.git’, :branch => ‘rails3”

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Development, Patches, Ruby / Rails | Tagged , , | 5 Comments

SRC10 – Breaking things with Ruby talk

Presenter: Rory McCune

The breaking things with Ruby session was all about penetration testing and security. It was one of the best sessions I attended while at SRC. A couple of tools and techniques were demonstrated, and the Pen testing process illustrated.

Pen testing consists of, scanning, exploitation and reporting. We were given a walk through and detail of tools used at each stage.

Scanning

NMap is the de-facto tool of choice for this task. You can scan entire networks or single IP’s you can choose which ports you want to scan and many other options. Remote OS detection is even available. Once you have performed your scan you can output XML which can be fed directly into other tools.

One thing that was news to me is that there exists ruby-nmap

Exploitation

It was a real treat to be introduced to metasploit. I didn’t even know this tool existed. I think it’s something that would require a long time to master but it basically allows you to choose from 100’s of known exploits and deploy them to targets.

A Windows machine was targeted with one of the known payloads, the payload was delivered and root access was gained in less than w minutes. It was quiet scary on one front, made me glad I’m not a Windows user, thats for sure.

Other exploits demonstrated included loading a generic PDF with and exploit, delivering it and watching as the PDF cause the target to machine to connect back to the host.

Exposing yourself?

The obvious lessons learned were; only expose ports you need, and only expose them to locations that need to get to them. Make sure you don’t give away too much info; for instance when your webserver errors, or throws a 500, 404 etc make sure the server description doesn’t give away whats running on it. This can make it very easy for an attacker to identify a way in.

Reporting

Reporting was only covered very briefly, but Dradis was mentioned.

Resources

Metasploit Unleashed
Carnal Ownage
Dark Operator Blog
The Slides from the session

Example Videos

Metasploit Demo from Westin on Vimeo.

How to own a Windows XP Sp2 system using MS08-67 vulnerability and run netcat as backdoor with Meterpreter? from Cycops India on Vimeo.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Conferences, Development, SRC10, Security | Tagged , , | Leave a comment

Google chrome select and CSS

If you try and set a background image in a select element in Google chrome and you get shading over the top of the element which completely buggers up the element, I think it’s a bug. I’ve managed to get it to stop adding the shading but at the expense of losing the drop down icon. Just use the following CSS

 select{
 background: url('myimage.png');
 -webkit-appearance: none;
}
Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Uncategorized | 2 Comments

A couple of funny videos

Best Fails of 2009:

http://www.huffingtonpost.com/2010/01/07/best-fails-of-2009-video_n_414549.html

Compare the Meerkat:

http://film.comparethemeerkat.com/

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Funnies | Leave a comment

Automatically generating a sitemap in rails

I recently had the need to generate a sitemap using a cron job on a regular basis (nightly) for my ruby on rails app. I found the excellent plugin from Chrisian Hellsten at http://github.com/christianhellsten/sitemap-generator. Which did the trick very nicley. However I have since added a new model and controller in the namespace blog. This caused a problem as the plugin did not look and further than the the app/models folder for the model files. Mine was at app/models/blog/article.rb.

To cut a long story short I fixed the problem by changing the following method find_models in generator.rb:

def find_models
      models = []

      files = Dir.glob(File.join(RAILS_ROOT, 'app', 'models', '*.rb')).delete_if {|c| c =~ /observer\.rb/ } #{|c| c < ActiveRecord::Base== false}

      files.each do |file|
        # Get the class from the filename
        model = file.split('/').last[0..-4].classify.constantize
        # Skip classes that don't have any sitemap options
        next if !model.methods.include?('sitemap_options') || model.sitemap_options == nil

        models << model
      end

      puts "Sitemap WARNING!! No models found. Have you included a call to the sitemap in your ActiveRecord models?" if models.empty?

      models
    end

to...

def find_models
      models = []
      model_path = File.join(RAILS_ROOT, 'app', 'models')
      files = Find.find(model_path) do |file|
        next unless file[-3..-1] == '.rb'
        next if file =~ /observer.rb/
        file.gsub!(model_path,'')
        # Get the class from the filename
        model = file.split('/').map{|f| f.gsub('.rb','').classify unless f.empty?}.compact.join('::').constantize
        # Skip classes that don't have any sitemap options
        next if !model.methods.include?('sitemap_options') || model.sitemap_options == nil

        models << model
      end

      puts "Sitemap WARNING!! No models found. Have you included a call to the sitemap in your ActiveRecord models?" if models.empty?

      models
    end

I also added an XML stylesheet to the plugin to make the sitemap.xml look pretty, the result of this can be seen at http://www.thebatteryguys.co.uk/sitemap.xml and you can install my version of the plugin using ./script/plugin install git://github.com/danhawkins/sitemap-generator.git

The homepage for my fork is at http://github.com/danhawkins/sitemap-generator

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter
Posted in Development, Ruby / Rails | Leave a comment