rspec on rails, LocalJumpError - no block given

Posted by matt on September 24, 2007

Quite frequently in rails I find myself saying something like:


def show
  @photo = User.find(params[:user_id]).photos.find(params[:id])
end

Pretty simple right…

But it can be the cause of headaches when trying to write rspec tests. Writing the following test:


describe PhotosController, ‘handling GET /users/1/photos/2.png’ do
  before(:each) do
    @photo = mock_model(Photo)
    @user = mock_model(User, :photos => [@photo])
    [@photo].stub!(:find).and_return(@photo)
    User.stub!(:find).and_return(@user)
  end

  def do_get
    get ’show’, :user_id => 1, :id => 2, :format => ‘png’
  end

  it “should find the specified user” do
    User.should_receive(:find).once.with(‘1′).and_return(@user)
    do_get
  end

  it “should find the found users photos” do
    @user.should_receive(:properties).once.and_return([@photo])
    do_get
  end

  it “should find the specified photo from within the found photos” do
    [@photo].should_receive(:find).once.with(‘2′).and_return(@photo)
    do_get
  end
end

Will result in the following errors:

LocalJumpError in 'PhotosControllerhandling GET /users/1/photos/2.png should find the specified user'
no block given
LocalJumpError in 'PhotosControllerhandling GET /users/1/photos/2.png should find the found users photos'
no block given
LocalJumpError in 'PhotosControllerhandling GET /users/1/photos/2.png should find the specified photo from within the found photos'
no block given

The cause of the problem is this. When rspec runs it is calling the Ruby Enumerable#find on an array of one object [@photo]. Enumerable#find expects a block. In the rails code, ActiveRecord::Base::find is being called which is really doing a scoped find for all photos belonging to the user. The solution is to stub the find method on the photos array in the before block of your rspec tests. Here is the working test:


describe PhotosController, ‘handling GET /users/1/photos/2.png’ do
  before(:each) do
    @photo = mock_model(Photo)
    @photos = [@photo]
    @photos.stub!(:find).and_return(@photo)
    @user = mock_model(User, :photos => @photos)
    User.stub!(:find).and_return(@user)
  end

  def do_get
    get ’show’, :user_id => 1, :id => 2, :format => ‘png’
  end

  it “should find the specified user” do
    User.should_receive(:find).once.with(‘1′).and_return(@user)
    do_get
  end

  it “should find the found users photos” do
    @user.should_receive(:properties).once.and_return(@photos)
    do_get
  end

  it “should find the specified photo from within the found photos” do
    @photos.should_receive(:find).once.with(‘2′).and_return(@photo)
    do_get
  end
end

best-mobile-phones.org attempt 2!

Posted by matt on August 21, 2007

I have finally gotten around to re-writing the first rails site I ever wrote. So here it is http://www.best-mobile-phones.org.uk, the new and improved best mobile phones. The original was just a simple DB, and literally everything was using page caching. I had used out of the box scaffolding to edit the db, and whenever a user submitted a review, a cache_sweeper would clear the required pages from the cache.

The new site is built almost completely using REST. All phones lists are paginated using the will_paginate plugin, although I have not implemented the AJAX version yet. All the images are stored in the DB, and cached on the server when requested. I’ve also built a sweet CMS which allows me to edit almost anything on the site once logged in. There are sweepers set up for all of the data so any caches affected by the CMS are automatically expired. Finally, I also decided it was time to learn some web2.0 CSS! So I got my GIMP out, made a “Beta” badge, and curved the edges of any box I saw! So there it is, please go take a look, find some bugs, give me some feedback, buy a phone. End advertisement!

Custom REST routes

Posted by matt on July 17, 2007

When developing rails applications using REST, all controllers have only seven actions (index, show, new, create, edit, update and destroy). Occasionally there is a need for additional custom actions. They can be added very simply in config/routes.rb. For example, in part of an application showing a list of venues, you may want to list only venues which have not closed down, and you may want to mark a venue as closed_down.

Your initial config/routes.rb setup would look something like this:

  ActionController::Routing::Routes.draw do |map|
    map.resources :venues
  end

To list all venues that are closed down you would first need to add the following action to your venue_controller.rb:

  def closed
    @venues = Venue.find(:all, :conditions => ['closed_down = ?', true])
  end

