Thursday, May 14, 2009

Scopes for conditions


It is common for your named and anonymous scopes to only specify the :conditions option. In RailsCast #112, Ryan Bates suggests adding a conditions named_scope:


This allows you to replace:
active_people = People.scoped(:conditions => {:active => true})
with:
active_people = People.conditions(:active => true)

A step further

This can be taken a step further by adding a class method, named_conditions, to ActiveRecord::Base:


Now you can replace:
class Post
named_scope :recent, lambda { {:conditions => ['created_at > ?', 1.day.ago] } }
end
with:
class Post
named_conditions :recent, lambda { ['created_at > ?', 1.day.ago] }
end

Not very exciting, but it's the little things that count. You can download the module at http://gist.github.com/111783.

Thursday, April 16, 2009

A Foreign Key migration plugin for Rails


I use foreign keys in my Rails projects, and they work great. There was a point in time where Rails tests did not work well when using foreign keys, but those days are long gone. I've been hand rolling foreign key migrations for quite some time, and decided to write a plugin that covers most of my needs. This resulted in Foreigner, which is now available at http://github.com/matthuhiggins/foreigner/tree/master.

One of my goals was to follow the API for add_index and remove_index. Another goal was to make sure migrations did not break when run against adapters that do not support foreign keys. The API simply no-ops by default, and only supported adapters perform the operation. (MySql is currently the only implemented adapter.)

You should be able to add most of your foreign keys with following (See the Readme for more details.)

add_foreign_key(:comments, :posts)
If you drank the Rails lemonade and don't think foreign keys are necessary, you're correct. They're not necessary, they are a nice to have.

Saturday, March 21, 2009

A Survey of URL Sharing Debris


As a loyal follower of Tufte, I believe in removing all unnecessary junk and debris from the visual design of a website. (The layout for this blog is a preselected template from Blogger; don't hold it against me). I'm going to point out a trend I'm noticing everywhere, and you will either start being irritated by it, or disagree with me. I call it URL Sharing Debris, and it is best described with examples. I surfed to random websites to collect a few samples.


huffingtonpost.com


Here's your classic example. Since it's too hard to copy and paste a URL, the user is provided with approximately 8-10 icons to share the URL.


indecisionforever.com


At least they realize the icons detract from the content and gray them out.


www.dailymail.co.uk


Since most users won't know what the icons mean, this example adds labels.


youtube.com


More space is wasted on the sharing section than on the video control. Am I the only one who knows how to copy and paste the URL displayed in my browser?


failblog.org


Finally, a site that makes fun of the sharing links.


scm.jadeferret.com


In my quest to find the worst offender, I came across the above winner.


Final words

I think a lot of site developers responsible for this are simply copying popular sites who started this trend. Putting a Digg button on your site does not make it popular. It needs to be popular in the first place.

It is difficult to fit content on a page. It is difficult to design clean aesthetics. I believe this fad will eventually die, and join the graveyard with webrings.


Wednesday, March 18, 2009

5 new CSS features you can use if you drop IE6


It is time for most sites to drop IE6, especially for projects that are just getting started. If you do make this choice, it is important to realize that there are some new CSS features that you can begin using, and some old habits worth dropping. While there are many sites that describe CSS bugs in IE6, I found no websites that describe working examples to improve your CSS and HTML if you simply drop support for it.

Here are 5 examples from my own project, Haiku Village.

1. Attribute Selectors

You can use attribute selectors for any arbitrary attribute, but I have used it exclusively for form elements.

<style>
input[type="submit"] {
margin-top: 5px;
}
</style>

<input type="submit" value="Save" />
This will help you delete those arbitrary class names you made up to select certain types of inputs.


2. Multiple Classes on a Single Element

This is best described with an example:

<style>
.icon {
background: transparent url(/images/icons.png) no-repeat scroll 0 0;
padding: 2px 0 0 20px;
}

.icon.trash {
background-position: 0 -80px;
}
</style>

<span class="icon trash">Delete</span>
With IE6, you either needed to make a class name of "icon-delete", or nest one element inside of the other.


3. Sibling Selectors

There are many ways to use sibling selectors. My most recent use of them is to add borders between the list items in a sub menu:

<style>
ul.menu li + li {
border-left: 1px dotted #DADADA;
padding-left: 8px;
}
</style>
Normally, you would need to introduce a "first" or "last" class name to make the borders only appear between items, and not on the outside.


3. Child Selectors

If you know that a certain style should only apply immediately within an element, then simply insert a ">" into your stylesheets:

<style>
ul.menu > li {
float: left;
margin-right: 7px;
padding: 3px 0 1px;
}
</style>
This will ensure that other list items within this list item do not receive the style. It also prevents the necessity to define a new class name, such as "menu-item"


4. Use :hover on any element

I started web development in 1995, and until recently, I never considered using the :hover meta selector for anything besides the "a" tag. Remove this from your mind, because it is no longer the case. I use :hover to expose some icons when you mouse over a haiku:

<style>
.haiku .actions {
visibility: hidden;
}

.haiku:hover .actions
:visibility visible
}
</style>
Most of us have probably worked around this by either introducing an arbitrary "a" element with an "href='#'", or by adding a class name during a 'mouseover' event.

