Code Language: ruby

Quick and dirty memory profiling

Language: Ruby

require 'pp'

def print_class_counts
  c = Hash.new 0
    ObjectSpace.each_object(Object) do |o|
    c[o.class] += 1
  end
  pp c.sort_by{|k,v|v}.reverse
end
Reveal More
Added 16 days ago by Costco_normal trevorturk

Using Redis for configuration management

Language: Ruby

# Origin: https://gist.github.com/4de7b3c1522b155008e1

module GitHub
  module Config
    def self.[](key)
      $redis.get("gh:cfg:#{key}")
    end

    def self.[]=(key, value)
      $redis.set("gh:cfg:#{key}", value)
    end
  end
end
Reveal More
Added 24 days ago by Twitterprofilephoto_normal zh

Integrate WebSockets (via sunshowers) in Sinatra application

Language: Ruby

# create config.ru like:
#
#   require 'echowebsocket'
#   run EchoWebSocket.new
#
# and start it with: 
#
#   rackup config.ru -s thin -E production -p 8000
#
# echowebsocket.rb will be:

require 'sinatra'
require 'sunshowers'

class Sinatra::Request < Rack::Request
  include Sunshowers::WebSocket
end

class EchoWebSocket < Sinatra::Base
  set :sessions, true

  get "/echo" do
    if request.ws?
      request.ws_handshake!

      request.ws_io.each do |record|
        ws_io.write_utf8(record)
        break if record == "Goodbye"
      end

      begin
        request.ws_quit!
      rescue
        nil
      end
    end
    "You're not using Web Sockets"
  end
end
Reveal More
Added about 1 month ago by Twitterprofilephoto_normal zh

Testing CouchDB view functions in Ruby with Johnson

Language: Ruby

# When CouchDB view functions get complex, it's nice to be able to unit test them.
# When your development dataset is large, and views take some time to build, better
# to find bugs via unit tests over having to wait for a view build to see if things
# are working correctly.

# This implementation uses Johnson for executing Javascript -- see the evaluate_map method
# at the end of this file. Note that we can define the emit and log functions as Ruby Proc 
# objects and have them work in the Javascript context. Pretty cool.

# I think it would be possible to test show and list functions as well, using a similar
# technique to mock out the getRow() and send() functions.
require 'rubygems'
require "johnson"
require "json"
require "test/unit"

# Johnson monkeypatch, so that assert_equal works as expected with array values
class Johnson::SpiderMonkey::RubyLandProxy
  def ==(other)
    case other
    when Array
      to_a == other
    else
      super
    end
  end
end

class TestViews < Test::Unit::TestCase

  def setup
    # Set the design doc in an instance variable. In practice, you'll want to get the 
    # design doc from the server using your preferred HTTP client, ex:
    # 
    #   @ddoc = JSON.parse RestClient.get('localhost:5984/mydb/_design/myapp')
    #
    # If you're getting the same ddoc again and again for each test, you can store it in a
    # class variable or constant on test suite startup, thus avoiding the overhead of 
    # HTTP and JSON parsing of the ddoc for each test.
    @ddoc = JSON.parse(<<-EOV)
      {
        "_id": "_design/myapp",
        "views": {
          "by_city": {
            "map": "function(doc) { emit([doc.city, doc.name], doc); }"
          }
        }
      }
    EOV
  end

  def test_by_city
    mapfun = @ddoc['views']['by_city']['map']
    doc = {"name" => "Geoff", "city" => "Chicago", "state" => "IL"}
    
    rows = evaluate_map(mapfun, doc)['rows']
    
    assert_equal 1, rows.size
    assert_equal ["Chicago", "Geoff"], rows.first['key']
    assert_equal doc, rows.first['value']
  end
  

  private
    def evaluate_map(fun, doc)
      rows, log = [], []
      emitfun = Proc.new {|k, v| rows << {"key" => k, "value" => v}}
      logfun = Proc.new {|m| log << m}
      map = Johnson.evaluate(fun, :emit => emitfun, :log => logfun)
      map.call(doc)
      {"rows" => rows, "log" => log}
    end
end
Reveal More
Added 2 months ago by Devo_normal gbuesing

Get your local IP address

Language: Ruby

# Origin: http://coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/#viewSource

require 'socket'

def local_ip
  # turn off reverse DNS resolution temporarily
  orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true

  UDPSocket.open do |s|
    s.connect '64.233.187.99', 1
    s.addr.last
  end
ensure
  Socket.do_not_reverse_lookup = orig
end
Reveal More
Added 3 months ago by Twitterprofilephoto_normal zh

Refuse bogus page params with will_paginate and Sinatra

Language: Ruby

# Invalid page numbers (e.g. "abc" or "0") will redirect to the home page
# You might also consider serving a 404

before do
  redirect '/', 302 if params[:page] && params[:page].to_i == 0 # refuse bogus page #s
end
Reveal More
Added 3 months ago by Costco_normal trevorturk

SetHITTypeNotification Amazon Mechanical Turk

Language: Ruby

  include Amazon::WebServices::MTurk

  @@mturk = Amazon::WebServices::MechanicalTurkRequester.new :Config => File.join( "#{RAILS_ROOT}/config/", "mturk.yml" )

  def create_notification(hit_type_id, email)
    result = @@mturk.SetHITTypeNotification(
                    :HITTypeId => hit_type_id,
                    :Notification => {
                      :Destination => email,
                      :Transport => "Email",
                      :EventType => "AssignmentSubmitted",
                      :Version => "2006-05-05"
                    },
                    :Active => true
                    )
  end
Reveal More
Added 3 months ago by Img_0163_normal Porta

1 liner in Rack to redirect from one domain name to another

Language: Ruby

# config.ru at the old domain
run lambda {|env| [301, {'Content-Type'=>'text/html', 'Location'=>"http://newdomain.com#{env['PATH_INFO']}"}, ['Redirecting...']]}
Reveal More
Added 3 months ago by Costco_normal trevorturk

Automatic html escaping with Sinatra and Erubis

Language: Ruby

# Requires Sinatra >= 1.0 and Tilt >= 0.9
# (fyi Tilt 0.8 is bundled with Sinatra 1.0, so you'll need to upgrade 
# to the latest gem version)
#
# Tilt 0.9 adds an :escape_html option for Erubis, which allows you
# to leverage Erubis' auto-escape functionality, so that anything inside 
# <%= %> blocks will be html-escaped by default. 
#
# To skip escaping, use a <%== %> block.
require 'rubygems'
gem "sinatra", ">= 1.0"
gem "tilt", ">= 0.9"
require 'sinatra'
require 'erubis'

# Globally set erubis to render with auto-escaping of html
set :erubis, :escape_html => true

get '/' do
  erubis :index
end

helpers do
  # Convenience method for manually escaping html
  def h(text)
    Rack::Utils.escape_html(text)
  end
  
  def link_to(text, href)
    %(<a href="#{href}">#{h(text)}</a>)
  end
end

__END__

@@ index
<p><%= "This string <b>will</b> be html escaped."%></p>
<p><%== "This string <b>will not</b> be html escaped."%></p>
<p><%== link_to "This link tag inner text <b>will</b> be escaped manually in our link_to helper, but the surrounding tag will not", "#" %></p>

@@ layout
<!DOCTYPE HTML>
<head><title>Erubis escaping test</title></head>
<body><%== yield %></body>
Reveal More
Added 3 months ago by Devo_normal gbuesing

Getting access to simple_format and other Rails view helpers

Language: Ruby

class Hello
  extend ActionView::Helpers::TagHelper
  extend ActionView::Helpers::TextHelper

  def world(text)
    simple_format(text) # simple_format is made available via "extend"
  end
end
Reveal More
Added 3 months ago by Costco_normal trevorturk

Run Once Proc

Language: Ruby

class RunOnceProc < Proc
  class MultipleCallAttempt < StandardError; end
  
  def call(*args)
    raise(MultipleCallAttempt, "You cannot call this proc more than once") if called?
    @_called = true
    super
  end
  
  def called?
    !!@_called
  end
  
end

p = RunOnceProc.new {|name| puts "hi #{name}"}

p.call("John")  # => hi John
p.call("Paul")  # => RunOnceProc:: MultipleCallAttempt: You cannot call this proc more than once
Reveal More
Added 4 months ago by Devo_normal gbuesing

CLICK THAT BUTTON

Language: Ruby

# The Sinatra app behind http://clickthatbutton.com/ running on http://heroku.com

# I can't figure out how to increment the "clicks" counter and get the db to return 
# the new total without doing another request... holler if you know how...
# I tried to use Sequel and ended up getting pissed off somehow, so reverted to
# using Active Record and laying in the hammock.

require 'rubygems'
require 'sinatra'
require 'erb'
require 'active_record'

dbconfig = YAML.load(File.read('config/database.yml'))
ActiveRecord::Base.establish_connection dbconfig['production']

class CreateClicks < ActiveRecord::Migration
  def self.up
    create_table :clicks do |t|
      t.integer :clicks, :default => 0, :null => false
    end
    Click.create!(:clicks => 0)
  end
end

class Click < ActiveRecord::Base
end

get '/' do
  response.set_cookie('click', 0) if request.cookies['click'].nil?
  @clicks_total = Click.first.clicks
  erb :index
end

post '/' do
  Click.first.increment!(:clicks)
  Click.first.clicks.to_s
end
Reveal More
Added 4 months ago by Costco_normal trevorturk

Quick and dirty "voting" with basic cookie tracking

Language: Ruby

class VotesController < ApplicationController
  
  def create
    @video = Video.find(params[:id])
    @voted_for = cookies[:voted_for] ? cookies[:voted_for].split(",") : []
    if @voted_for.include?(@video.id.to_s)
      render :text => "You already voted for #{@video}!"
    else
      render :text => "Thanks for voting for #{@video}!"
      cookies[:voted_for] ||= []
      cookies[:voted_for] = cookies[:voted_for] << "#{@video.id},"
      Video.increment_counter(:votes, @video.id)
    end
  end
end
Reveal More
Added 4 months ago by Costco_normal trevorturk

Automatic slug generation advanced with de-dupe technology

Language: Ruby

# I'm not sure if there's a better way to do this, but it works...

# The tests look like:

  test "deals with dupe slugs automatically" do
    v1 = Video.make(:name => "Nick Vegas")
    v2 = Video.make(:name => "Nick Vegas")
    v3 = Video.make(:name => "Nick Vegas")
    assert_equal "nickvegas", v1.slug
    assert_equal "nickvegas2", v2.slug
    assert_equal "nickvegas3", v3.slug
  end

# The model and relevant code looks like:

class Video < ActiveRecord::Base
  before_validation :generate_slug
  validates_presence_of :slug
  validates_uniqueness_of :slug
  
  def generate_slug
    slug = name.parameterize.gsub('-', '')
    if Video.find_by_slug(slug)
      counter = 2
      until Video.find_by_slug("#{slug}#{counter}").nil?
        counter += 1
      end
      slug = "#{slug}#{counter}"
    end
    self.slug = slug
  rescue
    # use validations to catch errors
  end   
end
Reveal More
Added 4 months ago by Costco_normal trevorturk

Passing a block to Rack::Response#finish

Language: Ruby

# Passing a block to Rack::Response#finish
#
# You can pass a block to #write, which yields self;
# calls to #write inside the block will write directly to the
# output stream instead of Rack::Response's internal buffer
class App
  def call(env)
    Rack::Response.new.finish do |resp|
      resp.write "one\n"
      sleep 1
      resp.write "two\n"
      sleep 1
      resp.write "three\n"
    end
  end
end

run App.new

# Run with "rackup" command; use curl to connect:
#
#   > curl localhost:9292
#   one
#   two
#   three
Reveal More
Added 4 months ago by Devo_normal gbuesing

Mock Web

Language: Ruby

#!/usr/bin/env ruby
#
# unknown source :(

require 'rubygems'
require 'rack'
require 'thin'

# Mock server for testing bad or heavyweight server responses; runs on
# localhost:4000 by default
#
# Example of use
#
# In setup method:
#
# @mock_server = MockServer.new # creating a new instance spawns a
# thread running the TCP server
# @mock_server.register( { 'REQUEST_METHOD' => 'GET' }, 
# [ 200, { 'Content-Type' => 'text/plain', 'Content-Length' => '11' }, 
# [ 'Hello World' ]])
# @mock_server.register( { `REQUEST_METHOD' => `GET' }, [
#  200, { 'Content-Type' => 'text/plain', 'Content-Length' => '11' }, 
#  [ 'Hello Again' ]])
#
# After each test, to remove all expectations:
#
# @mock_server.clear
#
# In teardown method:
#
# @mock_server.stop

class MockServer

  def initialize(options={})
    host = options[:host] || '127.0.0.1'
    port = options[:port] || 4000
    @expectations = []
    @server = Thin::Server.new(host, port, self)
    @thread = Thread.new { @server.start }
  end

  def stop
    @server.stop!
    Thread.kill(@thread)
  end

# env should be a hash mapping elements of a Rack env to expected values 
# (see examples above); note that an expected value can be a Proc which 
# will be passed the value from the request
# and executed - if the Proc returns true on execution, the expectation is met
#
# For example, to check that the querystring contains the value `1234', env could be:
#
# { `QUERY_STRING' => lambda { |qs| !((qs =~ /1234/).nil?) } }
#
# response should be a Rack-formatted response; i.e. [response_code,
# {'header' => 'value', ...}, response_body]
#
# options:
# :transient => false to prevent a response being removed after it has 
# been served (default is true)
  def register(env, response, options={})
    transient = options[:transient]
    transient = true if transient.nil?

    @expectations = []

    @expectations.each_with_index do |expectation, index|
      expectation_env, matched_response, transient = expectation
      matched = false

      expectation_env.each do |env_key, value|
        puts "Trying to match #{env_key} => #{value} to request"
        matched = true

        req_value = env[env_key]

        if value.is_a? Proc
          req_element_matches = value.call(req_value)
        else
          req_element_matches = (value == req_value)
        end

        unless req_element_matches
          puts " Value NOT matched: request value was #{env[env_key]} (needed #{value} to match)"
          matched = false
          break
        end
      end

      if matched
        if transient
          @expectations.delete_at(index)
        end
        response = matched_response
        break
      end
    end
    response
  end

end
Reveal More
Added 5 months ago by Twitterprofilephoto_normal zh

Mock Mail

Language: Ruby

#!/usr/bin/env ruby
#
# unknown source :(

require 'socket'

DEBUG = false

def data(sock)
  s = ""

  sock.print "354 End data with <CR><LF>.<CR><LF>\r\n"
  while(line = sock.gets)
    puts line if DEBUG
    break if line =~ /^\.\r?\n?$/
    s += line
  end
  s
end

def session(sock)
  sock.print "220 localhost SMTP mockmail\r\n"
  from = nil
  to = []
  body = nil
  while(line = sock.gets)
    line.chomp!
    puts line if DEBUG
    sock.print case line
      when /HELO/: "250 localhost\r\n"
      when /RSET/: "250 Ok\r\n"
      when /VRFY/:
        /VRFY [^\s]/ =~ line
        "252 #{$1}\r\n"
      when /MAIL FROM/:
        /MAIL FROM:\s*\<?([^\s<>]+)\>?/ =~ line
        from = $1
        puts from if DEBUG
        "250 Ok\r\n"
      when /RCPT TO/:
        /RCPT TO:\s*\<?([^\s\r\n\t\f<>]+)\>?/ =~ line
        to << $1
        puts to if DEBUG
        "250 Ok\r\n"
      when /DATA/:
        body = data(sock)
        "250 Ok\r\n"
      when /QUIT/:
        sock.print "221 Bye\r\n"
        break
      else "500 Err\r\n"
    end
  end
  puts "from: #{from}"
  puts "to: #{to.join '; '}"
  puts "---"
  puts body
  puts "==="
  open("mockmail.txt", "a") { |f|
    f.puts "from: #{from}"
    f.puts "to: #{to.join '; '}"
    f.puts "---"
    f.puts body
    f.puts "==="
  }
  sock.close
end

def main
  begin
    server = TCPServer.new('localhost',25)
    Thread.start {
      loop { sleep 1 }
    }
    loop do 
      Thread.start(server.accept) { |sock|
        begin
          session(sock)
        rescue Exception => e
          p e
        end
      }
    end
  rescue Interrupt => i
    puts "ending..."
  end
end

main
Reveal More
Added 5 months ago by Twitterprofilephoto_normal zh

Truncate a UTF-8 string at character boundary in Ruby 1.8

Language: Ruby

# For more on $KCODE, see
#   http://blog.grayproductions.net/articles/the_kcode_variable_and_jcode_library
$KCODE = 'u'

def truncate(str, length)
  str.match(/.{0,#{length}}/m).to_s
end

p truncate("åéîøü", 3) # => "åéî"
Reveal More
Added 5 months ago by Devo_normal gbuesing

Rack: call handler by name: "thin" -> Rack::Handler::Thin etc.

Language: Ruby

require "rubygems"
require "rack"

def run(server)
  require server
  s = Rack::Handler.const_get("#{server.capitalize}")
  app = proc {|env| [200, {"Content-Type" => "text/plain"}, "hello"]}
  s.run(app,:Host => '127.0.0.1', :Port => 2323)
end

run "thin"
# run "mongrel"
Reveal More
Added 6 months ago by Twitterprofilephoto_normal zh

make a system call and then kill it if the timeout is reached

Language: Ruby

require 'timeout'

class System
 def self.system_with_timeout(timeout, *args)
  if ( (pid = fork) == nil )
    #child process
    @@logger.debug(args.join(' '))
    exec(*args)
  else
    success = false
    #parent process
    begin
      #TODO if the process fails return false
      success = Timeout::timeout(timeout){ Process.waitpid(pid) }
    rescue Timeout::Error
      @@logger.error "***** Timeout error"
      Process.kill("HUP", pid)
      Process.detach(pid)
    end
    success
  end
 end
end
Reveal More
Added 6 months ago by Twitterprofilephoto_normal zh