However, trying to navigate to this action will result in a routing error. To fix this, you will need to amend routes.rb:

  ActionController::Routing::Routes.draw do |map|
    map.resources :venues, :collection => {:closed => :get}
  end

The collection hash is used to specify actions which reference collections of objects instead of actions which reference one object. In this case the closed action is referencing a collection of venues. Inside the hash :closed is mapped to a GET request. This will also automatically create a named route: closed_venues_path. Cool!

So that’s working. Now to be able to mark a venue as closed_down.
In your venues_controller.rb you would add the following action:

def mark_closed_down
  @venue = Venue.find(params[:id])
  @venue.update_attribute :closed_down, true
  redirect_to closed_venues_path
end

However, trying to navigate to this action will currently throw an error, as following the current RESTful setup the application will try to render the show action, which will try to find a venue with id => ‘mark_closed_down’.

To fix this you need to make the following change to your routes.rb file:

  ActionController::Routing::Routes.draw do |map|
    map.resources :venues, :collection => {:closed => :get}, :member => { :mark_closed_down => :put }
  end

The member hash is used to specify actions that reference one object in particular. In this case mark_closed_down is referencing one venue. Inside the hash :mark_closed_down is mapped to a PUT request. This also gives you a named route: mark_closed_down_venue_path(venue). Thats it!

You can add as many custom routes as you like to each controller, but you should do so with caution. If you find yourself needing lots of them it probably means that you have missed a model, or that you should create another controller. Each controller maps one to one with a resource, but not necessarily with a model. In this case, for example, it would be possible to map another resource in routes.rb maybe called closed_down_venues:

map.resources :closed_down_venues

Then create a closed_down_venues controller with:

script/generate controller closed_down_venues

The index action would then be the list of closed venues, and the update action would be the mark_closed_down action.

I hope this is all clear. Please add a comment if not, and I will do my best to clarify…

acts_as_emailable

Posted by matt on June 05, 2007

Quite often when building a site, I find that it would be nice if users could email each other within the site. In my previous post I explained how to set up the models and relationships for this. Today I’ve gone one step further and packaged them up into a plugin: acts_as_emailable. Here is how to use it:

Setup
=====
First up you need to install the plugin. This can be done like so:

script/plugin install svn://matt-beedle.com:3396/acts_as_emailable

Then generate the model and migration for the emails table.

script/generate acts_as_emailable_model Email
rake db:migrate

Now you are ready to go. Just add the following line of code to your User model:

class User < ActiveRecord::Base
  acts_as_emailable
  #
  # The rest of you code
end

Usage
=====
After the plugin is installed the following methods become available to your User class.

These methods are the associations. They return what you would expect:

user.users_whom_i_have_emailed
user.users_who_have_emailed_me

At the moment there is only bare-bones functionality, but if any interest is shown or I feel the need, I will build in some more useful methods and make it more complete…

UPDATE
I am really pleased with all the interest and feedback I have received, especially from egze who basically did all the work for these changes. I have now added in three new functions with two aliases as I couldn’t decide on the which I preferred:
These two are really the same, they both return unread mail, although you need to make sure you update the ‘read_at’ field in the emails table when an email is read by the receiver.

user.unread_mail
or
user.new_mail

These two return all read emails, although I’m not sure if there will be much use for it.

user.read_mail
or
user.old_mail

Finally this returns all users who have emailed or been emailed by the user.

user.all_mail

I have a couple more ideas for new functions but suggestions are welcome. I was also intending to write some example code but haven’t had the chance. I’ll try to do that this week.

UPDATE: EXAMPLE CODE

In a REST based application the code may look something like this to send an email. The current_user that is referred to in the create method of the emails controller can be whatever way you get the current user. In my case I usually use Rick Olson’s Restful Authentication plugin which does this for me.
app/views/emails/new.rhtml

<% form_for :email, @email, :url => emails_path(:user_id => params[:user_id]) do |f| %>
<%= render :partial => ‘form’, :locals => {:f => f} %>
<%= submit_tag 'Send' %>
<% end %>

app/views/emails/_form.rhtml

<fieldset>
    <legend>Email</legend>
    <%= f.hidden_field :receiver_id %>
    <div>
        <label for="subject">Subject</label><br/>
        <%= f.text_field :subject %>
    </div>
    <div>
        <label for="body">Message</label><br/>
        <%= f.text_area :body %>
    </div>
</fieldset>

emails_controller.rb