5. New properties available

There are plenty of new properties that you can start using. The most significant are:
  • min-width/min-height
  • max-width/max-height
  • background-attachment - You can use a value of 'fixed'

There are hacks to make all of these work in IE6, but that's the point: You should stop the hacking. Also, did I mention transparent PNGs?


Sunday, January 18, 2009

A matter of style...


I've seen plenty of code examples that show how to set the current user or subdomain to a variable. For example:


1
2
3
4
5
6
7
8
class ProfileController < ActionController::Base
before_filter :set_current_user

private
def set_current_user
@current_user = User.find_by_username(session[:username]) if session[:username]
end
end


However, I prefer this way:


1
2
3
4
5
6
7
class ProfileController < ActionController::Base
private
def current_user
@current_user ||= User.find_by_username(session[:username]) if session[:username]
end
helper_method :current_user
end


With this technique, I always use the current_user method to determine the current user, and never reference the @current_user variable. If an action doesn't need to know the current_user, no time is wasted to set it.

Wednesday, November 26, 2008

I killed ApplicationController


For the longest time, developers have asked for application.rb to be renamed to application_controller.rb. This is finally fixed in RailsEdge, and there's even a Death of Application.rb blog posting about it.

That's great, but none of this affects me. Why? Because ApplicationController always annoyed me, so I killed it.


Life without ApplicationController

You might ask, "how do you survive without this loving, parental figure; the ApplicationController?" Because my parent is ActionController::Base, in the same way that most of your models inherit from ActiveRecord::Base. Can you tell me why your models don't inherit from an arbitrary ApplicationRecord class?

The primary reason why a developer puts code into ApplicationController is for code reuse and changing default behavior. The ultimate result is that this class becomes a dumping ground for any common methods required across two or more controllers. Ruby has a better pattern for reusing methods and changing behavior across classes: Modules.

I create my own controller modules in the lib folder, and include them into ActionController::Base. If I want only certain controllers to be affected, the module defines a class level method, similar to the before_filter and has_many macros. For example, some controllers require a login. Rather than adding a filter to ApplicationController, I would make a 'require_login' module. My controllers could optionally use it like this:



1
2
3
class PostController < ActionController::Base
require_login
end


Why do I go through all this trouble? Because it (1) cuts one layer out of the inheritance tree, and (2) forces me to think about packaging functionality into small, testable modules. I encourage you to look at the code in your ApplicationController, and question whether any or all of your controllers should be inheriting from it.

Friday, November 21, 2008

I am not dead


To the dedicated numbers subscribing to my blog: I'd like to notify everyone that I still exist. I just awakened from a temporary, semi-comatose state. Thankfully, I have numerous blog posts queued in my non-volatile persistence mechanism.

Please stand by for tips in perfectionism with HTTP, SQL and Ruby on Rails.