Viking's Ruby Snippets

Here's some Ruby snippets I've written or found. Some of these are here to help me remember how to do certain things, and others are here for no good reason at all.

Simple Buffer

Here's a buffer class I whipped up:

class Buffer include Enumerable

attr_reader :length def initialize(capacity) @buffer = Array.new(capacity) @capa = capacity @length = 0 end

def <<(value) raise "buffer is full" if full? @buffer[@length] = value @length += 1 self end

def each(&block) @buffer[0, @length].each(&block) end

def full? @length == @capa end

def flush! @length = 0 end end

Flickr Interesting Photos

Here's a little script I wrote that downloads some of the latest interesting photos from Flickr, crops them, scales them, and sets them as your KDE desktop. It's set up for 6 desktops and 1280x1024 resolution. You can change that by using the variables at the top of the script.

Requirements: imagemagick, xmlsimple (gem)

» Download

A better version of this can be found here: http://github.com/viking/kawalla

Module Class Methods

I forget how to do this a lot, so here's an example:

module Foo module ClassMethods def junk "junk" end end

def self.included(klass) klass.extend(ClassMethods) end end

class Bar include Foo end

Bar.junk #=> "junk"

Sudoku Solver

I wrote this sudoku solver during a long road trip because I got frustrated with a sudoku puzzle I was working on.

class Board class Space attr_accessor :value def initialize(value) @value = value end

def empty? @value == 0 end

def to_s empty? ? " " : @value.to_s end alias :inspect :to_s

def <=>(oth) @value <=> oth.value end end

ROWS = (0..8).collect { |i| Array.new(9) { |j| i*9 + j } } COLUMNS = (0..8).collect { |i| Array.new(9) { |j| j*9 + i } } BOXES = (0..8).collect do |i| j = 27 * (i / 3) + 3 * (i % 3) # first row offset k = j + 9 # second row offset l = k + 9 # third row offset [j, j+1, j+2, k, k+1, k+2, l, l+1, l+2] end

attr_reader :spaces def initialize(spaces) raise unless spaces.length == 81 @spaces = spaces.collect { |s| s.is_a?(Space) ? s : Space.new(s) } end

def row(index) @spaces.values_at(*ROWS[index]) end

def column(index) @spaces.values_at(*COLUMNS[index]) end

def box(index) @spaces.values_at(*BOXES[index]) end

def empty_spaces empties = [] @spaces.length.times do |i| empties << i if @spaces[i].empty? end empties end

def clone Board.new(@spaces.collect { |s| s.dup }) end

def valid? [:row, :column, :box].collect do |method| return false unless (0..8).collect { |i| set = send(method, i).select { |x| x.empty? } set.collect! { |x| x.value } set.uniq == set }.all? end true end

def complete? @spaces.collect { |s| s.empty? }.all? && valid? end

def to_s str = "" 9.times do |i| row = row(i) str << "+-------" * 3 + "+\n" if i % 3 == 0
    1. times { |j| str << "| %s %s %s " % row[(j*3)..(j*3+2)] } str << "|\n" end str + "+-------" * 3 + "+" end
end

class Solver def initialize(board) @board = board.clone end

def solve empties = @board.empty_spaces empties.each_with_index do |space_i, i| (1..9).each do |j| @board.spaces[space_i].value = j next unless @board.valid? return @board if i == empties.length - 1 b = Solver.new(@board).solve return b if b end end nil end end

board = Board.new([ 3,0,4,5,0,8,0,0,7, 9,8,2,7,4,6,1,3,5, 5,0,7,0,0,9,8,0,4, 8,4,0,9,0,5,6,7,0, 1,7,0,0,6,4,0,0,8, 6,2,0,0,8,7,4,0,0, 2,9,0,8,5,0,7,4,0, 7,3,0,4,9,0,5,8,0, 4,5,8,6,7,0,0,0,0 ]) #puts "row 2" #p board.row(2) #puts "column 2" #p board.column(2) #puts "box 0" #p board.box(0) #puts "box 4" #p board.box(4) #puts "box 7" #p board.box(7) puts "======================" puts board.to_s puts "======================" puts Solver.new(board).solve.to_s

» Download

Bash Progress Meter

class Progress RESET = "\r\e[0K"

def initialize(total, increment = 1, total_steps = 50) @total = total.to_f @count = 0 @increment = increment @total_steps = total_steps.to_i end

def next return if done? @count += @increment draw end

def done? @count >= @total end

def reset! @count = 0 end

private def draw perc = @count / @total steps = (perc * @total_steps).round left = @total_steps - steps

print "%s[%s>%s] %.2f%" % [RESET, "=" * steps, "_" * left, perc * 100.0] $stdout.flush puts if done? end end

