DZone 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
  • submit to reddit
        I wanted to store and display an array of the last 10 visited pages in a session. With the help of some folks in #rubyonrails (particularly aqua) this is what i've come up with:


class ApplicationController < ActionController::Base
	before_filter :add_to_history
	before_filter :page_title
	
	def add_to_history
	  session[:history] ||= []
	  session[:history].unshift ({"url" => @request.request_uri, "name" => page_title })
	  session[:history].pop while session[:history].length > 11
	end


# This bit came from Peter Cooper's snippets source and was moved into the application controller:

	def page_title
		case self.controller_name
			when 'tag' 
				title = "Tags » " + @params[:tags].join(" > ")
			when 'user'
				title = "Users » #{@params[:user]}"	 
			when 'features'
					case self.action_name
						when 'show' then title = "Feature » #{Feature.find(@params[:id]).title}"
						else title = APP_CONFIG["default_title"]
					end
			else 
				title = APP_CONFIG["default_title"] + self.controller_name + ":" + self.action_name
		end
	end
	helper_method :page_title

...
end

In your partial you might do something like this:


<h4>User History</h4>
<% for cur in session[:history][0..9] -%>
  <p><a href="<%= cur["url"] %>"><%= cur["name"] %></a></p>
<% end -%>


Feedback and comments would be appreciated    
        Except that I can't figure out how to do it in routes.  This is what I found.

In *config/routes/rb*, as the last route add:
 map.connect '*path', :controller => 'application', :action => 'handle_unrecog'

In *app/controllers/application.rb*, put this:
 def handle_unrecog
  #do something here, the path info is in the @params value
 end

One of my uses for this is for a del.icio.us type user viewing.  IE: _http://del.icio.us/[user]_ but having it only valid for users.

I'd do something like this:
 def handle_unrec
  uname = @params['path'][0] #first part of the path
  user = User.find_by_login( uname )
  if user
   return render :controller => "user", :action => "show", :id => user
  else
   return render :controller => "user", :action => "notfound"
  end
 end

