August 6th, 2007 by ahsan
Here are some things about Ruby Strings that may have escaped your attention - if you were introduced to Ruby via Rails
Efficiency
Since Ruby scans double-quoted strings for variables and escape sequences, it’s more efficient to use single-quotes for raw strings:
@sentence = 'Jackdaws love my big sphinx of quartz'
redirect_to :index => 'action'
Pretty Please, with sugar on top …
Split your strings across multiple lines. No backslashes required (sorry, couldn’t resist that !).
sql_query = "SELECT [column]
FROM [table]
WHERE [condition]
-- sql comment goes here"
or
# Q = double-quotes, embed variables
# q = single-quotes
sql_query = %Q{SELECT @columnname
FROM @tablename
WHERE @conditions}
# You may use [ < or (as delimiters instead of {
ASCII code
To obtain the ASCII code for a character, prefix it with a question-mark:
Convert it back to a string with:
Concatenation
Use the << operator to concatenate strings. Where += or + create a new copy, << appends to an existing string. Hence, it is more efficient:
Instead of:
(source)
Index a string with a regexp
You can test a string like this:
email = "spamandbakedbeans@skit.org"
if email[/@/]
puts "I found the first @"
end
And this replaces the first match
string = "jackdaws love my big sphinx of quartz"
string[/a/] = 'A'
# => jAckdaws love my big sphinx of quartz
This replaces the second match
string = "jackdaws love my big sphinx of quartz"
string[/(j).+(z)/, 2] = "Z"
# => jackdaws love my big sphinx of quartZ
Remember, the regexp matches the entire string
Convert hex to integer (sort of)
Given a string representation of a hexadecimal, String.hex returns the corresponding integer:
puts "0x7b".hex # you can omit 0x if you wish
# => 123
Multiply a string
puts "<br />" * 3
# => "<br /><br /><br />"
June 17th, 2007 by ahsan
Well, this is weird.
I wrote a rake task to import data from a csv file (output from a legacy system) into my development database for testing. The catch was that I wanted to extend my model class by adding a custom method only in the rake file.
require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
class Customer < ActiveRecord::Base
def my_custom_method
end
end
But here, for some reason, rake tries to define a _new_ activerecord model, not redefine the existing model I’ve written. So, what I tried was to precede the class definition with:
c = Customer.new # which really goes to waste
and it worked ! Rake now recognizes that I’m trying to add a method to my existing rails model !
June 3rd, 2007 by ahsan
Dreamweaver CS 3 has a facility to rearrange inline styles in a <style> tag. Well, here’s a utility that does the opposite: it converts css in style tags to inline css. Yeah, I hear you. Why would anyone want to do that ?!
Sending HTML Newsletters is a nightmare. Most of the email clients, bar Eudora Light, support css. However, not all properties are supported, and Gmail, one of the major web-based email clients, supports only inline styles.
You need Ruby, and Hpricot installed to run this. Duh, it runs on windows too !
EDIT: fixed a bug & added NOTES
Here’s the code:
#!/bin/env ruby
# style2inline.rb - v0.2
# http://tech.bytefull.com
# NOTES:
# CSS must not contain any comments
# the last attribute-value pair must end in a semi-colon, example:
# a {font-family: Verdana; font-size: 18pt;}
# uncomment this if you have hpricot installed as a gem
# require 'rubygems'
require 'hpricot'
def style_to_inline(filename)
doc = open(filename) {|f| Hpricot(f)}
css = ""
elems = doc.search('head/style')
# combine the content of all style tags
elems.map {|x| css << x.inner_html}
# remove the style tags - we don't need them in our output doc
elems.remove
# collapse all newlines
css.gsub!("\n", " ")
# Regexp by Nick Franceschina
# http://regexlib.com/REDetails.aspx?regexp_id=916
dec_block = '((\s*([^,{]+)\s*,?\s*)*?){((\s*([^:]+)\s*:\s*([^;]+?)\s*;\s*)*?)}'
regexp = Regexp.new(dec_block, Regexp::IGNORECASE)
results = css.scan(regexp)
results.each do |res|
res[0].split(',').each do |css_sel|
doc.search(css_sel.strip).each do |elem|
if elem.elem? # added in version 0.2,
# to avoid operating on a Hpricot::Text element
if elem[:style] then
# append to the existing style information
elem[:style] = elem[:style] + res[3]
else
# add a style attribute
elem[:style] = res[3]
end
# we don't need the class attribute
elem.remove_attribute(:class)
end
end
end
end
# output
File.open("s2i_#{filename}", 'w') {|file| file.write(doc) }
end
ARGV.each {|x| style_to_inline(x)}
Invoke it with ruby style2inline.rb [FILENAME], and it will output a file of the same name prepended with ’s2i’, e.g s2i-filename.html.