Never been to TextSnippets 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 (or not, you can keep them private!)

« Newer Snippets
Older Snippets »
Showing 81-100 of 117 total

DRY up empty controller actions

Ever create Rails views that don't user the controller at all just to take advantage of an application layout?
If you have, you may have a lot of code that looks like this:


class HelpController < ApplicationController
  def index
  end

  def tutorial
  end

  def faq
  end
end


Well, there's a simple way to make this a lot cleaner...


class ApplicationController < ActionController::Base
  def self.simple_action(*actions)
    actions.each {|action| class_eval("def #{action}; end")}
  end
end

Now your controller can look like this instead...

class HelpController < ApplicationController
  simple_action :index, :tutorial, :faq
end

Recursively add file extensions in OSX using Magic and your own filetypes

ExtensionAdder v.1

ExtensionAdder is an OSX ruby script that recursively traverses a folder, adding extensions to approprate files. The script uses the Magic file, but you can extend the behavior by adding your own shell scripts (see the "includes" folder) to grep into files that Magic only classifies as "data".

At this time you have to explicitly state which file types you want to add extensions to.

Download it here


Sandon Jurowski
[email protected]

Make a subversion release

Ruby script to make a release from SVN trunk.

Assumes a repository structure of:

/path/to/Trunk
/path/to/Releases/YYYY-MM-DD--XX

Should be easy enough to modify to suit your needs. Comments welcome :)

Example usage:
vi /usr/local/bin/release (and dump snippet into it)
chmod +x /usr/local/bin/release
cd /path/to/checked-out-trunk
release


#!/usr/bin/ruby

today = Time.now.strftime('%Y-%m-%d')

if `svn info`.to_a[1] !~ /^URL: (.*)\/Trunk$/
        puts "Repository invalid. Must be in Trunk."
        exit
end

repo_url = $1

repo = repo_url.split('/').last

release_url = repo_url + "/Releases"

if `svn ls #{release_url}`.to_a.last =~ /#{today}--(\d+)/
        num = $1.to_i + 1
else
        num = 1
end

release = "#{today}--#{num}"

cmd = "svn copy #{repo_url}/Trunk #{release_url}/#{release} -m 'copy #{repo} trunk to release #{release}'"
puts cmd
puts

print "Execute command? "

if gets.chomp.upcase != 'Y'
        puts "Nothing done."
        exit
end

`#{cmd}`
puts "Copied as #{release}."
puts "Execute on the remote machine:"
puts "svn switch #{release_url}/#{release}"

Replacing all shebangs in a rails app

perl -pi -e 's|^#!/.*|#!/usr/bin/env ruby|;' script/* script/*/* public/dispatch.*

Camel case a string ( removing accents )

# input str = " j'ai écris l'œuvre de ma vie "
# output str :"JAiEcrisLOeuvreDeMaVie"

accents = { ['á','à','â','ä','ã','Ã','Ä','Â','À'] => 'a',
  ['é','è','ê','ë','Ë','É','È','Ê'] => 'e',
  ['í','ì','î','ï','I','Î','Ì'] => 'i',
  ['ó','ò','ô','ö','õ','Õ','Ö','Ô','Ò'] => 'o',
  ['œ'] => 'oe',
  ['ß'] => 'ss',
  ['ú','ù','û','ü','U','Û','Ù'] => 'u'
  }
accents.each do |ac,rep|
  ac.each do |s|
    str.gsub!(s, rep)
  end
end
str.gsub!(/[^a-zA-Z_\- ]/," ")
str = " " + str.split.join(" ")
str.gsub!(/ (.)/) { $1.upcase }

Convert numbers to words

Ugly code. But it works. If you have something better, then post it.

This code is probably (definitely :-) buggy, so if you want to get real work done, just use the Linguistics gem instead.