Yay!    
        Stripping html tags, with an optional array of tags to be preserved.

	def strip_html(str, allow = ['a','img','p','br','i','b','u','ul','li'])
		str = str.strip || ''
		allow_arr = allow.join('|') << '|\/'
		str.gsub(/<(\/|\s)*[^(#{allow_arr})][^>]*>/,'')
	end
    
        The new Text() control allows rich text which can be
used for syntax coloring
(screenshot)
http://photos22.flickr.com/30187174_8598b800ec_o.jpg
from appuifw import *
from pyfontify import fontify
import os, e32

src = ur"""
__version__ = "0.4"
import string, re, keyword  
commentPat = "#.*"  
# Build up a regular expression
pat = "q[^\q\n]*(\\\\[\000-\377][^\q\n]*)*q"
"""

color = { 'keyword': 0x0000ff,
          'string': 0xff00ff,
          'comment': 0x008000,
          'function': 0x008080,
          'class': 0x008080 }

t = Text()
pos = 0
for tag, start, end, sl in fontify(src):
    t.color = 0
    t.add(src[pos:start])
    t.color = color[tag]
    t.add(src[start:end])
    pos = end
t.color = 0
t.add(src[pos:])

app.body = t
e32.ao_sleep(10)
You first need to install the pyfontify module from here
http://linux.duke.edu/~mstenner/free-docs/diveintopython-3.9-1/py/pyfontify.py    
        Can be used from VBA or as user defined function on worksheet . Shows that recursion can be used in user defined function .

 Function GetFilenameFromPath(ByVal strPath As String) As String
' Returns the rightmost characters of a string upto but not including the rightmost '\'
' e.g. 'c:\winnt\win.ini' returns 'win.ini'
    
    If Right$(strPath, 1) <> "\" And Len(strPath) > 0 Then
        GetFilenameFromPath = GetFilenameFromPath(Left$(strPath, Len(strPath) - 1)) + Right$(strPath, 1)
    End If
End Function
    
        <a href="http://jsfromhell.com/math/mmc">
Minimum Common Multiple

[UPDATED CODE AND HELP CAN BE FOUND HERE]
</a>


Code

//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/math.mmc [v1.0]

MCM = function( divisors ){
	for( var i, j, n, d, r = 1, x = divisors; ( n = x.pop() ) != undefined; )
		while( n > 1 ){
			if( !( n % 2 ) )
				d = 2;
			else {
				for ( i = 3, j = Math.floor( Math.sqrt( n ) ); i <= j && n % i; i += 2 );
				d = i <= j ? i : n;
			}
			for( i in ( n /= d, r *= d, x ) )
				x.splice( i, !( x[i] % d ) && ( x[i] /= d ) == 1 );
		}
	return r;
}


Usage

alert( MCM( [2, 2, 4, 6, 9] ) );
    
        Google maps is a marvelous app.
I try to program a prototype of it on pys60
http://bigbold.com/snippets/posts/show/458

There I only show the default map, not the satellite images.
Retrieving a different mode isn't that difficult.
I read the info from here
http://intepid.com/2005-07-17/21.50/
Then I begin comparing the 2 tile types of the same area
(around California)
http://mt.google.com/mt?v=w2.5&x=20&y=49&zoom=10 (map)
http://kh.google.com/kh?v=3&t=tqtsqrqt (satellite)

Here's the conversion routine between x,y,zoom and quadtree
def quadtree(x,y, zoom):
	out = []
	m = {(0,0):'q', (0,1):'t', (1,0):'r', (1,1):'s'}
	for i in range(17-zoom):
		x, rx = divmod(x, 2)
		y, ry = divmod(y, 2)
		out.insert(0, m[(rx,ry)])
	return 't' + ''.join(out)
Then to convert back
def xyzoom(quad):
	x, y, z = 0, 0, 17
	m = {'q':(0,0), 't':(0,1), 'r':(1,0), 's':(1,1)}
 	for c in quad[1:]:
		x = x*2 + m[c][0]
		y = y*2 + m[c][1]
		z -= 1
	return x, y, z
Using them is simple
>>> quadtree(20,49,10)
'tqtsqrqt'
>>> xyzoom('tqtsqrqt')
(20, 49, 10)
>>> sat_url = 'http://kh.google.com/kh?v=3&t=' + quadtree(20,49,10)
    
        If your server has allow_url_fopen disabled, use this as a workaround for file() ... hell use it anyway and get the http headers as a bonus.
/**
 FUNCTION: ffl_HttpGet()
 * Perform a HTTP Get Request.
 *
 * ffl_HttpGet uses fsockopen() to request a given URL via HTTP
 * 1.0 GET and returns a three element array.  On success, array
 * key 'body' contains the body of the request's reply and key
 * 'header' contains the reply's headers.  On error, the keys
 * returned are 'errornumber' and 'errorstring' from
 * fsockopen()'s third and fourth arguments.  In either case,
 * key 'url' contains an array such as returned from parse_url()
 * after the input url has been massaged a bit.
 *
 * {@source }
 *
 * @param string $url URL to fetch.
 * @param boolean $followRedirects Optionally follow 
 * 'location:' in header, default true.
 * @return array 'header', 'body', 'url' OR 'errorstring',
 * 'errornumber', 'url'.
 */
function ffl_HttpGet( $url, $followRedirects=true ) {
    $url_parsed = parse_url($url);
    if ( empty($url_parsed['scheme']) ) {
        $url_parsed = parse_url('http://'.$url);
    }
    $rtn['url'] = $url_parsed;

    $port = $url_parsed["port"];
    if ( !$port ) {
        $port = 80;
    }
    $rtn['url']['port'] = $port;
    
    $path = $url_parsed["path"];
    if ( empty($path) ) {
            $path="/";
    }
    if ( !empty($url_parsed["query"]) ) {
        $path .= "?".$url_parsed["query"];
    }
    $rtn['url']['path'] = $path;

    $host = $url_parsed["host"];
    $foundBody = false;

    $out = "GET $path HTTP/1.0\r\n";
    $out .= "Host: $host\r\n";
    $out .= "Connection: Close\r\n\r\n";

    if ( !$fp = @fsockopen($host, $port, $errno, $errstr, 30) ) {
        $rtn['errornumber'] = $errno;
        $rtn['errorstring'] = $errstr;
        return $rtn;
    }
    fwrite($fp, $out);
    while (!feof($fp)) {
        $s = fgets($fp, 128);
        if ( $s == "\r\n" ) {
            $foundBody = true;
            continue;
        }
        if ( $foundBody ) {
            $body .= $s;
        } else {
            if ( ($followRedirects) && (stristr($s, "location:") != false) ) {
                $redirect = preg_replace("/location:/i", "", $s);
                return ffl_HttpGet( trim($redirect) );
            }
            $header .= $s;
        }
    }
    fclose($fp);

    $rtn['header'] = trim($header);
    $rtn['body'] = trim($body);
    return $rtn;
}
    
        To copy the entire directory tree at /some/path to other.host via SSH...

find /some/path -print | sort | cpio -o -Hnewc | ssh -C other.host "cpio -idvum"

Make sure you use an absolute path to the directory tree.  Existing files on the destination host will be overwritten unconditionally.    
        This snippet of shell code will set the title bar text of an xterm, rxvt, or possibly other terminal programs:

printf \\033]0\;\%s\\007 "$title"

...where $title is the title text.    
        Here's a little function to decode part of a query string that has been encoded as per the HTML specification with %xx notation, where xx is the hexidecimal representation of a character.

Be warned that this function modifies the contents of the string you pass as the argument!

#include <stdlib.h>

char* decode_query (char* str)
{
        char*           in = str;
        char*           out = str;

        char            c = 0;
        char            decode_buffer[5] = { '0', 'x', 0, 0, 0 };

        while ((c = *in++)) {
                if (c == '%' && *in && *(in + 1)) {
                        decode_buffer[2] = *in++;
                        decode_buffer[3] = *in++;

                        c = char(strtod(decode_buffer, (char**) NULL));
                } else if (c == '+')
                        c = ' ';

                *out++ = c;
        }

        *out = 0;

        return str;
}
    
        
    <a href="#" onClick="<%= remote_function(:update => 'fashion1', :url => { :action => :get_fashion_for_color, :color_name => color_name, :number => 1 })%>;
                         <%= remote_function(:update => 'fashion2', :url => { :action => :get_fashion_for_color, :color_name => color_name, :number => 2 })%>;
                         <%= remote_function(:update => 'fashion3', :url => { :action => :get_fashion_for_color, :color_name => color_name, :number => 3 })%>;
                         return false;">
    
        It's fairly easy, but I have no idea how (in)efficient it is.

Here's the important stuff.

In model:
def self.search(terms)
  find_by_sql(["select t.* from table t where #{ (["(lower(t.text_field1) like ? or lower(t.text_field1) like ?)"] * tokens.size).join(" and ") } order by s.created_on desc", *(tokens * 2).sort])
end

Basically it searches any of the fields you specify.  If I wanted just one search, I'd drop out the second lower(t.text_field) and change the (tokens*2) to just tokens.

Like this:
def self.search(terms)
  find_by_sql(["select t.* from table t where #{ (["(lower(t.text_field1) like ? )"] * tokens.size).join(" and ") } order by s.created_on desc", tokens])
end

The terms array is just an array of single words, lowercase.  They're prepared like this:

 terms = query.split.collect {|c| "%#{c.downcase}%"}

To use this in a controller, I just do this:
 @results = Model.search( @params['query'].split.collect{ |c| "%#{c.downcase}%" } )

Just like that.

From <a href="http://www.roryhansen.ca/?p=20">Rory on Rails</a>

    
        With DateTime, we have to convert value to its short date string representation :
myCompareValidator.ValueToCompare = myDateTime.ToShortDateString();
    
        <a href="http://jsfromhell.com/number/base-conversor">
Minimum Common Multiple

[UPDATED CODE AND HELP CAN BE FOUND HERE]
</a>

//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/number/base-conversor [v1.0]

Conversor = {
	h: '0123456789abcdefghijklmnopqrstuvwxyz',

	int2base: function( n, base ){
		if( base < 2 || base > this.h.length )
			throw new Error( "base inválida" );
		for( var n = parseInt( n ) || 0, result = ""; n; result = this.h.charAt( n % base ) + result, n = Math.floor( n / base ) );
		return result;
	},
	base2int: function( s, base ){
		for( var i = -1, l = s.length, result = 0; ++i < l; result = result * base + this.h.indexOf( s.charAt( i ) ) );
		return result;
	}
}