Conferencia Rails

Posted by lori, Mon Nov 01 15:54:00 UTC 2010


I'll be speaking at Conferencia Rails this week. Looking forward to meeting some Rails folks from Spain.

Also, I'll finally be releasing one of my pet projects as an open source component on GitHub. Check there this weekend, and let me know what you think.

0 comments | Filed Under: | Tags:

Full outer join pain

Posted by lori, Thu Sep 30 00:00:00 UTC 2010


I was struggling with a custom SQL query I had to write. The "first pass" at this functionality, just using my Rails models and predefined associations came at a cost of M x N queries. I figured I could get that down to 2 queries, which is better, right? Of course, it took me the better part of two days (many interruptions, not conducive to concentration) to get it right.

After a lot of trial and error, I knew that one part of my query involved a full outer join on two of the three tables. This was only required for 2 subsets of data, so it wasn't as huge a performance issue as you might think. The problem was that the two subsets of data I had to join had no common columns.

Sadly, it appears that no one out there who has solved this problem has blogged or written an article about it. Or, if they have, it's hidden in sites like "Experts Exchange" where you have to sign up and/or pay to see the results. So, here is my answer, to this part of the problem that I solved.

Assuming you have table (or subquery) w and another table (or subquery) s, you can do something like this: with w1 as ( select w.*, 1 as match from w ), s1 as ( select s.*, 1 as match from s ) select .... from w1 full outer join s1 on ( w1.match = s1.match )

Note that the ... part is where you have to select all the columns by name, because w1.*, s1.* would result in an ambiguous (and unnecessary) column "match".

I was using Oracle. I know that SQLServer also supports the "with" clause. If you know how to restructure this to work in MySQL, or any other common database, please do reply in the comments for the edification of all. And, of course, if there is some other magical way to accomplish this type of full outer join without my hack, please comment as well.

1 comment | Filed Under: | Tags:

WNDXcasts launch

Posted by lori, Fri Sep 17 09:15:00 UTC 2010

After taking the plunge with the inaugural Year of Hustle Launch Class, I've procrastinated long enough (my problem, not the class) with my own product launch, and am finally announcing the the official launch of WNDXcasts - Mobile Web Development for regular web creators.

So, what's this all about? After being a smart-phone owner throughout the initial phases of the landslide rush to mobile, I know exactly the kinds of problems people experience with visiting websites using their mobile phones. I see those problems personally just about every day. As a developer for many years, and a web developer more recently, I also know exactly what is involved in fixing most of those problems. Some of it is so drop-dead easy that most website/web application creators would be embarrassed to think that they could have improved their customers' experiences so quickly. Other issues just require a little more work, but it's still not that difficult. And, at last we have the problems where you really need to dig in, and rewrite. I aim to teach people how to do all that.

As you probably know, if you follow my blog, I'm not much of a writer. I try, but writing isn't really my thing. So, instead of writing about all this stuff, I'm creating screen-casts. Videos that you can sit down and watch, following along with real examples and real source code, and immediately apply to your own website or web application.

If that sounds like something you'd be interested in, go to my WNDXcasts website now, and sign up. Everyone who signs up early will get extra special discounts when the first of the screen-casts becomes available in October.

0 comments | Filed Under: | Tags:

config.gem 'ruby-ole'

Posted by lori, Tue Jun 22 15:25:00 UTC 2010

This had me screwed up for hours, trying to figure out why the ruby-ole gem was coming up as "not installed" but then it still worked. You need to specify a :lib for it.

config.gem "ruby-ole", :lib => 'ole/file_system', :version => "1.2.10.1"

Gem developers, PLEASE, if there is anything special/nonstandard about using your gem, PLEASE, mention in prominently in the documentation. I don't think that's too much to ask.

0 comments | Filed Under: Ruby & Rails | Tags:

Snow Leopard bites me on the a$$ again

Posted by lori, Thu Dec 03 15:02:00 UTC 2009

Twice, actually.

First, there was the, I think, Ruby 1.8.7 upgrade. Suddenly, my home-grown acts_as_my_thing plugin stops working. The classes with "acts_as_my_thing" crash and burn when loading, saying that "acts_as_my_thing" doesn't exist. Crap. Now what?

Eventually I managed to find the proper incantation. I have an abstract super class for a bunch of my models. It's called LabRecord. In the file that defines my "acts_as_my_thing", I had:
LabRecord.class_eval do include Lti::Acts::MyThing end

I think there is a class-loading chicken-and-egg problem going on, so after trying a bunch of stuff like moving around "requires" in the environment.rb file, I eventually decided that I was "doin it rong", and did this instead:
class LabRecord < ActiveRecord::Base include Lti::Acts::MyThing ...

