Enough with the Flash Already

It often bothers me when Flash is being misused for small visual effects on home pages of websites. Not just that it slows things down, but it also usually breaks these websites terribly when I want to copy&paste stuff or when one doesn’t have the Flash plugin installed.

Margarete, has recently bugged me quite a bit about making the front page of her website a bit more “visual”. She started with an idea of adding some flash to her website, which I dismissed quickly.

Fortunately I was able to come up with a neat little CSS code, which is way better than Flash for what she was trying to achieve. Don’t be mistaken, I didn’t even need JavaScript to do all the subtle movements and eager image loading, it’s all pure CSS.

The front page:

A small “visual” effect when one mouses over the “Blog” element:

I still plan to enhance the code a bit more to make it faster to load by decreasing the number of HTTP requests needed to load the asset files as well as size of the images, but I’m quite happy with what it looks and feels like already. Check out the live version at www.fgslovakia.com.

A good technical article describing a technique very similar to the one that I used can be found the A List Apart website.

#116 Selenium

Selenium is a great way to test your app automatically through a browser. See how it works in this episode.

#116 Selenium

Selenium is a great way to test your app automatically through a browser. See how it works in this episode.

BTrace == DTrace for Java

Last week, I was trying to nail down a bug in SunWikis that was triggered by some kind of race condition. These kinds of issues are pretty nasty, especially if the application in question is a pretty complex beast, something that Confluence definitely qualifies as.

The debugger was no help because the timing had to be very precise for the issue to occur, and logging was totally useless because of zillions lines of logs that would be difficult to safely filter out. In many cases the information I needed was not present in logs anyway and since my guess was that the bug was coming from 3rd party code, logged data couldn’t be easily expanded. DTrace, which I blogged about in my previous post, could have revealed some information, but I think that it would be very difficult to write a good D script that could give me some clues.

While waiting for my dev server to restart, I came across an interesting blog post that caught my eye. It mentioned this thing called BTrace, that I hadn’t heard about before. It promised it to be a DTrace aimed at Java apps. With a fair amount of skepticism, I navigated to the BTrace website and started reading. Four things about BTrace earned my interest:

  • It’s based on same or very similar principals as DTrace, but specialized for Java apps
  • No restarts necessary, you can observe a running app by connecting to a JVM identified by a PID
  • The BTrace programs are written in a language that is a subset of Java, and heavily based on annotations. This was a bit of a turnoff for me at first, until I found out that the programs don’t need to be compiled manually but btrace takes care of that for me. Bravo!
  • I can call DTrace from my BTrace programs if I need to instrument native code or the OS

Armed with all this info and my eyes sparking, I wrote my first BTrace program and it worked as advertised! No restarts, no compilation, no hassle.

A few hours later, I had a program that was observing exactly those parts of Confluence that I needed. All of this while the application was running uninterrupted. I was able to snoop on how my code was interacting with Confluence and Confluence was in turn interacting with Hibernate in a way that I would have never dreamed of. All of this while concurrent events aimed at triggering the bug were happening.

Running BTrace programs is as easy as this:


$ ./bin/btrace \
-classpath hibernate-2.1.8-atlassian.jar:spring-hibernate2-2.0.6.jar \
6266 HibernateSessions.java

Where 6266 is the PID of my app/web server and HibernateSessions.java is my BTrace program.

Parts of the program looks like this (check out the javadoc comments for explanation of the code):


import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.collection.PersistentCollection;
import net.sf.hibernate.engine.SessionImplementor;
import org.springframework.orm.hibernate.support.OpenSessionInViewFilter;

