Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

James Robertson http://www.r0bertson.co.uk

« Newer Snippets
Older Snippets »
Showing 1-10 of 43 total  RSS 

Adding helpful error messages to your Ruby code

This Ruby code raises an error if the XPath query fails because the attribute being queried did not exist for the given element.

  def map_pattr(node, fieldx, valuex)
    begin
    parameter = node.root.elements["parameter[@field='#{fieldx}']"]
    parameter.add_attribute('value', valuex)
    parameter
    
    rescue
      puts 'feedpopulated.rb: map_attr() the field ' + fieldx + ' was not found in params.'
      raise
    end
  end

Notice that a raise statement is used to ensure that the system error message is raised and any further code execution is halted.

Without adding a customized helpful message I would be left scratching my head trying to work out what the following system error message meant.
./feedpopulated.rb:27:in `map_pattr': undefined method `add_attribute' for nil:NilClass (NoMethodError)
     from ./feedpopulated.rb:51:in `create_record'
     from ./feedpopulated.rb:49:in `each'
     from ./feedpopulated.rb:49:in `create_record'
     from ./recordx.rb:91:in `call_create'
     from ./s3fileuploader_handler.rb:14:in `call'
     from ./s3fileuploader_handler.rb:40:in `invoke'
     from ./uploadtwitteraudio.rb:22:in `initialize'
     from /usr/lib/ruby/1.8/rexml/element.rb:890:in `each'
     from /usr/lib/ruby/1.8/rexml/xpath.rb:53:in `each'
     from /usr/lib/ruby/1.8/rexml/element.rb:890:in `each'
     from ./uploadtwitteraudio.rb:18:in `initialize'
     from ./uploadtwitteraudio.rb:72:in `new'
     from ./uploadtwitteraudio.rb:72


Reference: Programming Ruby: The Pragmatic Programmer's Guide - Exceptions, Catch, and Throw [ruby-doc.org]

Helpful XPath examples

A few XPath examples copied from XPath Syntax [w3schools.com]

Predicates
/bookstore/book[1] 	# Selects the first book element that is the child of the bookstore element. 
                        # Note: IE5 and later has implemented that [0] should be the first node, 
                        # but according to the W3C standard it should have been [1]!!
/bookstore/book[last()] 	# Selects the last book element that is the child of the bookstore element
/bookstore/book[last()-1] 	# Selects the last but one book element that is the child of the bookstore element
/bookstore/book[position()<3] 	# Selects the first two book elements that are children of the bookstore element
//title[@lang] 	# Selects all the title elements that have an attribute named lang