class Number
  
  def self.to_words(number)
    Number.new.to_s(number)
  end
  
  def self.commify(number)
    (s=number.to_s;x=s.length;s).rjust(x+(3-(x%3))).gsub(/(\d)(?=\d{3}+(\.\d*)?$)/,'\1,')
  end
    
  def initialize
    @unit = %w[zero one two three four five six seven eight nine]
    @teen = %w[ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]
    @tens = %w[zero ten twenty thirty fourty fifty sixty seventy eighty ninety]
    @qtys = %w[hundred thousand million billion trillion quadrillion quintillion]
    @zero = ["zero"]
    @hundred = "hundred"
    @sepr = "and"
  end
    
  def to_s(number)
    out = quantify(number).flatten
    for x in 0 .. out.length - 1
      out[x] = nil if out[x] == @sepr && out[x+1] == @sepr
    end
    out.compact!
    out = @zero if out.length == 1 && out[0] == @sepr
    out.pop while out.last == @sepr
    out.shift while out.first == @sepr    
    out.join(' ').gsub(/ ,/,',')
  end
        
  private 
  
  def padded_groups(v)
    out = []
    padded = (s=v.to_s;x=s.length;s).rjust(x+(3-(x%3))).gsub(//,'0')
    padded.scan(/.{3}/)
  end
  
  def wordify(v)
    out = []
    zero = '0'[0]
    h, t, u = v[0] - zero, v[1] - zero, v[2] - zero
    if h != 0
      out << @unit[h]
      out << @hundred
    end
    out << @sepr if h != 0 && (t != 0 || u != 0)
    out << @sepr if h == 0 && t == 0 && u != 0
    if t == 1
      out << @teen[u]
    else
      out << @tens[t] if t != 0
      out << @unit[u] if u != 0
    end
    return out
  end
  
  def quantify(v)
    v = padded_groups(v).reverse
    pos = v.length - 1
    out = []
    while pos >= 0
      word = wordify(v[pos])
      if word[0] != nil
        out << word
        out << @qtys[pos] if pos != 0                
      else
        out << @sepr
      end
      pos -= 1
    end
    return out
  end

end

# for number in [
#     0, 
#     1, 
#     3, 
#     11, 
#     100,
#     1000, 
#     1001, 
#     1100, 
#     1101, 
#     1_000_001, 
#     8_000_000_000, 
#     8_000_000_001, 
#     4_567_890_923, 
#     6_804_567_890_903, 
#     5_006_804_567_890_903
#   ]
#   print "#{Number.commify(number)}: #{Number.to_words(number)}\n"
# end

Substitute for the :spacer_template option to rail's "render" method

when working with the :collection option, it seems silly to have to have an entire file just for a spacer, which would probably just be something like "
" for most, so this is a great substitute for
<%= render :partial => "thing", :collection => @coll, :spacer_template => "filename_to_file_with_hr_inside_it" %>


New version with code embedded:
  <%= @coll.map { |item| render :partial => "thing", :locals => {:thing => item} }.join("
") %>

Copy data from database into fixtures

Take from pylonhead.com

  def self.to_fixture
    write_file(File.expand_path("test/fixtures/#{table_name}.yml", RAILS_ROOT),
      self.find(:all).inject("---\n") { |s, record|
        self.columns.inject(s+"#{record.id}:\n") { |s, c|
          s+"  #{{c.name => record.attributes[c.name]}.to_yaml[5..-1]}\n" }
    })
  end

Bulk svn actions (usefull with rails)

Just run this code from inside your repository. This will do a bulk action like "svn add" on each file marked with the given filter (like '?') when doing "svn status"

Beware: this code might break with multi word filenames...

usage :
# ./svn_bulk ? add ---> this shows a preview of the actions
# ./svn_bulk ? add 1 ---> action !
#!/usr/bin/ruby
sign, action, doit = ARGV
sign = '\?' if sign == '?'
list = IO.popen("svn st")
list.each {|i|
if (i =~ /^#{sign}\s*(.*)/) 
cmd = "svn #{action} '"+$1+"'"
print cmd + "\n"
system(cmd) if doit
end
}

Very simple act_as base file

This is a very simple file to show how to add 'act_as_whatever' to ActiveRecord.

To use it, put the code into a file like lib/your_super_name/acts/idiot.rb and voilà.
Thanks to technoweenie for "acts_as_paranoid" which I used with "acts_as_tree" to build this template.

module YourSuperName
  module Acts
    module Idiot
      # this is called when the module is included into the 'base' module
      def self.included(base)
        # add all methods from the module "AddActsAsMethod" to the 'base' module
        base.extend AddActsAsMethod
      end
      module AddActsAsMethod
        def acts_as_idiot
          # BELONGS_TO HAS_MANY GOES HERE

          class_eval <<-END
            include YourSuperName::Acts::Idiot::InstanceMethods
          END
        end
      end
      
      
      module InstanceMethods
        def self.included(aClass)
          aClass.extend ClassMethods
        end

        # PUT YOUR INSTANCE METHODS HERE
        def idiot(msg)
          "#{self}: I am an idiotic object. And I say '#{msg}'."
        end
        
        module ClassMethods
          # PUT YOUR CLASS METHODS HERE
          def idiot(msg)
          "#{self}: I am an idiotic class. And I say '#{msg}'."
          end
        end
      end
    end
  end
end

ActiveRecord::Base.send :include, YourSuperName::Acts::Idiot

Getting a less verbose list of installed gems

Wanna know what gems you have installed without looking at all the descriptions?

gem list | egrep -v "^( |$)"


Here's a (trimmed) sample output:

$ gem list | egrep -v "^ |^$"
*** LOCAL GEMS ***
actionmailer (1.2.1, 1.2.0, 1.1.5)
actionpack (1.12.1, 1.12.0, 1.11.2)
actionwebservice (1.1.2, 1.1.1, 1.1.0, 1.0.0)
activerecord (1.14.2, 1.14.1, 1.14.0, 1.13.2)
activesupport (1.3.1, 1.3.0, 1.2.5)
BlueCloth (1.0.0)
capistrano (1.1.0)
diff-lcs (1.1.2)

Upload your Flickr photos to Strongspace

require 'net/http'
require 'rubygems'
require_gem 'flickr'
require_gem 'net-sftp'

flickr_username = "[email protected]"
flickr_pass = 'x'
strongie_pass = 'x'
strongie_username = 'johan'
strongie_upload_dir = "flickr_test"

flickr = Flickr.new 
flickr.login(flickr_username, flickr_pass)
user = flickr.users(flickr_username)

Net::SFTP.start("#{strongie_username}.strongspace.com", strongie_username, strongie_pass) do |sftp|
  Net::HTTP.start('static.flickr.com') do |http|
    user.photos.each do |photo|
      src_url = photo.source('Large').sub("http://static.flickr.com", '')    
      puts "Fetching \"#{photo.title}\"..."
      res = http.get(src_url)
      filename = File.basename(src_url)
      sftp.open_handle("/home/#{strongie_username}/#{strongie_upload_dir}/#{filename}", 'w') do |handle|
        result = sftp.write(handle, res.body)
        puts "Wrote #{filename} with result code: #{result.code}..."
      end    
    end
  end
end

Format an integer with commas to make it more readable

More information or better ways of doing this welcome ...

def commify(number)
    c = { :value => "", :length => 0 }
    r = number.to_s.reverse.split("").inject(c) do |t, e|  
      iv, il = t[:value], t[:length]
      iv += ',' if il % 3 == 0 && il != 0    
      { :value => iv + e, :length => il + 1 }
    end
    r[:value].reverse!
  end


Alex Young suggested

def commify(v)
 (s=v.to_s;x=s.length;s).rjust(x+(3-(x%3))).scan(/.{3}/).join(',').strip
end


and there's always

number_with_delimiter(number, delimiter)


from NumberHelper in the Rails API ... which is implemented as follows:-

def number_with_delimiter(number, delimiter=",")
  number.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
end


They don't always work too well when the number has a decimal point in it (and more than two or so digits after the decimal point), so there's room for an improved version ...

JV suggested the following snippet from http://pleac.sourceforge.net/pleac_ruby/numbers.html which appears to be able to handle commas and decimal places as well.

def commify(n)
    n.to_s =~ /([^\.]*)(\..*)?/
    int, dec = $1.reverse, $2 ? $2 : ""
    while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
    end
    int.reverse + dec
end

Clearing out ruby sessions less than a day old (meaning that etc periodic won't get)

find /tmp/ -name "ruby_sess*" -cmin +1 -exec rm \{} \;
find /tmp/ -name "*request_body*" -cmin +1 -exec rm \{} \;
find /tmp/ -name "*CGI*" -cmin +1 -exec rm \{} \;
find /tmp/ -name "*apr*" -cmin +1 -exec rm \{} \;
find /tmp/ -name "open-uri*" -cmin +1 -exec rm \{} \;
find /tmp/ -name "vi*" -cmin +1 -exec rm \{} \;
find /tmp/ -name "sess_*" -cmin +1 -exec rm \{} \;
find /var/tmp/ -name "sess_*" -cmin +1 -exec rm \{} \;

Install Rails/lighttpd with DarwinPorts for Tiger

install darwinports package

Add 'export PATH=/opt/local/bin:$PATH' to ~/.bashrc

sudo port -d selfupdate

sudo port install ruby

sudo port install rb-rubygems

sudo gem install rails --include-dependencies

sudo port install readline

sudo port install lighttpd

vi /opt/local/etc/lighttpd.conf [edit lighttpd.conf to your liking]

set up launchd item for lighttpd
        -- restart lighttpd: sudo launchctl stop net.lighttpd
                             sudo launchctl start net.lighttpd

sudo port install fcgi

sudo port install rb-fcgi
         
install official OS X MySQL package (not darwinports)

sudo gem install mysql -- --with-mysql-dir=/usr/local/mysql


Links:
darwinports package
launchd item
OS X MySQL package

Rake task to load fixtures in a specific order

The default task for loading fixtures, rake load_fixtures, appears to load the fixture data in alphabetical order. If you have foreign key or other constraints, it may be impossible to load the fixtures into the database.

The rake task below searches for a file called test/ordered_fixtures.rb and loads that file. The file contains code that sets an environment variable specifying the load order for fixtures.

ENV["FIXTURE_ORDER"] = 
  %w( entities interaction_sources interaction_devices payments 
      interactions accounts employments enrollments payables 
      receivables tenures wards ).join(' ')


The lib/tasks/fixtures.rake (rake load_fixtures_ordered) task first loads all fixtures specified via ordered_fixtures, and then loads all other fixtures not specified as being ordered so it should work for you even if you do not create an ordered_fixtures file.

require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
require File.expand_path(File.dirname(__FILE__) + "/../../test/ordered_fixtures")

ENV["FIXTURE_ORDER"] ||= ""

desc "Load fixtures into #{ENV['RAILS_ENV']} database"
task :load_fixtures_ordered => :environment do
  require 'active_record/fixtures'  
  ordered_fixtures = Hash.new
  ENV["FIXTURE_ORDER"].split.each { |fx| ordered_fixtures[fx] = nil }
  other_fixtures = Dir.glob(File.join(RAILS_ROOT, 'test', 'fixtures', '*.{yml,csv}')).collect { |file| File.basename(file, '.*') }.reject {|fx| ordered_fixtures.key? fx }
  ActiveRecord::Base.establish_connection(ENV['RAILS_ENV'])
  (ordered_fixtures.keys + other_fixtures).each do |fixture|
    Fixtures.create_fixtures('test/fixtures',  fixture)
  end unless :environment == 'production' 
  # You really don't want to load your *fixtures* 
  # into your production database, do you?  
end


The code may not be the best but it Works For Me.

Rails MySQL Session Sweeper

1) Download the launchd GUI, Lingon, from: http://lingon.sourceforge.net/

2) Add hourly job:

$RAILS_APP_DIR/script/runner 'ActiveRecord::Base.connection.delete("DELETE FROM sessions WHERE updated_at < now() - INTERVAL 1 HOUR")'


3) My launchd task plist file (yours will vary):

<?xml version="1.0" encoding="UTF-8"?>
DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Labelkey>
        us.boygeni.mysql-session-sweeper</string>
        <key>LowPriorityIOkey>
        />
        <key>ProgramArgumentskey>
        
                /users/defeated/Sites/rails_apps/boygenius/script/runnerstring>
                'ActiveRecord::Base.connection.delete("DELETE FROM sessions WHERE updated_at < now() - INTERVAL 1 HOUR")'</string>
        array>
        RunAtLoad</key>
        <true/>
        <key>StartIntervalkey>
        3600</integer>
dict>
</plist>

Is this error in installing rails via rubygems important?

Horatio:~ Rahul$ sudo gem install rails --include-dependencies
Attempting local installation of 'rails'
Local gem file not found: rails*.gem
Attempting remote installation of 'rails'
Updating Gem source index for: http://gems.rubyforge.org
Successfully installed rails-1.0.0
Successfully installed rake-0.6.2
Successfully installed activesupport-1.2.5
Successfully installed activerecord-1.13.2
Successfully installed actionpack-1.11.2
Successfully installed actionmailer-1.1.5
Successfully installed actionwebservice-1.0.0
Installing RDoc documentation for rake-0.6.2...

lib/rake.rb:733:18: unexpected token: '#'
Installing RDoc documentation for activesupport-1.2.5...
Installing RDoc documentation for activerecord-1.13.2...
Installing RDoc documentation for actionpack-1.11.2...

lib/action_controller/code_generation.rb:77:31: unexpected token: '#'

lib/action_controller/code_generation.rb:168:31: unexpected token: '#'
ERROR:  While executing gem ... (NoMethodError)
    undefined method `find_module_named' for nil:NilClass

Ruby Function Time Diff To String

def time_diff time1, time2
diff = time1 - time2

if diff < 1.minute
return diff.ceil.to_s + " seconds"
elsif diff < 1.hour
return (diff / 1.minute).ceil.to_s + " minutes"
elsif diff < 1.day
return (diff / 1.hour).ceil.to_s + " hours"
elsif diff < 7.day
return (diff / 1.day).ceil.to_s + " days"
elsif diff < 1.month
return (diff / 1.week).ceil.to_s + " weeks"
elsif diff < 1.year
return (diff / 1.month).ceil.to_s + " months"
else
return (diff / 1.year).ceil.to_s + " years"
end
end

Daedalus Config to Keep Lighttpd Up Nicely

This daedalus config as well as my previous snippet is meant to supplement chapter 5 of "Lighttpd the painless way".

This config is dependent on having a ~/lighttpd directory setup as described in that manual. Also, you must have the restart.rb script (again from my previous snippet) in the lighttpd folder.

As before, remember to swap out your USERNAME, DOMAIN, and PORT.

The first check here is that a lighttpd process is running. If not then it calls restart.rb which will kill any zombie dispatchers and restart lighttpd.

The second check is more of a departure from the original suggestion. Rather than checking that a specific file is generating the expected output, I go right to the source and verify that lighttpd is responding with an HTTP header on the port you were assigned. This is a pure indication of whether lighttpd is responsive on the correct port. It won't be fouled up by application errors or apache forwarding misconfiguration. More importantly, it won't generate a flood of restarts due to an unrelated code error.

Also, you will notice I set the checkinterval to 10 minutes. I felt this was a good compromise between keeping lighttpd up and saturating the server with unnecessary processing.

name: lighttpd
checkcommand: /bin/ps axww
checkregex: /lighttpd/
onfailcommand: /home/USERNAME/lighttpd/restart.rb
checkinterval: 600 
aftercommandwait: 120

name: lighttpd-external
checkcommand: /usr/local/bin/curl -I http://YOURDOMAIN.com:YOURPORT
checkregex: /^HTTP/s
onfailcommand: /usr/bin/killall -9 lighttpd; /home/USERNAME/lighttpd/restart.rb
checkinterval: 600 
aftercommandwait: 120
« Newer Snippets
Older Snippets »
Showing 81-100 of 117 total