@BTrace
public class HibernateSessions {
/**
* A thread local variable used to filter out all the events that we
* are not interested it.
*/
@TLS private static boolean viaSso = false;
private static boolean printStack = false;

/** print a message when a thread enters doFilter method of SsoFilter */
@OnMethod(
clazz="com.sun.dse.wikis.auth.SsoFilter",
method="doFilter"
)
public static void enableProbing() {
println(str(currentThread(), " - Entered SSO Filter"));
viaSso = true;
}

/** print a message when exiting the doFilter method of SsoFilter */
@OnMethod(
clazz="com.sun.dse.wikis.auth.SsoFilter",
method="doFilter",
location=@Location(Kind.RETURN)
)
public static void disableProbing() {
println(str(currentThread(), " - Exited SSO Filter"));
viaSso = false;
}

/**
* print an message with a HibernateException is thrown, with detailed
* info about the current context
*/
@OnMethod(
clazz="net.sf.hibernate.HibernateException",
method=""
)
public static void onthrowreturn(HibernateException self, String s) {
println(str(currentThread(),
strcat(" - HibernateException was thrown: ",
strcat(s, strcat(" | collection: ", str(collection))))));
}

/**
* Print a message when Hibernate is attaching a collection to a session.
* This was crucial info for me to get in order to resolve the issue
*/
@OnMethod(
clazz="net.sf.hibernate.collection.PersistentCollection",
method="setCurrentSession",
location = @Location(Kind.RETURN)
)
public static void setSessionForCollection(boolean returnValue) {
if (returnValue == true) {
println(str(currentThread(),
strcat(" - a collection was attached to a session. Collection:",
str(collection))));
}
}

The result of this was a workaround for my code as well as a pretty detailed bug report that Atlassian confirmed to be a very similar to a confirmed bug that was reported recently. I could hardly achieve this without BTrace or without an in-depth knowledge of how all the Confluence code works.

As great as BTrace is, it is still a beta. If you decide to use it in production environment you should keep that in mind. During the several hours I spent working with BTrace, I experienced one JVM crash/lockup caused by BTrace. I bet that this kind of issues will be ironed out soon, and often this kind of risk is worth undertaking in order to resolve otherwise untraceable bugs.

Since last week, BTrace is part of my toolkit and I already have other mysteries on my ToDo list that I want to shine some light on with BTrace. I applaud the BTrace team for giving us this amazing tool!

DTrace and Java – Observations and Docs

For a long time I’ve been hearing about DTrace and how cool it was. I read a lot about it and saw some presentation on observing Java apps with DTrace, but only recently have I found enough free time to extensively play with it. And oh boy, it really is cool. But even with all this coolness, dtracing Java apps feels a bit awkward.

I think there are two reasons for that. The D language, which looks like C, but has a few fundamental differences, is pretty far from what Java developers are used to. And the second reason is the fact that DTrace is in reality instrumenting JVM and not the application running in the JVM. This means that dtracing Java is limited by abilities of the Java DTrace provider and also that the transition between the different layers of the stack can add some awkwardness.

Having said that, DTrace is really awesome and can be enormously helpful in many cases when developing or troubleshooting (Java) apps.

One thing I really miss in DTrace is regex support in any part of D scripts. There is a limited globbing support and some workarounds, but they ain’t pretty.

Here are some DTrace resources that I found useful:

The Best of Cheat

There’s some real gold in Cheat. Like, nuggets. Ever since we got tagged by mustache it’s been just wild.

Ever wonder how to make hot chocolate? We’ve got a tasty recipe.

Need some night time reading to go along with your cocoa? May I suggest Into the Code?

The DataMapper sheet is superb in its brevity: has_many :class => “ClassName”

(By the way, this post has been highly optimized with the SEO sheet.)

The Foo sheet is the foo sheet is the foo sheet.

Hot chocolate not hitting the spot? How about some Gazpacho soup?

If you’re a designer, you’ll love this: lipsum. All of it.

Ever wanted to talk like you’re in the military, or own a walkie talkie? Now you can with this handy military alphabet.

Oh, an entire Cheat Emacs mode. Remember: Never quit Emacs.

I’m sure you’ve been wondering, so here it is: every TLD ever.

In the spirit of three letter acronyms, there’s also the GTD sheet.

One of my favorites, the Runescape sheet:

Hot keys

1 selling
2 buing
3 buy
4 noob

For the serious kids in the room, there’s the Unix permissions and Unix redirection sheets. Oh, and the notify trick then the complete Firebug sheet.

Finally, the nonsense sheet imparts on us some non-nonsense wisdom: “and that’s why cheat also is an anagram for teach!”

#115 Caching in Rails 2.1

Rails 2.1 brings some new caching features which makes it very easy to cache any values including models. See how in this episode.

#115 Caching in Rails 2.1

Rails 2.1 brings some new caching features which makes it very easy to cache any values including models. See how in this episode.

Extra geeky: the recursive lambda

I’m not sure where I first heard that you could do a recursive lamdba in Ruby, but it’s been simmering on the back burner of my brain for a while. I’ve just never had a reason to use one, until now…

I wanted to process the Rails request params, which is a hash of strings and hashes of strings and hashes of strings and hashes… you get the idea. The need was to strip all the accent marks from user input throughout the application. Here’s what I came up with:

class ApplicationController < ActionController::Base
  before_filter :strip_accents

