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

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

Perform Comment Recount for WordPress

Run from the command line and uncomment line #2 if your mysql adapter is installed via RubyGems. Fast as hell.

#!/usr/bin/ruby
#require 'rubygems'
require 'mysql'
 
db = Mysql.real_connect("host", "username", "password", "database")
ids = db.query("SELECT `ID` FROM `wp_posts` WHERE 1")
 
ids.each_hash do |post|
  id = post['ID']
  num = 0
  comments = db.query("SELECT COUNT(1) FROM `wp_comments` WHERE `comment_post_ID`='#{id}' AND `comment_approved`='1';")
  comments.each {|x| num = x[0]}
  up = db.query("UPDATE `wp_posts` SET `comment_count`='#{num}' WHERE `ID`='#{id}';")
end

Using mmap to do a global search and replace on Windows

// Use win32-mmap to do a global search and replace on Windows

require 'win32/mmap'
require 'windows/msvcrt/buffer'
include Windows::MSVCRT::Buffer

Strlen = API.new('strlen', 'L', 'L', 'msvcrt')
Strstr = API.new('strstr', 'LP', 'L', 'msvcrt')

Dir["**/*.rb"].each{ |f|
   p f
   Win32::MMap.new(:file => f) do |addr|
      old_str = 'some_old_string'
      old_len = old_str.length
      new_str = 'some_other_string'
      new_len = new_str.length

      ptr1 = ptr2 = ptr3 = Strstr.call(addr,old_str)

      while ptr1 && ptr1 != 0
         ptr2 += new_len
         ptr3 += old_len
         memmove(ptr2, ptr3, 1 + Strlen.call(ptr3))
         memcpy(ptr1, new_str, new_len)
         ptr1 = ptr2 = ptr3 = Strstr.call(ptr2,old_str)
      end
   end
}

Audioscrobbler

"now_playing" won't have any effect to the statistics, for that use "submit". Use "submit" AFTER playing the song.

require 'digest/md5'
require 'fileutils'
require 'md5'
require 'net/http'
require 'thread'
require 'uri'



Config={}
Config[:user]="yourlastfmusername"
Config[:password]="yourpassword"

Submission_settings={}


def do_handshake
		timestamp = Time.now.gmtime.to_i.to_s

		md5 = Digest::MD5.hexdigest(Config[:password])
		md5 = Digest::MD5.hexdigest(md5 + timestamp)

# replace c=tst and v=1.0 to a vaild id of a last.fm client.

		query = "/?hs=true&p=1.2&c=tst&v=1.0&u=#{Config[:user]}&t=#{timestamp}&a=#{md5}"

		begin
			Net::HTTP.start("post.audioscrobbler.com", 80) do |http|
				resp = http.get(query).body.strip

				case resp
				when /^OK\n([0-9a-z]+)\n(.+)\n(.+)/
					puts("handshake succeeded")
					Submission_settings[:session_id] = $1
					Submission_settings[:now_playing_url] = URI.parse($2)
					Submission_settings[:submission_url] = URI.parse($3)
				when /^BANNED$/
					puts("banned")
				when /^BADTIME$/
					puts("bad time, go fix your clock")
				when /^FAILED (.+)$/
					puts("handshake failed - #{resp}")
				when /^BADAUTH$/
					puts("handshake failed - bad username/password")
				else
					puts("bad response in handshake - #{resp}")
				end
			end
		rescue SocketError => err
			puts("socket error: #{err}")
		rescue SystemCallError => err
			puts("system call error: #{err}")
		rescue IOError => err
			puts("io error: #{err}")
		rescue Timeout::Error
			puts("timeout during handshake")
		end
end

def now_playing(a)
	[:band,:song,:album,:lenght,:nr,:mb].each do |i|
		a[i]="" unless a[i]
		a[i]=a[i].to_s.gsub(/ /,'_')
	end

	Net::HTTP.post_form(Submission_settings[:now_playing_url],{"s"=>Submission_settings[:session_id],"a"=>a[:band], "t"=>a[:song], "b"=>a[:album],"l"=>a[:lenght], "n"=>a[:nr], "m"=>a[:mb]  })
end


def submit(a)
	[:band,:song,:album,:lenght,:rating,:nr,:mb].each do |i|
		a[i]="" unless a[i]
		a[i]=a[i].to_s.gsub(/ /,'_')
	end

	Net::HTTP.post_form(Submission_settings[:now_playing_url],{"s"=>Submission_settings[:session_id],"a[0]"=>a[:band], "t[0]"=>a[:song],"i[0]" =>Time.now.to_i,"o[0]" => 'P', "r[0]"=>a[:rating], "b[0]"=>a[:album],"l[0]"=>a[:lenght], "n[0]"=>a[:nr], "m[0]"=>a[:mb]  })
end

Move acts_as_attachment / attachment_fu images

Use this to move files from the old directory structure (before 0000 format) to new one

Dir.new(File.dirname($PROGRAM_NAME)).each do |f|
  next if f == '0000' || f == 'move.rb' || f == '..' || f == '.'
  
  new_name = sprintf("%04d", f.to_i)
  
  puts "Moving #{f} to #{new_name}"
  puts `mv #{f} 0000/#{name}`
end

Deploying on a passenger / mod_rails host with capistrano

// add this to deploy.rb

namespace :mod_rails do
  desc <<-DESC
  Restart the application altering tmp/restart.txt for mod_rails.
  DESC
  task :restart, :roles => :app do
    run "touch  #{release_path}/tmp/restart.txt"
  end
end

namespace :deploy do
  %w(start restart).each { |name| task name, :roles => :app do mod_rails.restart end }
end

Perform a Rails find() and iterate over the resulting records in groups

module ActiveRecord
  class Base
    # This method lets you iterate over the results of a .find, in groups.
    # (Basically an interface to LIMIT.)
    # Anything you can pass as options to .find, you can pass here. 
    # Example 1:
    #   Order.each_by(100, :conditions => { :cc_processed_at => nil }) do |order|
    #     # do stuff with order
    #   end
    # Example 2:
    #   Person.each_by(50, :order => 'name') do |person, index|
    #     # do stuff with person and index
    #   end
    # Pass :update => true in the options to print a message before each group is
    # fetched from the db.
    #
    # Author: Elliot Winkler <elliot.winkler@gmail.com>
    # Source: http://snippets.dzone.com/posts/show/5461
    def self.each_by(group_size, options={}, &blk)
      update = options.delete(:update) || false
      num_records = count(options.except(:from))
      return 0 if num_records == 0
      #raise "Number of records: #{num_records}"
      also_pass_offset = (blk.arity == 2)
      0.step(num_records, group_size) do |offset|
        find_options = { :offset => offset, :limit => group_size }.merge(options)
        if update
          if num_records == 1
            puts ">> Reading the only record."
          else
            start_offset = offset + 1
            end_offset   = offset + group_size
            end_offset   = num_records if num_records < end_offset
            puts ">> Reading records #{start_offset}-#{end_offset}."
          end
        end 
        find(:all, find_options).each do |record|
          also_pass_offset ? blk.call(record, offset) : blk.call(record)
        end
      end
      num_records
    end
  end
end

Pousse (Game)

#! /usr/bin/ruby
# Pousse.rb   Ruby implementation of the game of Pousse.
class Hash
  #add a method to Hash that gets the next key in the hash, given a key.
  def next(key)
    keys = self.keys
    pos  = keys.index(key)
    if pos+1 == keys.length
      return keys[0]
    else
      return keys[pos+1]
    end
  end  
end
  