But, that wasn't the end of my day. I did say twice, didn't I? A little while later I was diddling around with svn in my Rails project, and then BOOM. 3rdRail/Subclipse couldn't read my workspace anymore:
Unsupported working copy format svn: This client is too old to work with working copy '/Users/lori/Documents/workspaces/labrador/dev2'. You need to get a newer Subversion client, or to downgrade this working copy. See http://subversion.tigris.org/faq.html#working-copy-format-change for details. I'm too tired for this shit. Sigh. At least if you follow the link, you can download the Python script which will convert your Subversion workspace back to 1.5 (Snow Leopard has SVN 1.6), and get back to it.

0 comments | Filed Under: Ruby & Rails | Tags:

Interface Builder hates me - PragProWriMo

Posted by lori, Sun Nov 01 14:30:00 UTC 2009

Since I've already tried the write-a-book thing before, and I know I suck at it, I'm opting for the "blog entry a day" thing... which actually means more like "blog entry a week". I know that sounds bad, but when you consider how often I've been blogging, it's a vast improvement, so...

To get down to it, maybe it's more like I hate Interface Builder... but not really. It's just that I have not yet "become one" with my tool, and we have these little spats from time to time.

I've been fighting with an Array Controller in IB, because it has no bindings listed. If you know IB and Array Controllers, you will know why that is wrong/bad. I can't bind any content into my array, and that's a big problem. I finally noticed that the icon for my bad array controller didn't look like the icon for a different, working array controller. This was a key breakthrough. And I finally figured out what I did wrong. When I added the array controller to my XIB file, I dragged in a plain old Object, and then changed the class to be my custom NoiseArrayController. That was it. What I shoulda done - drag in a generic ArrayController object, and then change IT to be my custom class.

Simple error. Hours of frustration. So, if an Array Controller in your XIB file doesn't have any bindings, maybe you did what I did. You have to get rid of it and start over with the correct base NSArrayController. Then you'll be rockin. Sigh.

0 comments | Filed Under: | Tags:

Pulling out your Mac app version number

Posted by lori, Wed Sep 16 23:14:00 UTC 2009

File this one under useful snippets for Mac Cocoa development. How to extract the application version number out of your app's info.plist file.


[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];

0 comments | Filed Under: | Tags:

Creating application support files on the Mac

Posted by lori, Sat Sep 05 09:04:00 UTC 2009


You are writing a Mac Cocoa application, and you know you want to store your user specific application support files in a predictable location, like ~/Library/Application Support/<Application>/. So... how exactly do we do that?

Once again, Google to the rescue, and we find the answer at Cocoa Dev Central. This will not only construct the file name for you, but it will create the directory if it doesn't exist, too.

- (NSString *) pathForDataFile { 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 

    NSString *folder = @"~/Library/Application Support/MyApplication/"; 
    folder = [folder stringByExpandingTildeInPath]; 

    if ([fileManager fileExistsAtPath: folder] == NO) { 
        [fileManager createDirectoryAtPath:folder attributes: nil]; 
    }

    NSString *fileName = @"MyApplication.mysettings"; 
    return [folder stringByAppendingPathComponent: fileName];
} 

Again, an example that just works. I'm on a roll today.

0 comments | Filed Under: | Tags:

Cocoa Sheets

Posted by lori, Wed Sep 02 15:28:00 UTC 2009

I was struggling with my Photoshop plugin again. The plugin window is modal. But then I need to pop up a modal window, in order to prompt the user for new name/description for the user-saved presets. I was puzzling and Googling, and then I stumbled across a reference to "sheets". Bingo!

This page has the best little example of sheet usage. I was able to copy/paste and then a couple of tweaks, and a couple IB bindings and it all just worked.

- (IBAction)openSheet:(id)sender
{
	[NSApp beginSheet: theSheet
			modalForWindow: theParent
			modalDelegate: self
			didEndSelector: @selector(sheetDidEnd: returnCode: contextInfo:)
			contextInfo:NULL];
}

- (IBAction)theSheetOK:(id)sender
{
	[NSApp endSheet:theSheet returnCode: NSOKButton];
	[theSheet orderOut:nil];
}

- (IBAction)theSheetCancel:(id)sender
{
	[NSApp endSheet:theSheet returnCode: NSCancelButton];
	[theSheet orderOut:nil];
}

- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
	if (returnCode == NSOKButton)
		NSBeep();
}

I really love code examples that just work.

0 comments | Filed Under: | Tags: