Author Archive for Filip Tepper

[Hint] Reading STDERR output in PHP

Recently I was working on a command line PHP script. I know that there are better ways to do things, but I didn’t want to use any other language, since most developers in our company know mainly PHP.

The script exec’s MySQL command to execute a batch of SQL queries. I also wanted the script to mail the error messages. mysql redirects error messages to STDERR - but STDERR is by default not available in exec’s output argument.

Walkaround is simple:

exec('your_command 2>&1');

Works!

[Beta] Webbynode - VPS provider

Back to my tech-blogging, hopefully for good!

This is just a quick note to let you know that there’s new VPS hosting service launching and it requires your input. Webbynode is giving out free beta accounts for Ruby on Rails, Django and PHP (and more!) applications.

I have a couple of drafts one-step-from-being-posted and back from project management to development so expect more updates soon.

[Tool] SQLite Manager

For a couple of months I’ve been developing some Adobe AIR applications - all of them require local SQLite databases. To get the job done I needed an application that would ease SQLite DB management.

After some googling SQLite Manager poped up. It’s a pretty easy yet powerful tool - can be run both a Firefox extension or a stand-alone application (via XULRunner).

My only wish so far - a decent-looking interface.

SQLite Manager

SQLite Manager

[Hint] Discarding non-ASCII characters in Ruby on Rails

My current Ruby on Rails project requires SEO-friendly URL-s. I’ve installed acts_as_slugable plugin, but soon I found out that all my slugs contained Polish characters (in UTF-8). After some googling (Polish Ruby on Rails forum) and some more sips of coffee I came up with some modifications to acts_as_slugable.

Here’s lib/acts_as_slugable_ascii.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 require 'string'
 
module Multiup
  module Acts
    module Slugable
      module InstanceMethods
        private
          def create_slug
            return if self.errors.length > 0
 
            if self[source_column].nil? or self[source_column].empty?
              return
            end
 
            if self[slug_column].to_s.empty?
              test_string = self[source_column]
 
              proposed_slug = test_string.strip.downcase.gsub(/[\'\"\#\$\,\.\!\?\%\@\(\)]+/, '').to_ascii
              proposed_slug = proposed_slug.gsub(/&/, 'and')
              proposed_slug = proposed_slug.gsub(/[\W^-_]+/, '-')
              proposed_slug = proposed_slug.gsub(/\-{2}/, '-')
 
              suffix = ""
              existing = true
              acts_as_slugable_class.transaction do
                while existing != nil
                  existing = acts_as_slugable_class.find(:first, :conditions => ["#{slug_column} = ? and #{slug_scope_condition}",  proposed_slug + suffix])
                  if existing
                    if suffix.empty?
                      suffix = "-0"
                    else
                      suffix.succ!
                    end
                  end
                end
              end         
              self[slug_column] = proposed_slug + suffix
            end
        end
      end
    end
  end
end
 
ActiveRecord::Base.class_eval do
  include Multiup::Acts::Slugable
end

The only difference is the use of to_ascii method.

Now, we need to extend the String class. to_ascii method converts Polish UTF-8 characters to ASCII and discards all unknown characters:

 require 'iconv'
 
class String
  def to_ascii
    ascii = 'acelnoszzACELNOSZZ'
    non_ascii = "\271\346\352\263\361\363\234\277\237"
    to_ascii_string = self
    begin
      result = Iconv.new("CP1250", "UTF-8").iconv(to_ascii_string)
    rescue Iconv::IllegalSequence => e
      failed = e.failed.chars.split(//, 2)
      to_ascii_string = to_ascii_string.gsub(failed[0], '')
    retry
    end
   result.tr!(non_ascii, ascii)
  end
end

And we’re done!

Just add the following line to your model:

 require 'acts_as_slugable_ascii'

and configure acts_as_slugable as instructed in README file. Now you’re ready to face your users.

[Hint] Nice URLs with observe_field

For the last couple of weeks I’ve been working on a small Ruby on Rails application (and learning both Ruby and Rails in the same time). Since everyone’s talking about the one-and-only Rails way, I wanted to make my little app as Rails as possible. That means that you have to write some workarounds to get things done the Rails way.

I wanted to add an onchange event to my collection_select. Normally you would put something like this in your template (that’s what I did after browsing through a couple of tutorial/helps):

<%= collection_select(:story, :license_id, License.find(:all), :id, :name) %>
<%= observe_field('story_license_id', :frequency =>; 0, :update => 'story_license_description', :url => {:controller => 'license', :action => 'description'}, :with => '"id="+value') %>

This code however results in ugly URLs (ie. /license/description?id=1). If you want to keep URLs nice, use the following method:

<%= collection_select(:story, :license_id, License.find(:all), :id, :name) %>
<%= observe_field('story_license_id', :frequency => 0, :update => 'story_license_description', :url => {:controller => 'license', :action => 'description', :id => "'+value+'"}) %>

This way you’ll keep your URLs beatiful throughout your application (ie. /license/description/1).

Oh, and forgive me the Rails way irony.

[Hint] Deploying Ruby on Rails applications on Dreamhost with Capistrano

So, you have a nifty Ruby on Rails application, got yourself a cheap Dreamhost account and you want to give Capistrano a try. And what do you get - errors.

This occurs if you have Ruby gems installed in your home directory (probably ~/.gems/). I’m assuming that you already have your environment configured. Despite that you still can get errors like no file to load -- json when executing cap deploy. That’s because you have your shell configured, but most likely non-interactive environment is left intact.

To fix this you have to modify your .bashrc file (since you probably added GEM_HOME and GEM_PATH to .bash_profile):

export GEM_HOME=$HOME/.gems 
export GEM_PATH=$GEM_HOME:/usr/lib/ruby/gems/1.8

And you’re probably done.

You can also check these articles, they’ve been very helpful:
Deploying Rails (2.0) to Mongrel with Capistrano 2.1
Using Capistrano with Rails
Ruby on Rails - Dreamhost

[Hint] Detecting Firefox 3 in extensions

For a couple of months I’ve been developing a Firefox extension called BlipFox - an interface to Blip, Polish way-better-than-the-original-Twitter-clone. With Firefox 3 coming soon I had to get my extension ready for the final release.

Due to some chrome changes and bugs I had to update some code related to dynamic overlay rendering. Now all I need to know is whether the extensions is installed on Firefox 2 or Firefox 3, hence this snippet of code:

function isFF3()
{
	var foo = Components.classes["@mozilla.org/login-manager;1"];
	return typeof foo === 'function';
}

How do you like? Let me know if there are other methods of detecting Firefox 3 (more elegant, perhaps?).

[Hint] Using Windows keyboard in OS X Leopard

Since sometimes I’m awfully lazy - I got myself a second keyboard, just for the sake of not having to carry one to office and back. At home I use my beloved Apple Keyboard, while at work - a crappy, no-name, ten-bucks-a-piece one (it does it job, though!).

However, since at work I use a Windows keyboard I had a problem with the switched Option / Command keys. I’ve tried DoubleCommand, however I had to click through the System Preferences each time I switched my keyboard. Couple of minutes of googling and a nice script popped out. However, it was useless in OS X Leopard, so I made a couple of quick changes and here’s something I came up with. First, switch-to-windows-keyboard script:

tell application "System Preferences"
	activate
	set current pane to pane "com.apple.preference.keyboard"
end tell
tell application "System Events"
	get properties
	tell process "System Preferences"
		click button "Modifier Keys…" of tab group 1 of window "Keyboard & Mouse"
		click pop up button 2 of sheet 1 of window "Keyboard & Mouse"
		delay 0.3
		click menu item 4 of menu 1 of pop up button 2 of sheet 1 of window "Keyboard & Mouse"
		delay 0.3
		click pop up button 1 of sheet 1 of window "Keyboard & Mouse"
		delay 0.3
		click menu item 3 of menu 1 of pop up button 1 of sheet 1 of window "Keyboard & Mouse"
		delay 0.3
		click button "OK" of sheet 1 of window "Keyboard & Mouse"
	end tell
end tell
tell application "System Preferences"
	quit
end tell

Second, back-to-apple-keyboard script:

tell application "System Preferences"
	activate
	set current pane to pane "com.apple.preference.keyboard"
end tell
tell application "System Events"
	get properties
	tell process "System Preferences"
		click button "Modifier Keys…" of tab group 1 of window "Keyboard & Mouse"
		click button "Restore Defaults" of sheet 1 of window "Keyboard & Mouse"
		click button "OK" of sheet 1 of window "Keyboard & Mouse"
	end tell
end tell
tell application "System Preferences"
	quit
end tell

You might ask why not use Ryan Block’s script? Well, since I rely heavily on QuickSilver I also created two Platypus applications - one for each script. I’m a keyboard user, so I didn’t like the clicking on the Macintosh / PC screen. ;-]

[Release] Fluid’s Google Reader Fix

For quite a few weeks I’ve been using Fluid with Google Reader - having a standalone WebKit based application with dock notification works great for me. However, one thing has been bothering me - Fluid never clears the dock badge when all the items are read. I’ve just posted a little fix for this issue - grab it at http://userscripts.org/scripts/show/23422.

Let me know if this works for you!

[Hint] Pasting content into Ext’s 1.1.1 HtmlEditor

Ext has it’s up and downsides, but is indeed a great framework if you need out-of-the-box set of tools for complex layout development. However we’ve noticed that Ext’s HtmlEditor has problems with content that is pasted into the textarea (we used Firefox 2.0 on both Linux and Windows - never happened on OS X systems). After pasting some HTML the getRawValue method returns a string that doesn’t include the pasted content. This issue only occurs if after pasting the content HtmlEditor’s textarea is not modified - inserting any character (including whitespace) will prevent it.

The workaround is easy - you need to use the method syncValue. An excerpt from Ext’s documentation:

Protected method that will not generally be called directly. Syncs the contents of the editor iframe with the textarea.

Despite it being protected we can call it directly. If you’re facing the problem of missing content then use the following snippet to read data from HtmlEditor:

YourHtmlEditor.syncValue();
var content = YourHtmlEditor.getStylesheet() + "\n" + YourHtmlEditor.getRawValue();

We use it in our webmail module and it works like a charm (finally!).