class Pousse
  def initialize(size = 4)
    @size       = size.to_i.freeze                      #our size can't change
    @board      = Array.new(@size){ Array.new(@size) }  #2d board array
    @previous   = []                                    #previous boards
    @players    = {:one => 'X', :two => 'O'}.freeze     #hash of players as:
                                                        # :name => piece
    run                                                 #run the game
  end
  
  #returns true if a victor is found, false if not
  def victory?
    grand_total = Hash.new(0)
    inv_players = @players.invert
    
    #add all the rows/cols representing a straight to grand_total
    @board.each_index do |x|
      r_sub, c_sub = Hash.new(0), Hash.new(0)
      @board[x].each_index do |y|
        r_sub[inv_players[@board[x][y]]] += 1 if @board[x][y]
        c_sub[inv_players[@board[y][x]]] += 1 if @board[y][x]
      end
      #add up subtotal vals
      [c_sub, r_sub].each do |a|
        a.each do |x|
          grand_total[x[0]] += 1 if x[1] == @size
        end
      end
    end
    
    #check for victory with straights
    if grand_total.values.inject{|sum, n| sum+n}
      if grand_total[@player] == grand_total[@players.next(@player)]
        puts "It's a tie!"
      elsif grand_total[@player] > grand_total[@players.next(@player)]
        puts "Player #{@player.to_s}, you win!"
        return true
      else
        puts "Player #{@players.next(@player)}, you win!"
        return true
      end
    end
    
    #check to see if this board is not a new one..
    @previous.each do |x|
      if x == @board
        puts "Player #{@player.to_s}, that board is a REPEAT! YOU LOSE!"
        return true
      end
    end
    #add a deep copy of the current board to the previous board list
    @previous << Marshal.load(Marshal.dump(@board))
    false
  end
  
  #print help messages
  def display_help
    puts "--------"
    puts "General commands:
    h - display this help dialog
    d - draw the board
    q - quit the program"
    
    puts "move? commands (i is an integer from 1 to #{@size})
    Li - Left
    Ri - Right
    Ti - Top
    Bi - Bottom"
    puts "--------"
  end
  
  #draw a grid representing current board status
  def draw_board
    #build numbers for top
    print "\n  "
    @size.times do |x|
      print " #{x+1}"
    end
    puts ""
    
    #main board section
    (@size * 2).times do |x|
      if (x % 2 == 0) #print a boundry
        print "  "
        @size.times { print "+-" }
        puts "+"
      else #print a data row
        print "#{x/2+1} "
        @size.times do |y|
          print "|"
          print @board[x/2][y] ? @board[x/2][y] : " "
        end
        puts "|"
      end
    end
    
    #bottom border
    print "  "
    @size.times { print "+-" }
     puts "+"
  end

  #execute a move? command. returns true if the move? was successful,
  #false if not
  def move?(command)
    direction, row = command.split(//)
    row = row.to_i
    
    if row > @size or row < 1 #we have a problem.
      puts "Invalid index value (#{row}) supplied."
      return false
    end
    
    row -= 1 #offset because of array index
    
    #setup values for shift_board call
    case direction.upcase
      when "L" then x = row;      y = 0;        dx = 0;   dy =  1
      when "R" then x = row;      y = @size-1;  dx = 0;   dy = -1
      when "T" then x = 0;        y = row;      dx = 1;   dy =  0
      when "B" then x = @size-1;  y = row ;     dx = -1;  dy =  0
    end
    shift_board(x, y, dx, dy, @players[@player])
    true
  end
  
  #game run loop. this method returns when the game is over
  def run
    puts "Welcome to Pousse!"
    display_help
    @player = :one
    loop do
      puts "Player #{@player.to_s}'s (#{@players[@player]}) turn."
      
      #get a value from the command line
      print "> "
      _input = $stdin.gets
      
      #process the input
      if    _input =~ /^[q|Q]/                  then break
      elsif _input =~ /^[h|H]/                  then display_help
      elsif _input =~ /^[d|D]/                  then draw_board
      elsif _input =~ /^[L|R|T|B|l|r|t|b][\d]/  then
        if move?(_input)
           draw_board
           break if victory? #exit the loop if we find a winner
           @player = @players.next(@player)
        end
      else puts "Command not recognized."
      end
    end
    puts "Thanks for playing Pousse!"
  end
  
  #shift cells in the board until our new data is appended and old data
  #is shifted into blank spaces or lost
  def shift_board(to_x, to_y, dx, dy, append)
    if to_y < @size and to_x < @size then #only handle existing cells
      if @board[to_x][to_y] != nil then
        mv = @board[to_x][to_y]
        @board[to_x][to_y] = nil
        shift_board(to_x+dx, to_y+dy, dx, dy, mv)
      end
      @board[to_x][to_y] = append
    end
  end
end

if ARGV[0]
  Pousse.new(ARGV[0]) 
else
  Pousse.new
end

Matching quoted strings in Ruby

An exercise in string processing and regexp matching, inspired by Parsing Quoted Strings in Ruby and Stupid Ruby Quoting Tricks.

#!/usr/local/bin/ruby -w

# some input examples
str = 'foo "bar baz" qux'
str = 'foo "bar baz " "bar baz" " bar baz" "bar "klr mre" " " \' "abc" \' baz " qux'
str = '" \' \'    " \n "   " \' \' "" foo \'ttt sss\' "bar "qqq zzz" baz" "added term" qux  " \' \'    "  yyy xxx'
str = '"""frickin \'#{bar}\'"""'
str = '""    "frickin chicken "    #{bar}""""'
str = '"""frickin "#{bar}""""'
str = '"a "b c" "d "e" f g" """h""""'       # cf. http://snippets.dzone.com/posts/show/4852

# escaped quotes
str = '\"'
str = "\\\""
str = '\\\''
str = "\\'"

# special cases
str = '"G","H I"'
str = '"G","H I""G","H I"'

str = '"abc""def"'
str = '"""a""b"'
str = '"abc""def""abc""def""abc""def"'
str = '"a"\'\'"b"'

str = "\"abc'vv'tt\"'klt'"

str = "abc,def,\"efg,hij\",klm,nop,\"qrstuv\",wxyz"
str = "abc,def,\"efg,hij\",klm, 'nop, \"qrstuv\",wxyz,mmm '"
str = "abc,def,\"efg,hij\",klm, \"nop, 'qrstuv',wxyz,mmm \""


puts
puts "input string:  #{str}" 
puts "str.inspect :  #{str.inspect}" 
puts

num_of_chars1 = str.count('a-zA-Z_0-9', "^\000ds")

error_code = 0      # in case of a parsing error Shellwords will be used instead of regex1 & regex2
str2 = str.clone

# encode escaped quotes
str = str.gsub(/\\"|\\'/) { |m| m =~ /^\\"$/ ? "\000d\000" : "\000s\000" }

dq_count = str.count('"')
sq_count = str.count("'")

if dq_count % 2 != 0 && sq_count % 2 != 0
   raise ArgumentError, "\e[1modd number of single & double quotes\e[m in: #{str}\nsq_count: #{sq_count}\ndq_count: #{dq_count}\n"
elsif dq_count % 2 != 0
   raise ArgumentError, "\e[1modd number of double quotes\e[m in: #{str}\ndq_count: #{dq_count}\n"
elsif sq_count % 2 != 0
   raise ArgumentError, "\e[1modd number of single quotes\e[m in: #{str}\nsq_count: #{sq_count}\n"
end

# regex1 separates substrings that contain quotes from substrings that do not contain quotes
regex1 = %r{[^"']+|["'].*?["'](?!.*["'])}m  

# example
#"abc 'quote1' pjk 'quote2' xyz".scan(regex1) { |m| puts m } 


regex2 = %r{
# experimental: special cases
\s*["'][^"']+["'][[:punct:]]["'][^"']+["']|  # special case:  xxx "ab c","def g" yyy
\s*["'][^"']+["']{2,}[^"']+["']|             # special case:  xxx "abc""def" yyy
\s"[^"]+"|                                   # special case: xxx "abc 'def' ghi"
\s'[^']+'|                                   # special case: xxx 'abc "def" ghi'
\s*["']\S+["']|                              # special case: "abc'vv'tt"'klt'

\s'\s|                       # xxx ' yyy
\s"\s|                       # xxx " yyy
\s''\s|                      # xxx '' yyy
\s""\s|                      # xxx "" yyy
\s'\s+'\s|                   # xxx '   ' yyy
\s"\s+"\s|                   # xxx "   " yyy
\s"\s[^"]+\s"\s|             # xxx " abc " yyy
\s'\s[^']+\s'\s|             # xxx ' abc ' yyy
\s["']["']+(?=[^"'\s])|      # :qoblock:  xxx "'""'abc yyy
[^"'\s]["']["']+(?=\s)|      # :qcblock:  xxx abc"'""' yyy
\s""+|                       # :dqoblock:  xxx """abc yyy
\s''+|                       # :sqoblock:  xxx '''abc yyy
[^"]""+|                     # :dqcblock:  xxx abc"" yyy
[^']''+|                     # :sqcblock:  xxx abc'' yyy
\s["'](?=[^"'\s])|           # :dqo or :sqo:  xxx "abc yyy  or  xxx 'abc yyy
[^"'\s]["'](?=\s)|           # :dqc or :sqc:  xxx abc" yyy  or  xxx abc' yyy
[^"']+[^"'\s](?=\s)          # no quotes at all
}mx


=begin

There are different kinds of quotes matched by regex2 below. They include:

- :sqo (single quote open)
- :sqc (single quote close)
- :sqoblock (single quote open block)
- :sqcblock (single quote close block)

- :dqo (double quote open)
- :dqc (double quote close)
- :dqoblock (double quote open block)
- :dqcblock (double quote close block)

- :qoblock (quote open block)
- :qcblock (quote close block)

=end


ret = []

str.scan(regex1) do |s| 

   if s !~ /\A["']/

      #puts "s1: #{s}"
      #puts "s1.inspect: #{s.inspect}"

      s.split(/\s+/m).each { |t| ret << t unless t.empty? }

   else

      #puts "s2: #{s}"
      #puts "s2.inspect: #{s.inspect}"

      open_quotes = 0
      close_quotes = 0
      ar = []

      # add spaces to simplify regex2 matching
      s = "\x20" << s << "\x20"    
      s.gsub!(/\x20/, "\x20\x20")  


      s.scan(regex2) do |m|

         # get the index of the quote
         # + 1 for leading space or non-space
         # $` is the prematch string

         index = $`.length + 1 

         post_match = $'  

         #puts
         #puts "index: #{index}"
         #puts "m: #{m.inspect}"
         #puts "m.length: #{m.length}"
         #puts "open_quotes:  #{open_quotes}\nclose_quotes: #{close_quotes}"
         #puts "ret: #{ret.inspect}"
         #puts "ar: #{ar.inspect}"
         #puts


         if m =~ /\A\s''\s\z/

            next unless open_quotes == 0 && close_quotes == 0
            ret << ''
            next

         elsif m =~ /\A\s""\s\z/

            next unless open_quotes == 0 && close_quotes == 0
            ret << ""
            next

         # example: xxx "ab c","def g" yyy
         elsif open_quotes.zero? && close_quotes.zero? && m =~ /\A\s*["'][^"']+["'][[:punct:]]["'][^"']+["']\z/ && m.count('"') % 2 == 0 && m.count("'") % 2 == 0           

            m = m.gsub(/\x20\x20/, "\x20")
            # cf. http://henrik.nyh.se/2008/03/flickr-style-tag-splitting-in-ruby
            m = m.split(/"(.+?)"|\s+/).reject {|s| s.empty? }
            #m = m.split(/"(.+?)"|'(.+?)'|\s+/).reject {|s| s.empty? }
            #m = m.split(/"(.+?)"|'(.+?)'|([[:punct:]])|\s+/).reject {|s| s.empty? }
            ret.concat(m)
            next

         # example: xxx "abc""def" yyy
         elsif open_quotes.zero? && close_quotes.zero? && m =~ /\A\s*["'][^"']+["']{2,}[^"']+["']\z/ && m.count('"') % 2 == 0 && m.count("'") % 2 == 0           
            
            m = m.gsub(/\x20\x20/, "\x20")
            m = m.split(/"(.+?)"|\s+/).reject {|s| s.empty? }
            #m = m.split(/"(.+?)"|'(.+?)'|\s+/).reject {|s| s.empty? }
            ret.concat(m)
            next


         elsif open_quotes.zero? && close_quotes.zero? && m =~ /\A\s"[^"]+"\z/ && m.count('"') % 2 == 0 && m.count("'") % 2 == 0
            ret.concat(m.split(/"(.+?)"|\s+/).reject {|sm| sm.empty? })
            next

         elsif open_quotes.zero? && close_quotes.zero? && m =~ /\A\s'[^']+'\z/ && m.count('"') % 2 == 0 && m.count("'") % 2 == 0
            ret.concat(m.split(/'(.+?)'|\s+/).reject {|sm| sm.empty? })
            next

         elsif open_quotes.zero? && close_quotes.zero? && m =~ /\A\s*["']\S+["']\z/ && m.count('"') % 2 == 0 && m.count("'") % 2 == 0
            ret.concat(m.split(/"(.+?)"|\s+/).reject {|s| s.empty? })
            next


         elsif m =~ /\A\s"\s[^"]+\s"\s\z/

            next unless open_quotes == 0 && close_quotes == 0
            ret << m.gsub(/\x20\x20/, "\x20").strip[1..-2]
            next

         elsif m =~ /\A\s'\s[^']+\s"\s\z/

            next unless open_quotes == 0 && close_quotes == 0
            ret << m.gsub(/\x20\x20/, "\x20").strip[1..-2]
            next

         elsif m =~ /\A\s'\s+'\s\z/

            next unless open_quotes == 0 && close_quotes == 0
            ret << m.gsub(/\x20\x20/, "\x20").strip[1..-2]
            next

         elsif m =~ /\A\s"\s+"\s\z/

           next unless open_quotes == 0 && close_quotes == 0
           ret << m.gsub(/\x20\x20/, "\x20").strip[1..-2]
           next


         elsif m =~ /\A\s""+\z/

            l = m.strip.length
            ar << [:dqoblock, index, l]
            old_open_quotes = open_quotes
            open_quotes += l

            if close_quotes == 0 && old_open_quotes == 0 && open_quotes % 2 == 0 && post_match !~ /"/
               ret << m[2..-2] 
               open_quotes = 0
               ar.pop
               next
            end


         elsif m =~ /\A\s''+\z/

            l = m.strip.length
            ar << [:sqoblock, index, l]
            old_open_quotes = open_quotes
            open_quotes += l

            if close_quotes == 0 && old_open_quotes == 0 && open_quotes % 2 == 0 && post_match !~ /'/
               ret << m[2..-2] 
               open_quotes = 0
               ar.pop
               next
            end


         elsif m =~ /\A[^"]""+\z/

            l = m[1..-1].strip.length
            ar << [:dqcblock, index+l-1, l]      #  index+l-1 is the index of the last closing quote: ''"'[']
            old_close_quotes = close_quotes
            close_quotes += l

            if open_quotes == 0 && old_close_quotes == 0 && close_quotes % 2 == 0 && post_match !~ /"/
               ret << m[2..-2] 
               close_quotes = 0
               ar.pop
               next
            end

         elsif m =~ /\A[^']''+\z/

            l = m[1..-1].strip.length
            ar << [:sqcblock, index+l-1, l]
            old_close_quotes = close_quotes
            close_quotes += l

            if open_quotes == 0 && old_close_quotes == 0 && close_quotes % 2 == 0 && post_match !~ /'/
               ret << m[2..-2] 
               close_quotes = 0
               ar.pop
               next
            end


         elsif m =~ /\A\s'\z/

            ar << [:sqo, index, 1]
            open_quotes += 1

         elsif m =~ /\A\S'\z/

            ar << [:sqc, index, 1]
            close_quotes += 1

         elsif m =~ /\A\s"\z/

            ar << [:dqo, index, 1]
            open_quotes += 1

         elsif m =~ /\A\S"\z/

            ar << [:dqc, index, 1]
            close_quotes += 1


         else


            if m =~ /\A\s"\s\z/              # " surrounded by whitespace

               if open_quotes > close_quotes

                  ar << [:dqc, index, 1]
                  close_quotes += 1

                  # avoid :sqo followed by :dqc or :sqc followed by :dqc
                  if post_match =~ /"/ && open_quotes == close_quotes && (ar.at(-2).first == :sqo || ar.at(-2).first == :sqc)
                     ar.pop
                     ar << [:dqo, index, 1]
                     close_quotes -= 1
                     open_quotes += 1
                  end

               else 

                  ar << [:dqo, index, 1]
                  open_quotes += 1

               end


            elsif m =~ /