def index
  @emails = User.find(params[:user_id]).all_mail
end

def new
  @email = Email.new
end

def create
  current_user.send_mail(User.find(params[:user_id]), Email.new(params[:email]))
  respond_to do |format|
    format.html do
      flash[:notice] = 'Email Sent'
      redirect_to emails_path
      false;
    end
  end
rescue ActiveRecord::RecordInvalid
  render :action => 'new'
end

How to model an internal emailing system using self-referential has_many :through associations

Posted by matt on June 02, 2007

I am currently working on a flat sharing site. One of the requirements is that users should be able to email each other within the site, a sort of internal emailing system. When one user emails another user that user has an email sent to their actual email address saying that they have an email waiting for them on the site. The intention being to keep them locked in to the site for as long as possible, and keep those adsense clicks coming in, and to provide a useful service of course! In order to do this a user model needs to be able to get all users who have emailed them and also carry through associated email details.

Anyway, here is the migration and model code to do this:


class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.column 'username', :string
      t.column 'forename', :string
      t.column 'surname', :string
      t.column 'email', :string
    end
  end

  def self.down
    drop_table :users
  end
end

class CreateEmails < ActiveRecord::Migration
  def self.up
    create_table :emails do |t|
      t.column 'sender_id', :integer, :null => false
      t.column ‘receiver_id’, :integer, :null => false
      t.column ’subject’, :string
      t.column ‘body’, :text
      t.column ‘created_at’, :datetime
    end
    add_index(’emails’, ’sender_id’)
    add_index(’emails’, ‘receiver_id’)
  end

  def self.down
    drop_table :emails
  end
end

The important thing to notice in the User model below is that the “users_who_emailed_me” goes through “emails_as_receiver” with :source => :sender and “users_whom_i_have_emailed” goes through “emails_as_sender” with :source => :receiver. It took me a while to figure that out.


class User < ActiveRecord::Base
  has_many :emails_as_sender,
    :foreign_key => ’sender_id’,
    :class_name => ‘Email’
  has_many :emails_as_receiver,
    :foreign_key => ‘receiver_id’,
    :class_name => ‘Email’
  has_many :users_who_emailed_me,
    :through => :emails_as_receiver,
    :source => :sender
  has_many :users_whom_i_have_emailed,
    :through => :emails_as_sender,
    :source => :receiver
end

class Email < ActiveRecord::Base
  belongs_to :sender,
    :foreign_key => ’sender_id’,
    :class_name => ‘User’
  belongs_to :receiver,
    :foreign_key => ‘receiver_id’,
    :class_name => ‘User’
end

I adapted this code from an excellent article on the excellent blog of Josh Susser which you can find here. If fact this is pretty much the same. However, after reading his post I did not notice the way a couple of the joins worked, which I have tried to point out here using possibly a more relevant example.

UPDATE:
I have now packaged all of this code up into a plugin. For install instructions read this post.

Refactor your controller code by using postbacks

Posted by matt on April 03, 2007

It is very easy to end up with an action for every single request. You may find you generate a controller like this for example:

./script/generate controller User create_form, create, edit_form, edit

It is not necessary to have 4 actions here. Instead this can all be handled by the same action:

def update
  @user = User.find_by_id(params[:id]) || User.new
  if request.post?
    @user.attributes = params[:user]
    if @user.save
      redirect_to :action => 'index'
      return
    end
  end
end

On first calling the action there is no data, and the template with your form is displayed. Once the form is submitted to the same action, the user object is saved and the controller redirects to the home page (or the page of your choice).

Using ActiveRecord to store session information in Ruby on Rails

Posted by matt on April 01, 2007

Rails default setting is to store sessions on the file system. This is fine during development, but this is not very scalable once an application goes into production. Often the application will be deployed to a number of servers. One good solution to is to use ActiveRecord to store the session information in the database. Fortunately this is very easy to do!

First of, open the config/environments.rb file and uncomment the following line:


config.action_controller.session_store = :active_record_store

Now we create the sessions table. There is already a rake task for doing this:


rake db:sessions:create
rake db:migrate

Now restart your server and voila! Rails does not automatically manage sessions so it is worth noting that you will need to deal with this. If you do not you could end up with a sessions table with millions of rows. This will slow your application down considerably. I will post more information soon on sweepers and dealing with session expiry.

Creating secure login code in Ruby on Rails