Selecting Unknown Nodes
/bookstore/* 	# Selects all the child nodes of the bookstore element
//* 	# Selects all elements in the document
//title[@*] 	# Selects all title elements which have any attribute

Selecting Several Paths
//book/title | //book/price  	# Selects all the title AND price elements of all book elements

Using ruby to upload multiple files to Amazon S3

This ruby code builds upon the code S3 upload client for Ruby [dzone.com] by reading the account details and file details from XML files.

#!/usr/bin/env ruby
#file : rubys3file2upload.rb

require 'rubygems'
require 'aws/s3'
require 'rexml/document'
include REXML

class S3FileUpload

  def initialize(xml_accounts_file, xml_upload_file)
    initialize_account(xml_accounts_file)
    main(xml_upload_file)
  end

  def initialize_account(accounts_file)

    file = File.new(accounts_file)
    doc = Document.new(file)

    account = doc.root.elements['records/access']
    h = Hash.new
    h[:access_key_id] = account.elements['key_id'].text.to_s
    h[:secret_access_key] = account.elements['secret'].text.to_s
    AWS::S3::Base.establish_connection!(h)

  end

  def main(xml_upload_file)
    file = File.new(xml_upload_file)
    doc = Document.new(file)
puts doc
    doc.root.elements.each('records/file') do |f|
      local_file = f.elements['local'].text.to_s
      bucket = f.elements['bucket'].text.to_s
      mime_type = f.elements['mime_type'].text.to_s
      upload(local_file, mime_type, bucket)
    end
  end

  def upload(local_file, mime_type, bucket)

    base_name = File.basename(local_file)

    puts "Uploading #{local_file} as '#{base_name}' to '#{bucket}'"

    AWS::S3::S3Object.store(
      base_name,
      File.open(local_file),
      bucket,
      :content_type => mime_type,
      :access => :public_read
    )

    puts "Uploaded!"
  end

end

if __FILE__ == $0
  s3fu = S3FileUpload.new('s3accounts.xml', 's3files2upload.xml')
end


file: s3accounts.xml
<s3accounts>
  <summary/>
  <records>
    <access id="100"><name>REPLACE_ME</name><key_id>REPLACE_ME</key_id><secret>REPLACE_ME</secret></access>
  </records>
</s3accounts>


file: s3files2upload.xml
<s3files2upload>
  <summary/>
  <records>
    <file>
      <local>autocomplete.html</local>
      <bucket>t2000</bucket>
      <mime_type>text/html</mime_type>
    </file>
    <file>
      <local>autocomplete2.html</local>
      <bucket>t2000</bucket>
      <mime_type>text/html</mime_type>
    </file>
    <file>
      <local>autocomplete3.html</local>
      <bucket>t2000</bucket>
      <mime_type>text/html</mime_type>
    </file>
  </records>
</s3files2upload>


Note: The file given the correct permission could be read from http://t2000.s3.amazonaws.com/autocomplete.html

Reference: http://amazon.rubyforge.org/

Adding style to SVG

To reference a CSS file within an SVG file refer to the following example code.

<?xml-stylesheet href="styles_austria_1.css" type="text/css"?> 

Here's what an SVG CSS file looks like.
.str1 {stroke:#0093DD;stroke-width:16;color:#0093DD}
.str2 {stroke:#0093DD;stroke-width:12}
.str3 {stroke:#0093DD;stroke-width:10}
.str4 {stroke:#0093DD;stroke-width:6}

.str0 {stroke:#DA251D;stroke-width:55;color:#DA251D}
.str6 {stroke:#BB90BB;stroke-width:44;color:#BB90BB}
.str5 {stroke:#0093DD;stroke-width:4}
.str7 {stroke:#1F1A17;stroke-width:13}

.fil0 {fill:none}
.fil2 {fill:#1F1A17}
.fil1 {fill:#C4E5FA}
.fil3 {fill:#FFFFFF}


Source: Example for using CSS-Styles [carto.net]
Reference: Styling - SVG 1.1 - 20030114 [w3.org]

Converting text to SVG

First of all the Ruby code reads the text, splits it into an array and then saves it in XML format.
require 'rexml/document'
include REXML

a = "Open source is a development method for software that harnesses the power of distributed peer 
review and transparency of process. The promise of open source is better quality, higher reliability, 
more flexibility, lower cost, and an end to predatory vendor lock-in.".split(' ') 

doc = Document.new
doc.add_element('text')
oline = Element.new('line')

char_count = 0
a.each do |word|
  
  oword = Element.new('word')
  oword.text = word.to_s
  oword.add_attribute('length',char_count)
  oline << oword 
  char_count += word.length
  
  if char_count > 50
    doc.root << oline
    oline = Element.new('line')
    char_count = 0
  end
end
doc.root << oline
puts char_count
puts doc

Here's a sample of the XML created
<text>
  <line>
    <word length='0'>Open</word><word length='4'>source</word><word length='10'>is</word>
    <word length='12'>a</word><word length='13'>development</word><word length='24'>method</word>
    <word length='30'>for</word><word length='33'>software</word><word length='41'>that</word>
    <word length='45'>harnesses</word>
  </line>
  <line>
    <word length='0'>the</word><word length='3'>power</word>
    <word length='8'>of</word><word length='10'>distributed</word><word length='21'>peer</word>
    <word length='25'>review</word><word length='31'>and</word><word length='34'>transparency</word>
    <word length='46'>of</word><word length='48'>process.</word>
  </line>
  <line>
    <word length='0'>The</word>
    <word length='3'>promise</word><word length='10'>of</word><word length='12'>open</word>
    <word length='16'>source</word><word length='22'>is</word><word length='24'>better</word>
    <word length='30'>quality,</word><word length='38'>higher</word><word length='44'>reliability,</word>
  </line>
  <line>
    <word length='0'>more</word><word length='4'>flexibility,</word><word length='16'>lower</word>
    <word length='21'>cost,</word><word length='26'>and</word><word length='29'>an</word>
    <word length='31'>end</word><word length='34'>to</word><word length='36'>predatory</word>
    <word length='45'>vendor</word>
  </line>
  <line>
    <word length='0'>lock-in.</word>
  </line>
</text>

The XML is then transformed to SVG using the following XSL file
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output encoding="UTF-8"
            method="xml"
            indent="yes"/>
            
  <xsl:template match="text">
    <svg xmlns="http://www.w3.org/2000/svg" width="100%"
                  xmlns:xlink="http://www.w3.org/1999/xlink" >
      <g id="sketch" class="sketch">
        <xsl:apply-templates select="line"/>
      </g>
    </svg>
  </xsl:template>
  
  <xsl:template match="line">
    <xsl:variable name="xfactor">12</xsl:variable>
    <xsl:variable name="yfactor">20</xsl:variable>
    <xsl:variable name="pos" select="position()"></xsl:variable>
    <xsl:apply-templates select="word">
      <xsl:with-param name="xfactor" select="$xfactor"></xsl:with-param>
      <xsl:with-param name="y" select="$pos * $yfactor + 10"></xsl:with-param>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="word">
    <xsl:param name="xfactor"/>
    <xsl:param name="y"/>
    <text xmlns="http://www.w3.org/2000/svg" font-size="12pt" x="{@length * $xfactor +10}" y="{$y}" id="t1"><xsl:value-of select="."/></text>
  </xsl:template>
</xsl:stylesheet>

The final SVG output [twitxr.com] shows 5 lines of text with each word as a separate SVG text element.

Append an XML element using the append operator

This Ruby code appends an XML node to an XML document using the append << operator.
      doc2 = Document.new(xml_svg)
      obody.text = ''
      obody << doc2.root

In this example the original obody.text contained escaped xml, which was then initialised as an XML document and appended to obody to be processed as pure XML.

Using XSLT to generate SVG

This XSL file is intended to be used as an SVG XSL template file which displays SVG content using Gorg (XSLT back-end processor).
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output encoding="UTF-8"
            method="xml"
            indent="yes"/>
            
  <xsl:template match="mainpage">
  <svg xmlns="http://www.w3.org/2000/svg" width="100%"
                xmlns:xlink="http://www.w3.org/1999/xlink" >

    <g>
    <text font-size="12pt" x="50" y="50" id="t2" stroke="olive"><xsl:value-of select="title"/></text>
    </g>

  </svg>
  </xsl:template>
</xsl:stylesheet>


Reference: 'using XSLT to generate SVG' http://snurl.com/24pwo [carto.net]

Instruct a shared whiteboard to save and refresh

The following code used with the ProjectX API informs the client web browser that the whiteboard will be refreshed in 5 seconds. It then archives the current whiteboard information, formats it, and sends a message to each web browser to refresh their view.

<project name="whiteboardqueue">
  <methods>
    <method name="create">
      <params>
        <param var="type">ecmascript</param>
        <param var="body">startRefresh(5)</param>
        <param var="sender">system</param>
      </params>
    </method>
    <method name="timer">
      <params>
        <param var="timer">5</param>
      </params>
    </method>
    <method name="archive_and_format">
      <params/>
    </method>
    <method name="create">
      <params>
        <param var="type">ecmascript</param>
        <param var="body">reloadDocument()</param>
        <param var="sender">system</param>
      </params>
    </method>
  </methods>
</project>


*update 1:14am*
The whiteboard demo [rorbuilder.info] allows the user to draw using the mouse within the web browser which renders SVG. Tested on Flock and Firefox.

*update 4:42pm 28 Mar 08*
You can also view the whiteboard message queue [rorbuilder.info].

*update 6:29pm Mar 08*
I've created a short url (http://rubyurl.com/vxHD) (to demonstrate the cleaning of the whiteboard) which redirects to this http://rorbuilder.info/api/projectx.cgi?xml_project=<project name="whiteboardqueue"><methods><method name="create"><params><param var="type">ecmascript</param><param var="body">startRefresh(5)</param><param var="sender">system</param></params></method><method name="timer"><params><param var="timer">5</param></params></method><method name="archive_and_format"><params/></method><method name="create"><params><param var="type">ecmascript</param><param var="body">reloadDocument()</param><param var="sender">system</param></params></method></methods></project>

I've

Post to both Jaiku and Twitter

This XML code is the ProjectX API to post to both Twitter and Jaiku. This is a follow-up example from Post to Jaiku using ProjectX API [dzone.com]

xml_project = <<PROJECT
<project name='micro_blog'>
  <methods>
    <method name='post2jaiku'>
      <params>
        <param var='user' val='YourJaikuUserName'/>
        <param var='msg' val='YourMessage'/>
        <param var='location' val='YourCity'/>
        <param var='apikey' val='YourApiKey'/>
      </params>
    </method>
    <method name='post2twitter'>
      <params>
        <param var='user' val='YourTwitterUserName'/>
        <param var='msg' val='YourMessage'/>
        <param var='password' val='YourPassword'/>
      </params>
    </method>    
  </methods>
</project>"
PROJECT

Post to Jaiku using ProjectX API

This Ruby code uses the ProjectX API on rorbuilder.info to send a post to Jaiku.

Prerequisites:
1) You have a Jaiku account. see http://jaiku.com/
2) You know your Jaiku API key. see http://api.jaiku.com/

#!/usr/bin/ruby
# file: projectx_client.rb

require 'net/http'
require 'rexml/document'
include REXML

class ProjectXClient
  attr :doc
  def initialize(raw_url)
    url = URI.escape(raw_url)
    xml_data = Net::HTTP.get_response(URI.parse(url)).body
    @doc = Document.new(xml_data)
  end
  
end

if __FILE__ == $0

xml_project = <<PROJECT
<project name='jaiku'>
  <methods>
    <method name='post'>
      <params>
        <param var='user' val='YourJaikuUserName'/>
        <param var='msg' val='YourMessage'/>
        <param var='location' val='YourCity'/>
        <param var='apikey' val='YourApiKey'/>
      </params>
    </method>
  </methods>
</project>"
PROJECT
  
  pxc = ProjectXClient.new("http://rorbuilder.info/api/projectx.cgi?xml_project=" + xml_project)
  doc = pxc.doc
  puts doc
    
end



You can also pass the url including xml into the address bar and it will post to Jaiku successfully.
eg.
http://rorbuilder.info/api/projectx.cgi?xml_project="<project name='jaiku'><methods><method name='post'><params><param var='user' val='jrobertson'/><param var='msg' val='testing 223'/><param var='location' val='London'/><param var='apikey' val='5ugr6ttr754y214445'/></params></method></methods></project>"

Note:
Your api key is not in any way stored by the website rorbuilder.info.
Rorbuilder.info is a 3rd party developer website which is not part of Jaiku.com.
« Newer Snippets
Older Snippets »
Showing 1-10 of 43 total  RSS