  protected
  def strip_accents
    thunk = lambda do |key,value|
      case value
        when String then value.remove_accents!
        when Hash   then value.each(&thunk)
      end
    end
    params.each(&thunk)
  end
end

That’s all completely clear, right? The filter enumerates the top-level hash using the &/to_proc operator to coerce the lambda to a block for the #each method. #each passes the key and value to the lambda, which either removes the accents from a string, or recursively enumerates the contents of a nested hash.

I think it’s totally cool that you can do this in Ruby. Everyone thinks that Ruby is just an object-oriented language, but I like to think of it as the love-child of Smalltalk and LISP (with Miss Perl as the nanny).

[PLUGIN RELEASE] ActsAsSeoFriendly


ActsAsSeoFriendly

== DESCRIPTION:

Create an SEO friendly field for a model automatically based on a given field.

So if you have a Blogs model, and you would like create an SEO friendly version
of the ‘title’ field, you would just add this to your model and then be able to
use the SEO friendly id as the unique id to the resource. The plugin will only
append an integer to the SEO id if there is a collision.


== SYNOPSIS:

Create seo column migration:


class CreateSeoTestModels < ActiveRecord::Migration
def self.up
create_table :seo_test_models do |t|
t.string :name
t.timestamps
end
SeoTestModel.create_seo_friendly_column()
end

def self.down
SeoTestModel.drop_seo_friendly_column()
drop_table :seo_test_models
end
end

Add to model:


class SeoTestModel < ActiveRecord::Base
acts_as_seo_friendly :resource_id => :name,
:seo_friendly_id_field => :seo_id, # default is :seo_friendly_id
:seo_friendly_id_limit => 100 # default is 50
end

To lookup the resource in the controllers use:


SeoTestModel.find_by_seo_id(params[:id])

== INSTALL:

sudo gem install

Continue reading “[PLUGIN RELEASE] ActsAsSeoFriendly”

[PLUGIN RELEASE] ActsAsSeoFriendly


ActsAsSeoFriendly

== DESCRIPTION:

Create an SEO friendly field for a model automatically based on a given field.

So if you have a Blogs model, and you would like create an SEO friendly version
of the ‘title’ field, you would just add this to your model and then be able to
use the SEO friendly id as the unique id to the resource. The plugin will only
append an integer to the SEO id if there is a collision.


== SYNOPSIS:

Create seo column migration:


class CreateSeoTestModels < ActiveRecord::Migration
def self.up
create_table :seo_test_models do |t|
t.string :name
t.timestamps
end
SeoTestModel.create_seo_friendly_column()
end

def self.down
SeoTestModel.drop_seo_friendly_column()
drop_table :seo_test_models
end
end

Add to model:


class SeoTestModel < ActiveRecord::Base
acts_as_seo_friendly :resource_id => :name,
:seo_friendly_id_field => :seo_id, # default is :seo_friendly_id
:seo_friendly_id_limit => 100 # default is 50
end

To lookup the resource in the controllers use:


SeoTestModel.find_by_seo_id(params[:id])

== INSTALL:

sudo gem install revolutionhealth-acts_as_seo_friendly -s http://gems.github.com

== SOURCE:

http://github.com/revolutionhealth/acts_as_seo_friendly/tree/master

To see the plugin in action see our recipes section, for example:

http://www.revolutionhealth.com/recipes/thai-miang-khem-style-salad

== FEATURES/PROBLEMS:

* Only tested on mysql and sqlite3

Compassionate Communications. A different kind of Rails application.

I have been working with Sean and Lee on Compassionate Communications a Ruby on Rails website. My role was small thanks to the ActiveMerchant plugin, I helped with the online payment but my part was done in no time. The site launched just before Rails Conference and I wanted to write about what the site is. It’s about giving, reaching out, helping…but I didn’t find the right words to describe it. The team at Compassionate Communications made the following video that captures the essence of what they want to achieve way better I could describe..so go check it out.

#114 Endless Page

Ever wondered how some sites seem to have endless scrolling page with no pagination? Find out how easy it is to do this in Rails in this episode.

#114 Endless Page

Ever wondered how some sites seem to have endless scrolling page with no pagination? Find out how easy it is to do this in Rails in this episode.

Advanced Rails Studio: Day 3

We are onto the 3rd day of the training, and the guys are still kicking. We are now onto Asynchronous processing. That’s good as I needed to catch up on what’s out there. I didn’t know about Starling. A light-weight queue server, might be a better solution than the heavier BackgroundRb based on the scenario you need to address. Any of you using Starling? Chad now goes into creating a plugin…ReviewableFu! Now onto debugging. And Caching.

Thanks guys awesome training, you covered tons of good material. Again, really worthwhile if you want to go to the next level with Rails.

Running mod_rails on Leopard (OSX 10.5)

From the command line:

gem install passenger
sudo passenger-install-apache2-module

The Apache 2 module was successfully installed.

Please edit your Apache configuration file, and add these lines:
LoadModule passenger_module /Library/Ruby/Gems/1.8/gems/passenger-1.0.5/ext/apache2/mod_passenger.so
RailsSpawnServer /Library/Ruby/Gems/1.8/gems/passenger-1.0.5/bin/passenger-spawn-server
RailsRuby /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
Hey…where is the configuration. Google told me to read this blog entry: http://www.fuzzylizard.com/archives/2008/05/29/947/

So copy these three lines and add them to the end of this file: /etc/apache2/httpd.conf

$ sudo mate /etc/apache2/httpd.conf

Start and stop Apache go the to the System Preferences|Sharing and select the Web Sharing service:

20080616_syspref.jpg

Then the install script gives you the following instructions.

Deploying a Ruby on Rails application: an example

Suppose you have a Ruby on Rails application in /somewhere. Add a virtual host
to your Apache configuration file, and set its DocumentRoot to
/somewhere/public, like this:
<VirtualHost *:80>
ServerName www.yourhost.com
DocumentRoot /somewhere/public

And that’s it! You may also want to check the Users Guide for security and
optimization tips and other useful information:
/Library/Ruby/Gems/1.8/gems/passenger-1.0.5/doc/Users guide.html
Enjoy Passenger, a product of Phusion (www.phusion.nl) 🙂
http://www.modrails.com/

Now where is “my” apache configuration file? And more important where is yours? On the command line do

$ ls /etc/apache2/users/

And I see daniel.conf, so let’s edit that one. I am developing one Rails app in this folder: /Users/daniel/SvnProjects/for/stockportfolio/rails. So let’s define this application in that conf file:

$ sudo mate /etc/apache2/users/daniel.conf

<Directory “/Users/daniel/SvnProjects/for/stockportfolio/rails/”>
Order allow,deny
Allow from all

<VirtualHost *:80>
ServerName dev.stockportfolio.com
DocumentRoot /Users/daniel/SvnProjects/for/stockportfolio/rails/public


Note the /public at the end of the folder in the DocumentRoot.
Now I am adding dev.stockportfolio.com in my /etc/hosts file. So just add the following line

127.0.0.1 dev.stockportfolio.com

Now go back to the system preference sharing tab and restart the web service. Now you have your application running … in production mode. Just point your browser to dev.stockportfolio.com.

Enjoy Daniel!

Advanced Rails Studio: Meta Programming

Chad is giving a very nice presentation walking us through meta programming step by step. You can see the code examples we are creating during his talk, but just looking at the code will note give the whole picture.

At the Advanced Rails Studio in Denver

We are just starting Day 2. Mike Clark and Chad Fowler are giving the training and are really good at it. They are 24 people taking the training, most not from Denver, and one from Mexico. Right now attendees are not awake and Mike and Chad are trying to wake us up. Yesterday we covered routes, looked at the Rails and Mongrel source code, looked at a RESTful application, covered ActiveResource, and checked ActiveRecord Associations. It’s nice to be able to sit back and take time to play with all these goodies without having to deliver code. It’s a nice refresher for me. Next step will be meta programming.

Here are some notes from the ActiveRecord Associations part of the training:

Join Model: has_many :through

Polymorphic Associations: has_many :address, :as => :addressable

Custom Finders:

class User
has_many :visits do
def recent(limiit – 5)
find(:all, :order => ‘created_at DESC’, :limit => 5)
end
end

Active Record Scoping:

with_scope # protected now

before_filter :find_account

Scoped Relationships:

@event.registations.find(params[:id])
@user.events.find_by_id(params[:id])
@event.registations.find(:all, :conditions => “pre_register is true”)

Named Associations:

class Event < ActiveRecord::Base
has_many :registrations
has_many :pre_registrations,
:class_name => “Registration”,
:conditions => “pre_register is true”
end

@event.pre_registrations

Named Scope:

class Coupon < ActiveRecord::Base
named_scope :limit_not_exceeded, :conditions => “use_count < max_uses”
named_scope :usable_in_store, :conditions => “external_only is false”
end

Coupon.limit_not_exceeded
Coupon.usable_in_store
Coupon.limit_not_exceeded.usable_in_store

Dynamic Named Scope:

class Coupon < ActiveRecord::Base
named_scope :not_expired, lambda { { :conditions => [‘expires_at > ?’, Time.now] } }
named_scope :used_at_most, lambda { |uses| { :conditions => [‘use_count <= ?’, uses] } }
end

Coupon.not_expired
Coupon.used_at_most(30)
Coupon.not_expired.used_at_most(10)

Advanced Rails Studio: Custom Form Builder

Custom Form Builder

Use a custom form builder to clean up your html.erb files.

class LabelFormBuilder < ActionView::Helpers::FormBuilder
helpers = field_helpers +
%w{date_select datetime_select time_select} +
%w{collection_select select country_select time_zone_select} –
%w{hidden_field label fields_for} # Don’t decorate these
helpers.each do |name|
define_method(name) do |field, *args|
options = args.last.is_a?(Hash) ? args.pop : {}
label = label(field, options[:label], :class => options[:label_clas])
@template.content_tag(:p, label +’
’ + super) #wrap with a paragraph
end
end
end

Then you can remove all the <p> and label tags from you form.

Editing user

<% form_for(@user, :builder => LabelFormBuilder) do |f| >
<
= f.error_messages >
<
= f.text_field :name >
<
= f.text_field :address >
<
= f.text_area :comment >
<
= f.check_box :check >
<
= f.submit “Update” >
<
end %>

<%= link_to ‘Show’, @user > |
<
= link_to ‘Back’, users_path %>

Add this to your application initializer to have all form use this form builder

ActionView::Base.default_form_builder = LabelFormBuilder

Then you can replace

<% form_for(@user, :builder => LabelFormBuilder) do |f| %>

with

<% form_for(@user) do |f| %>

Now the same form with no custom builder was looking like this before.

Editing user

<% form_for(@user) do |f| >
<
= f.error_messages %>

<%= f.label :name %>
<%= f.text_field :name %>

<%= f.label :address %>
<%= f.text_field :address %>

<%= f.label :comment %>
<%= f.text_area :comment %>

<%= f.label :check %>
<%= f.check_box :check %>

<%= f.submit “Update” %>

<% end %>

<%= link_to ‘Show’, @user > |
<
= link_to ‘Back’, users_path %>

GitHub and Powerset – Ruby on Rails Podcast

Developers from GitHub and Powerset with a short appearance by photographer James Duncan Davidson.
For even more about GitHub, check out their Gitsplosion! podcast.

Sponsor