Platinum Partner

UUID, GUID Generation From Within Ruby

An UUID (Universally Unique Identification), also known as GUID, is often used in software to uniquely identify information. Originally designed for distributed systems, UUIDs have quickly found their way to wherever non-conflicting identifiers identifiers are needed.
Following snippet implements a simple cross-platform UUID generation code based on available web-services and and os (win32) specific version.

Please follow the discussion at http://cheind.blogspot.com/2008/12/uuids-for-masses-in-ruby.html for advanced examples and details. In order to run the code you'll need some small extensions to ruby core classes. Please find them at http://cheind.blogspot.com/2008/12/git-repository-for-blog-code.html


#
# Project:: Ruby-Snippets
# 
# Author:: Christoph Heindl  (mailto:christoph.heindl@gmail.com)
# Homepage:: http://cheind.blogspot.com
#
# == Overview
# 
# Implements generation of UUIDs based on
# - A web-service UUID.from_url
# - Platform dependant API's UUID.from_os
#
# Currently only windows platforms are supported 

require 'net/http'
require 'uri/http'

# Include extensions, http://cheind.blogspot.com/2008/12/git-repository-for-blog-code.html
require 'ext/reverse_merge.rb'
require 'ext/join.rb'
require 'ext/breakup.rb'

# Provides generation of universal unique identifiers (UUID) or more
# commonly known as GUIDs. 
class UUID
  
  # Generates an UUID string by using
  # the web-services provided by http://www.fileformat.info
  # at http://www.fileformat.info/tool/guid.htm
  #
  # Options
  # - :format should always be :text
  # - :uppercase sets all letters to uppercase if set
  # - :hyphen uses '-' between groups if set
  # - :bracket wrap UUID in courly brackets if set
  # - :count number of UUIDs to receiver.
  #
  #  UUID.from_url # => "{F4C77E3A-F1C3-45BD-B740-7DD61B889AD9}"
  #
  #  UUID.from_url(:count => 2)
  #  # => ["{44351F05-8CCC-4408-9FE0-CE41864F03CE}", 
  #        "{3730EA6C-986B-4A4A-A942-ED4C1192D713}]
  #
  def UUID.from_url(options={})
    options = UUID.default_options(options)
    # Replace all instances of TrueClass to 'Y' for web-service
    options.each { |k,v| options[k] = 'Y' if v.instance_of?(TrueClass) }
    # Build URI
    uri = URI::HTTP.build(
      :host => 'www.fileformat.info',
      :path => '/tool/guid.htm',
      :query => options.join('&', '=')
    )
    # Query
    uuids = Net::HTTP.get(uri)
    # Split lines if multiple uuids and
    uuids.split($/).breakup
  end
  
  # Following block provides platform dependant UUID generation
  if RUBY_PLATFORM =~ /mswin/
    # Windows platform...
    require 'Win32API'
    
    @@api = Win32API.new('rpcrt4', 'UuidCreate', 'P', 'L')
    
    # Generates an UUID string using Win32API.
    #
    # This is based on code from Brad Wilson posted in 2005 at
    # http://www.agileprogrammer.com/dotnetguy/archive/2005/10/27/8991.aspx
    #
    # Options
    # - :uppercase sets all letters to uppercase if set
    # - :hyphen uses '-' between groups if set
    # - :bracket wrap UUID in courly brackets if set
    # - :count number of UUIDs to receiver.
    #
    #  UUID.from_os # => "{F4C77E3A-F1C3-45BD-B740-7DD61B889AD9}"
    #
    #  UUID.from_os(:count => 2)
    #  # => ["{44351F05-8CCC-4408-9FE0-CE41864F03CE}", 
    #        "{3730EA6C-986B-4A4A-A942-ED4C1192D713}]
    #
    def UUID.from_os(options={})
      options = UUID.default_options(options)
      # Setup format string based on options
      format = options[:hyphen] ? '{' : ''
      format += options[:bracket] ? 
        '%04X%04X-%04X-%04X-%04X-%04X%04X%04X' :
        '%04X%04X%04X%04X%04X%04X%04X%04X'
      format += options[:hyphen] ? '}' : ''
      # Invoke API
      uuids = []
      options[:count].times do 
        buffer = ' ' * 16
        @@api.call(buffer)
        a, b, c, d, e, f, g, h = buffer.unpack('SSSSSSSS')
        uuid = sprintf(format, a, b, c, d, e, f, g, h)
        uuid.upcase! if options[:uppercase]
        uuids << uuid
      end
      uuids.breakup
    end
  end
  
  private
  
  # Plugin default options if not already specified in options hash
  def UUID.default_options(options)
    raise "Generating zero UUIDs makes really no sense..." if options[:count] == 0
    options.reverse_merge(
      :format => :text,
      :uppercase => true,
      :hyphen => true,
      :bracket => true,
      :count => 1
    )
  end
end
{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}