Posted by matt on March 30, 2007

Many web sites require secure user authentication, but a shocking number of them implement it very badly. At the time of posting one of the best ways of dealing with this problem not to store the password in the database, but instead to save a “salt” and a “hash”. The salt is a set of 6 random characters which when combined with the users password and encoded, is equal to the hash. Before going any further, you should be aware that there are plugins for rails which deal with salted logins (http://wiki.rubyonrails.org/rails/pages/SaltedHashLoginGenerator), but I believe it is best to be able to write the code yourself, or at least to have a basic understanding.

user migration

  t.column :username, :string
  t.column :password_salt, :string
  t.column :password_hash, :string

app/models/user.rb:

require 'digest/sha2'
class User < ActiveRecord::Base
  attr_accessor :password

  def password=(pass)
    salt = [Array.new(6){rand(256).chr}.join].pack("m").chomp
    self.password_salt, self.password_hash = salt, Digest::SHA256.hexdigest(pass + salt)
  end

  def self.authenticate(username, password)
    user = User.find(:first, :conditions => [”username = ?”, username])
    if user.blank? || Digest::SHA256.hexdigest(password + user.password_salt) != user.password_hash
      raise “Username or password invalid”
    end
    user
  end
end

application_controller.rb

  def check_authentication
    if session[:user].blank?
      session[:intended_controller] = controller_name
      session[:intended_action] = action_name
      redirect_to :controller => 'user', :action => 'login'
    end
  end

app/controllers/user_controller.rb:

def login
    if request.post?
      begin
        session[:user] = User.authenticate(params[:username],params[:password]).id
        redirect_to :controller => session[:intended_controller], :action => session[:intended_action]
      rescue
        flash[:notice] = "Username or password invalid"
      end
    end
  end

  def logout
    session[:user] = nil
    redirect_to :controller => :user, :action => :index
  end

def register
    if request.post?
        @user = User.new(params[:user])
        if @user.save
          redirect_to :action => :account_creation_success, :id => @user
        end
      end
    end

app/views/user/login.rhtml:


<%= flash[:notice] -%>

<% form_tag :controller => :user, :action => :login do %>
<fieldset>
<label for=”user_username”>Username</label> <%= text_field 'user', 'username' -%>
<label for=”user_password”>Password</label> <%= password_field 'user', 'password' -%>
</fieldset> <%= submit_tag 'Login' -%> <% end %>

app/views/user/register.rhtml:

<% form_tag :controller => :user, :action => :register do %>
<fieldset>
<label for=”username”>Username>/label> <%= text_field_tag 'user', nil, 'username' -%>
<label for=”password”>Password</label> <%= password_field_tag 'user', nil, 'password' -%>
</fieldset> <%= submit_tag 'Register' -%> <% end %>

Now use a before_filter on any controllers where you need to login.

in_place_form_field - editing empty fields

Posted by matt on March 23, 2007

Ruby on Rails AJAX helper in_place_form_field is great. However, it does not allow you to edit fields that have no data, which can be a real pain. There is a simple solution! Create the following extensions.rb file in RAILS_ROOT/lib/.

class Extensions
  ActionView::Helpers::JavaScriptMacrosHelper.class_eval do
    def in_place_editor_field(object, method, tag_options = {}, in_place_editor_options = {})
      tag = ::ActionView::Helpers::InstanceTag.new(object, method, self)
      tag.nil_content_replacement = in_place_editor_options[:nil_content_replacement] || 'Unknown'
      tag_options = {:tag => "span", :id => "#{object}_#{method}_#{tag.object.id}_in_place_editor", :class => "in_place_editor_field"}.merge!(tag_options)
      in_place_editor_options[:url] = in_place_editor_options[:url] || url_for({ :action => "set_#{object}_#{method}", :id => tag.object.id })
      tag.to_content_tag(tag_options.delete(:tag), tag_options) +
      in_place_editor(tag_options[:id], in_place_editor_options)
    end
  end

  ActionView::Helpers::InstanceTag.class_eval do
    attr_writer :nil_content_replacement

    def value(object)
        unless object.nil?
        v = object.send(@method_name)
        if @nil_content_replacement.nil?
          return v
        else
          (v.nil? || v.to_s.strip=='') ? @nil_content_replacement : v
        end
      end
    end
  end
end

Then in RAILS_ROOT/config/environment.rb at the bottom add the following line:
require ‘extensions’

Generating an EAN-13 barcode using Ruby on Rails and RMagick

Posted by matt on December 19, 2006

A fair while ago now I had to create an administration system for a client which needed a barcode printed out to stick on various items. These barcodes were then to be read by a barcode reader at a later date to check their progress in the system. There doesn’t appear to be much information on the internet on how to do this, so I have decided to publish my barcode creating code. There are many different types of barcode. I chose to generate one of the most popular formats - EAN-13.

The demonstration

There is a bare bones demonstration here: Barcode demonstration

Create the form

<div style="width: 500px;">
<%= start_form_tag( :action => "barcode" ) %>
<label>Code <small>(12 or 13 digits)</small></label>
<%= text_field( "e_a_n_bar_code", "code", "size" => 15 ) %>
<label>height <small>(20-50)</small></label>
<%= text_field( "e_a_n_bar_code", "size", "size" => 5 ) %>
<%= submit_tag( "go" ) %>
<%= end_form_tag %></div>

Create the controller

class BarcodeDemoController < ApplicationController
        def form
        end
        def barcode
            bar = EanBarCode.new
            @image = bar.getImage( params[ :e_a_n_bar_code ][ "code" ], params[ :e_a_n_bar_code ][ "size" ].to_i, 'png' )
        end
end

Create the model

class EanBarCode
  SIZES = [
      [ "20", "20" ],
      [ "30", "30" ],
      [ "40", "40" ],
      [ "50", "50" ]
    ].freeze
  attr_reader :groupC, :family, :ean13, :courB08_pil, :courB08_pbm
  attr_writer :groupC, :family, :ean13
   def initialize
      a = { 0 => "0001101", 1 => "0011001", 2 => "0010011", 3 => "0111101", 4 => "0100011",
            5 => "0110001", 6 => "0101111", 7 => "0111011", 8 => "0110111", 9 => "0001011"}
      b = { 0 => "0100111", 1 => "0110011", 2 => "0011011", 3 => "0100001", 4 => "0011101",
            5 => "0111001", 6 => "0000101", 7 => "0010001", 8 => "0001001", 9 => "0010111"}
      c = { 0 => "1110010", 1 => "1100110", 2 => "1101100", 3 => "1000010", 4 => "1011100",
            5 => "1001110", 6 => "1010000", 7 => "1000100", 8 => "1001000", 9 => "1110100"}
      self.groupC = c
      self.family = {0 => [a,a,a,a,a,a], 1 => [a,a,b,a,b,b], 2 => [a,a,b,b,a,b], 3 => [a,a,b,b,b,a], 4 => [a,b,a,a,b,b],
                     5 => [a,b,b,a,a,b], 6 => [a,b,b,b,a,a], 7 => [a,b,a,b,a,b], 8 => [a,b,a,b,b,a], 9 => [a,b,b,a,b,a]}
    end
   def makeCode( code )
      self.ean13 = code.split(//)
      # If the code already has a checksum
      if self.ean13.length == 13
        # Verify checksum
        verifyChecksum( self.ean13 )
      end
      # If the code does not have a checksum
      if self.ean13.length == 12
        # Add checksum value
        self.ean13 << computeChecksum( self.ean13 )
      end
      left = self.family[ self.ean13[ 0 ].to_i ]
      # Add start separator
      strCode = 'L0L'
      for i in 0..5
        strCode += left[ i ][ self.ean13[ i + 1 ].to_i ]
      end
      # Add the middle separator
      strCode += '0L0L0'
      # Compute the right codage class
      for i in 7..13
        strCode += self.groupC[ self.ean13[ i ].to_i ]
      end
      # Add stop separator
      strCode += 'L0L'
      return strCode
    end
   def computeChecksum( arg )
      # UPCA/EAN13
      weight=[1,3]*6
      magic=10
      sum = 0
      for i in 0..11         # checksum based on first 12 digits.
         sum = sum + arg[i].to_i * weight[i]
      end
      z = ( magic - (sum % magic) ) % magic
      if z < 0 or z >= magic
         return None
      end
      return z
    end
   def verifyChecksum( bits )
      computedChecksum = self.computeChecksum(bits[12])
      codeBarChecksum = bits[12]
   end
    def getImage( value, height = 50, extension = ‘png’ )
      # courbB08.pil PIL Font file uuencoded
      courB08_pil =”"”eJztl91rFkcUxp+Zt7vGFYzVtiJKICgYlLRWkaBBVGgDraFGCH5gsQp+QMBqabAVRYJYAlakCkohCpYgxaLkIu1NvLBeSAStglpqL6xQAsVe2AuL5u2buH3mzGaYPf9AKWTl8d3nl7MzZ2bnazvea9+97+PurFWut5e0Zu+s7VybYfKavP7LK3X/5TlM4Q3/OWbyf1ARD/6mgb2SjwtPhbpnq0iKZ6ahrmCjwqbxdgamRnHOA69jimN5zvIS8cDcUEeVdYzRAw1FHcJYXgPvG4s6Jlgj7xeEequS3wLeNvGvnrEOtq+Jt82szT+b86+WHlgS2jHGuHF6YHnog1zaupxqCcy3t4X3rVG9iXhgjW+bsFQ80BaxRDywTrF1VId6toPaqOI2UlsV20ptV2w7tUuxXVSXYl3UvoIZ9kFFPPBJ6D/HLD3QXbwjyDjI6YHPiz5FXiN7SQ8cDu/N9/1h3veEOP/Oe6gvQnmuvYYe+NL3qYyNVDxw2seF8XKa+jrKJREPnFdx56l+xfqpS4pdogZUeQPU91FcKh64GveBeOCaKu8adUM9e4O6reJuU/cUu0c9VM8+pB6r/B5TI+rZEerPUpyhB/6K5lsqHniuyntO1VR5Nb5CU86FHqZOsTqqXrF66o2ojlQ8zDwVN4+aX86FHqYpXg9YLeevWRzPc7LFZG+V1wN6mKXxvMzH6GFaJua5zGNLD7MqmtNcc+hh1oT1oCb5cf6aNj92mbPMGXqY9jCPasLaqQ1hjMv8pYfZpOI2UR9GcYl4mB1RnMtvB9me8N583B5qb3mNoIf5NGJc1+hhPvPrrjybioc5op49Qh0Ldfj8jlHHQ3s9O059Fc3zRDzMmVKcpYfpU+3oI/umxJyH+TYqLxUPc0X13xVqMMovFQ8zpPIbon6MWCoeZljVMUz9VIqz9DAP1Dt6QP0a9gpZ7+lhHhXjysreaOhhfiv1vaGH+T2Mv5rbU+hh/uAaOnlNXv+Hy4/7mtv3OW5hnpTODIYe5mm0xqbiYf4OcbLv08NU1ZyuuqKLOEvm6sjhJkd8TjRustgkrO3uvFGjh60r1uyiPHrY6eH84tb7l/SwM8vrAT3snHgNY9wcsoby+Y8edn5UxxTxsIuitrlcFpG9GcVx/6CHXRrKk72MHrYl3stYB/ceu7I4X02wlWSrCmaF1ehhV7NrovWKHrattI4betj20Fc8r7E87kf2g+gcy32BHnZDfKZmHPco2xnl4vqlk2yz6r/N1EfRPpiKh90d7VGpeNi9inGPst2lNdbSwx4McS8k7iDVE/Ytz3qoXsV6qZOKnaTOBDYqjPuRPRfOkz7uHNUf4uQMQg/7XekMYulhB6JnE/GwP0T1JuJhryrGM6G9HuWSiIcdDnPmhTs70sPeCuPes1vUXcXuUvcDGxV2n/olOisn4mEfhfOVby/3KDsSlZeIh32iGOe0faoY57R9ptgzajTKJREPOx7aJnOfHhUbxov0Mz0qU8v50aMyo/wu6VGZrdhsqqH8fnllHEEz4zj6DNMxK+4X+gyv8cszyoU+4zfmjNAO9zuXrNGXF1gj2ULFFpI1K9ZMtiww//22jGwFXg39535XkK0O+cl5gz7Du6iP5wd9hvfDs9LP9BnWR/U6tp6sU7FOsi1RLo5tIdsWled+t5HtVO3YSdalWBfZftW2/WQHVH4HyA6F9+GfPUR2VOV3lKxXsV6yE4qdIDul2Cmys6ptZ8n6Qi7+m7OP7ELoU/8tdIHsoo8L+V0ku6xyvkw2qNgg2VBgvg+GyK6XyrP0GW5ydE3EuXd5k+xOeOdVibtD9jNm/Qv15O4i”"”
      # courbB08.pbm font file uuencoded
      courB08_pbm =”"”eJxNkntM01cUx8+P2/1apUAZEpECq4KRjKhF0E55FYEp4yG6mglz2Q8Q1BhERhhls/zKI+CID4wbIAPKpk4GAzqZPKKMX2GIUwGJG+ImtKwKjIzXcGuBtncV0Hn+uLnn5Nzv55xv7mdRkbusVjquBACr0N3B+wCQi/m+ijAf4LGl/wgAiwkNDpRIyyABSjGkBQ/fa3c1bfLs4U8ulDcYUs/502rTpIlO9pycKp/Buql6f3rmZ1NqvpO2SZXf0duY3j0563zjoZpW8AvHRmVeZ/Co36mFR8bERzlsxOMJ+oJshsS57rlfzFzmnZFEFnIEZjTGizgLsLzjl4QtrNprBRu10e+u9GgePHjG63bPDw/H87uix0Vtsvkqg9qOlUimPLiOM4z69YfqIu5Pa2Sr/io6n9Xmf9e+57W1Iapo4lLQBdLSWc/z3KOSlgznDXTW/Flh21kXIeUIX8FZVL9dwP4NBH5jglYxkBNFmWgMcfsAxM/9gEL5TTwYpnfElR8qQ+WiCgeTHOAfb2bW/cQC/FozFOOQzAebtjRvQLI7HBtXvaZe25a3Q/1vZpPa+kd1XXKuflr5Cm48YUsUcjMXjsm/sf+22s6zQAbGZ8mEXMzSE4y9AHhRpltwB1N9ynz5H2MOi0MEi4E5O1ov9ogrFU5cMWAcdgQb3xHFtFK+0pkhVnYWxltx92j69p6jJ9OnHr+Cq5×5X6Mz70JcX2tEG5LIShM4EHIGoLIRsHzcvEuGwMYA4DZPn7gPMA1QIgltnt82cTu7j5n76mmz3TU5Bh3PFRTHku52aBgaTnJD7m1c0a3hNjbWWjBtMsP/OFac/LYANAAWepdYodB58NBFIuOjNSQ4cgXplqP2RyOe8fd999T8weqBRwLwNFdQobHgA1/YTV8PH+TwV59vBo7Y1J4rmHFv3T9e8rmmXdGSuPpSbBnhYJ7V8ICz6AfGcdTpRkpCUU8WcOT8wb+dSHIb6QZapx0MY2DO4i7jYV2AUNkkErpQFHVYmFRmYD7OJhDyQSiow4IkrS3TbpQqFA9slE4jnj6peXMTC+N8buJ20Uv5eOothuGIiluyCDtff3miBzJHjncOIC3bPT8FLabRPd0TCWy346Mmn9Rz23WyNMJcsnqhQani3CMFOZuYU7c20zTNVqNbGPNxALWnybeLEcTvXWpc10leI5ae/CI9qBqI686cnO6P6F33e2vAp0nz9+hnbNeueh/261UJK5aVeSf73ZSXA7dOBXvkXODEb9hVww4KtPNAbPvaZbi0q9kICCl+CiBJSzLva8TlntYlC4UHvCRTlaXOy13VAbN0eae2v3hNesWXLsWPkjfOPq7e6zd1fOfc1TckDaylrvleinnT8Ui87ScLMVhhEx7SUJ8U2zKrRR2Z1dEqZlkr7kDTuhFjpkvse9ZXN0R9H+DlYA4TXVm6/kXDQMyTeGnJFXlLlSgva5iLUEcbiyDzNqf4Wr9kKYVUIcY40DrnsW4E4zW9QxnHVYx+bo64mIskDWjZgCrqeVQFrS7Sh/uFLftIidKWbgj6Oq652d4c3v88Dw2JDK7bSWX/ByuaLZI=”"”
      decodeFontFile( courB08_pil, “courB08.pil” )
      bits = makeCode( value )
      bits = bits.split( // )
      code = “”
      for digit in self.ean13
        code += “%d”%digit
      end
      require ‘RMagick’
      position = 8
      # Create a new image
      im = Magick::ImageList.new
      im.new_image( bits.length + position, height )
      # Create a drawer
      draw = Magick::Draw.new
      # Draw the bar codes
      for bit in 0..bits.length
        # Draw normal bar
        if bits[ bit ] == ‘1′
          draw.fill( ‘black’ )
          draw.rectangle( bit + position, 0, bit + position, height - 10 )
        end
        # Draw long bar
        if bits[ bit ] == ‘L’
          draw.fill( ‘black’ )
          draw.rectangle( bit + position, 0, bit + position, height - 3 )
        end
      end
      draw.draw( im )
      im.write( “barcode.” + extension )
      return bits
    end
  def decodeFontFile(data, file)
#     from zlib import decompress
#     from base64 import decodestring
#     from os.path import exists
    data = Base64.decode64( data )
     # If the font file is missing
      if not File.exists?( file )
        # Write font file
        File.open( file, “w+” ).write( data )
      end
  end
  def testWithChecksum()
     bar = EanBarCode()
     assert(bar.makeCode(’0000000000000′)== ‘L0L0001101000110100011010001101000110100011010L0L0111001011100101110010111001011100101110010L0L’ )
     assert(bar.makeCode(’1111111111116′)== ‘L0L0011001001100101100110011001011001101100110L0L0110011011001101100110110011011001101010000L0L’ )
     assert(bar.makeCode(’2222222222222′)== ‘L0L0010011001001100110110011011001001100110110L0L0110110011011001101100110110011011001101100L0L’ )
     assert(bar.makeCode(’3333333333338′)== ‘L0L0111101011110101000010100001010000101111010L0L0100001010000101000010100001010000101001000L0L’ )
     assert(bar.makeCode(’4444444444444′)== ‘L0L0100011001110101000110100011001110100111010L0L0101110010111001011100101110010111001011100L0L’ )
     assert(bar.makeCode(’5555555555550′)== ‘L0L0110001011100101110010110001011000101110010L0L0100111010011101001110100111010011101110010L0L’ )
     assert(bar.makeCode(’6666666666666′)== ‘L0L0101111000010100001010000101010111101011110L0L0101000010100001010000101000010100001010000L0L’ )
     assert(bar.makeCode(’7777777777772′)== ‘L0L0111011001000101110110010001011101100100010L0L0100010010001001000100100010010001001101100L0L’ )
     assert(bar.makeCode(’8888888888888′)== ‘L0L0110111000100101101110001001000100101101110L0L0100100010010001001000100100010010001001000L0L’ )
     assert(bar.makeCode(’9999999999994′)== ‘L0L0001011001011100101110001011001011100010110L0L0111010011101001110100111010011101001011100L0L’ )
  end
  def testWithoutChecksum()
     bar = EanBarCode()
     assert(bar.makeCode(’000000000000′)== ‘L0L0001101000110100011010001101000110100011010L0L0111001011100101110010111001011100101110010L0L’ )
     assert(bar.makeCode(’111111111111′)== ‘L0L0011001001100101100110011001011001101100110L0L0110011011001101100110110011011001101010000L0L’ )
     assert(bar.makeCode(’222222222222′)== ‘L0L0010011001001100110110011011001001100110110L0L0110110011011001101100110110011011001101100L0L’ )
     assert(bar.makeCode(’333333333333′)== ‘L0L0111101011110101000010100001010000101111010L0L0100001010000101000010100001010000101001000L0L’ )
     assert(bar.makeCode(’444444444444′)== ‘L0L0100011001110101000110100011001110100111010L0L0101110010111001011100101110010111001011100L0L’ )
     assert(bar.makeCode(’555555555555′)== ‘L0L0110001011100101110010110001011000101110010L0L0100111010011101001110100111010011101110010L0L’ )
     assert(bar.makeCode(’666666666666′)== ‘L0L0101111000010100001010000101010111101011110L0L0101000010100001010000101000010100001010000L0L’ )
     assert(bar.makeCode(’777777777777′)== ‘L0L0111011001000101110110010001011101100100010L0L0100010010001001000100100010010001001101100L0L’ )
     assert(bar.makeCode(’888888888888′)== ‘L0L0110111000100101101110001001000100101101110L0L0100100010010001001000100100010010001001000L0L’ )
     assert(bar.makeCode(’999999999999′)== ‘L0L0001011001011100101110001011001011100010110L0L0111010011101001110100111010011101001011100L0L’ )
  end
end

barcode.rhtml code

<%= image_tag( "/barcode.png" ) %>