x = Progress.new(1000) while (x.done?) do x.next sleep(0.01) end

Based on ideas from http://snippets.dzone.com/posts/show/3760

Normalizing mp3's

Here's a script to normalize mp3's. sox with mp3 encoding support and the id3lib-ruby rubygem is required.

#!/usr/bin/ruby require 'rubygems' require 'id3lib'

targetdir = `mktemp -d`.chomp puts "Target directory: #{targetdir}" Dir["*.mp3"].each do |file| print "Normalizing #{file}..." $stdout.flush

file2 = file.gsub(/'/, "\\'") adjust = %x{sox '#{file2}' -e stat -v 2>&1}.chomp.to_f if adjust < 1.01 puts "not done." next end adjust -= 0.01 afile = "#{targetdir}/#{file}" afile2 = afile.gsub(/'/, "\\'") %x{sox -v #{adjust} '#{file2}' '#{afile2}'}

# assign id3 tags tag = ID3Lib::Tag.new(file) atag = ID3Lib::Tag.new(afile) tag.each { |frame| atag << frame.dup } atag.update!

puts "done (#{adjust})." end

IRB echo

To turn off IRB's echo of return values, do this: conf.return_format = ""

Here's a function in ~/.irbrc to turn it off and on easily: def echo(bool) val = case bool when Symbol if bool == :on true else false end else bool end conf.return_format = val ? "=> %s\n" : "" end

Using Proc's in Case Statements

Someone asked about this in #ruby-lang. I came up with this solution:

class Foo def good? true end end

class Proc alias :orig_eql :=== def ===(other) if other.is_a?(Foo) call(other) else orig_eql(other) end end end

f = Foo.new case f when proc { |x| x.good? } puts "yay" end

Other Bits of Code

A neat way to calculate number of duplications in an array (rickdangerous from #ruby-lang): a = [1,1,1,1,2,2,2,3,3,3,4,5,5,6] res = []; a.uniq.each {|x| res << [x, a.size - [a.delete(x), a.size][1]]}

My version: a.inject(a.uniq.collect{|x| [x, 0]}) {|arr, x| arr.assoc(x)[1] += 1; arr}

Leet Abbreviation Goodness Stuff

Rails Stuff

Generating fixtures from existing data

Something like this (although this is a specific issue): template = ERB.new(<<EOF) two_<%= field %><%= suffix %>: patient: two field_name: <%= field %> reason: <%= reason %> status: todo created_at: <%%= Time.now.to_s :db %> updated_at: <%%= Time.now.to_s :db %> EOF

hsh = Patient.find(:first, :order => "id desc").problem_hash hsh.keys.sort.each do |field| probs = hsh[field] probs.each_with_index do |problem, i| reason = problem.reason suffix = probs.length > 1 ? "_#{i}": "" puts template.result(binding) end end

DRY database.yml

I always forget how to write DRY YAML, so here it is for reference:

login: &login
  adapter: mysql
  encoding: utf8
  username: foo
  password: bar
  socket: /var/run/mysqld/mysqld.sock

development:
  database: foo_dev
  <<: *login

test:
  database: foo_test
  <<: *login

production:
  database: foo
  <<: *login

Development Script

I wrote a script to set up Konsole with several tabs for developing Ruby on Rails applications. It assumes your Rails apps are in ~/rails, but you can change it via the RailsDev::BASEDIR constant. You also need the korundum library (ubuntu package is libkorundum0-ruby1.8). It randomly chooses a port for Webrick to use on a per-application basis. That way each application will run its server on a unique port, so you can set up separate saved passwords in Firefox without conflicting with other app's saved passwords, etc. Ain't Ruby fun? You can tweak the .railsdevrc file in your home area to change tab setup. Here is an example configuration file.

ALERT! If the script segfaults, it's probably the korundum package's fault. Download the korundum source and build it yourself.

» Download

Topic attachments
I Attachment Action Size Date Who Comment
flickr.rbrb flickr.rb manage 2.4 K 11 Apr 2008 - 14:00 JeremyStephens Flickr script
rails_dev.rbrb rails_dev.rb manage 7.5 K 03 Jan 2008 - 09:07 JeremyStephens Rails development script
railsdevrcEXT railsdevrc manage 0.7 K 03 Jan 2008 - 09:08 JeremyStephens Example Rails development configuration
sudoku_solver.rbrb sudoku_solver.rb manage 2.6 K 03 Jan 2008 - 09:23 JeremyStephens Sudoku solver script
Topic revision: r7 - 31 Mar 2010, JeremyStephens
 

This site is powered by FoswikiCopyright © 2013-2022 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Vanderbilt Biostatistics Wiki? Send feedback