IE Web Developer Toolbar?

Posted by Brian in Accessibility, Browsers, web (April 24th, 2007)

There’s a toolbar for Internet Explorer that has many of the same features as Firebug for Firefox.
Visit http://www.microsoft.com/downloads/details.aspx?familyid=e59c3964-672d-4511-bb3e-2d5e1db91038&displaylang=en to get a copy of the current beta.

To launch it, start IE7 and go to Tools -> Toolbars -> Explorer Bar -> IE DOM explorer.

You can inspect the DOM, the HTML elements, the CSS, and much more. It’s great to have this available!

Updating Multiple Fields in Rails

Posted by Brian in Rails, snacks (April 23rd, 2007)

Just a quick one today…. I always have to look this one up.

Let’s say you have a guestbook and you want to approve multiple entries quickly. Rails has a built-in method for handling that, although it’s poorly documented.

Assuming your model “Entry” has an “approved” attribute that maps to a boolean field in the database, you might make a form like this:


<% form_tag :action=>"approve" do %>

<% @entries.each do |@entry| %>

Posted at<%=@entry.created_at %> by
<%=@entry.email %>

<%=h(@entry.body) %>

Approved? <%=check_box "@entry[]", "approved" %>

<% end %>

<%= submit_tag "Moderate Entries" %>
<% end %>

The key here is that you’re iterating over the items in the collection and using an instance variable to hold each one (@entry). Normally, a check_box helper looks like this:


<%=check_box "entry", "approved" %>

If you use the check_box helper with an array as the first parameter, you can create an array of entries that can all be sent to the back-end.


<%=check_box "entry[]", "approved" %>

Rails puts the primary key of the entry inside of the square-brackets, thus causing them to group nicely.

Your params hash will look like this:


{
"commit"=>"Moderate Selected Entries",
"action"=>"moderate",
"entry"=>{
"1"=>{"approved"=>"1"},
"2"=>{"approved"=>"1"}
},
"controller"=>"guestbook"
}

That’s the hard part. The action that receives the POST request looks like this


def moderate
Entry.update(params[:entry].keys, params[:entry].values)
flash[:notice] = "Successfully modified the approval flags for all records."
redirect_to :action=>"index"
end

Yeah, you read that right… no looping. The “update” class method on an ActiveRecord object can take either an ID or an array of IDs as the first parameter, and a hash of names and values or an array of hashes containing names and values for the second parameter. Since the form made the record ids as the keys in the hash, calling params[:entry].keys gives us the array of IDs we need for the first parameter. params[:entry].values gives us an array of the hashes we need for the second parameter.

Now, you can use this technique to do some simple mass-update pages if you needed to, but then it gets a little trickier.

I hope someone out there finds this useful.

Is XHTML bad for you?

Posted by Brian in Accessibility, Browsers, News, web (April 17th, 2007)

What do you do when you are confronted with the possibility that everything you know is wrong, or that you’re doing things not because they’re good, but because everyone else is doing it?

It seems that there are issues with using XHTML instead of HTML, and I think this is something that any web developer needs to investigate further.

From the article:

If you’re a web developer, you’ve probably heard about XHTML, the markup language developed in 1999 to implement HTML as an XML format. Most people who use and promote XHTML do so because they think it’s the newest and hottest thing, and they may have heard of some (usually false) benefits here and there. But there is a lot more to it than you may realize, and if you’re using it on your website, even if it validates, you are probably using it incorrectly.

This website uses XHTML 1.0 Transitional, apparently incorrectly.

All links open in a new window.

Other links:

Unit testing

Posted by Brian in Rails, snacks (April 3rd, 2007)

Rails developers typically do test-driven development, so they’re writing their unit tests before they write their business rules. For example, if I was to write a keyword search method, I’d write a unit test first.

# Should find 2 because I have “red” in the test data in 2 records
assert_equal(2, Document.find_by_keywords(“red”)

# should find 0 because that term isn’t in any of the records
assert_equal(2, Document.find_by_keywords(“blue”)

# should find 2 because the word “ninja” is found on one document
# and ‘pirate’ is found in another.
assert_equal(2, Document.find_by_keywords(“ninja pirate”)

The test that I wrote gives me a clear indication of the requirement I have to implement. When these tests (and more) all pass, I know that I have my search engine finished. I don’t need to continously try various examples manually to see if I am done. It takes a lot of the manual testing away, but it also gives me more confidence that my code does what I think it does.

The hardest part about testing is learning to do it first. It takes much longer to write tests after you already have a working application, and it feels pointless. (It’s really not, but it just feels that way when you’re doing it which can be really demotivating.)

Associations and caching

Posted by Brian in Rails, snacks (April 2nd, 2007)

Sometimes I just do dumb things when I write code. The way I look at it, every mistake I make is a chance to learn something new.

I’ve got a system with workshops, presenters, enrollments, and more. It’s a fairly complex system that has a lot of relationships. If you peek into my User model, you’ll see some things like this:


class User < ActiveRecord::Base has_many :presenterships has_many :troubleshooterships has_many :enrollments has_many :presentations, :through=>:presenterships, :source=>:workshop
has_many :troubleshoots, :through=>:troubleshooterships, :source=>:workshop
has_many :workshops, :through=>:enrollments
end

....
end

This post Turn finders into associations and get caching for free got me thinking about my code a bit so I decided to take a second look. When I did, I saw this method:


#Returns all of the workshops for which this user is enrolled.
def workshops_enrolled
@workshops = Workshop.find :all, :include=>[:offering, :enrollments],
:conditions=>["enrollments.user_id = ? and enrollments.withdrew = ?", self.id, false]
end

I added this method because I wanted to make sure I only showed associations where the user did not withdraw. (I’m recording withdrawls from a workshop instead of removing the association between the user and the workshop.)

Darn it… that’s just not right. While that works, I lose the ability to cache, and it’s also exactly what an association is for. Refactored, it now looks like this:


has_many :workshops_enrolled, :source=>:workshop, :include=>[:offering, :enrollments],
:through => :enrollments, :conditions=>["enrollments.withdrew = ?", false]

Since it’s a has_many :through, it needs to have the :source option defined so Rails knows what the parent class is.

Fun stuff, this Rails.