This is not a drill, please do not be alarmed. Proceed carefully and quickly to the nearest exit, and we will all escape unharmed. If you use a feed reader, please proceed to the specially marked exit for nerds. Thank you for your cooperation.
[If you're feeling a little humor-challenged tonight: this blog is going away, so I'm moving to Blogger. Yes, I am still too lazy to do my own blog hosting.]
I'm writing this from the Portland International Airport, where I'm on standby for the next flight to Dallas / home. β was admitted to the hospital around 3AM CDT today because she was having trouble breathing (she's been battling strep all week). At last report she was doing much better, but she's still under observation. Your thoughts and prayers for her speedy recovery (and my speedy return home) are greatly appreciated. I promise I'll post about last night's roller derby in due time, but right now my brain is a little fried. I hope you'll understand.
I'm writing this from the Portland International Airport, where I'm on standby for the next flight to Dallas / home. Beta was admitted to the hospital around 3AM CDT today because she was having trouble breathing (she's been battling strep all week). At last report she was doing much better, but she's still under observation. Your thoughts and prayers for her speedy recovery (and my speedy return home) are greatly appreciated. I promise I'll post about last night's roller derby in due time, but right now my brain is a little fried. I hope you'll understand.
Morning keynote by Tim Bray. Great talk about where "we" ought to be headed with Ruby and Rails. Tim is proof that age and treachery can still beat youth and enthusiasm -- that makes me feel a lot better.
Another talk about using helpers in Rails to clean up views, this time by Glenn Vanderburg. I guess I felt like the lesson didn't take the first time -- there wasn't too much overlap between this and the Thursday tutorial of nearly the same name, so no wasted time.
Joyent Slingshot -- a super-cool library that allows a Rails app to (with small modifications) run locally on a user's desktop, while still syncing with a remote data source. Wow. Writing a desktop app in Rails sounds like fun, I'll just have to think of a use for it.
Xen and the Art of Rails Deployment -- Ezra Z talked about the Xen virtualization framework, which allows you to turn one server into many "virtual servers." To my shame, I haven't played with this stuff at all, so I was glad for the summary. After seeing this and the Amazon EC2 presentation, I'm more convinced than ever that this is the way provisioning will happen in the very near future (<10 years for sure). I don't kill my own chicken for Sunday dinner anymore, why should I provision my own server?
Practical Design for Developers -- A bit more high level than I was hoping for, but still plenty useful. David Verba from AdaptivePath (the MeasureMap guys) talked briefly about information architecture, and how to design an application that people will actually use. Isn't that what we all want?
Before lunch, attendees were treated to a short performance from the Extra Action Marching Band. I'm from a somewhat funky town, but seeing a marching band complete with a platinum-wigged co-ed flag line reminded me that funky is a very relative term. On a sad note, I had nearly 10 minutes of video showcasing the marching band but managed to corrupt / delete / burninate it while trying to pull it off my camera. Oh well.
A few more pictures from yesterday are flying through the internets towards my photo stream as I type. Thrill to the sight of... a dangerous chain of power strips. I wasn't close enough to get a good shot of Ze Frank last night, but you can hit his site and get the general idea. His discourse on graphic design and airplane safety cards was priceless. I'll try to be more photophilic today (you know what I mean).
No midday update today, as I just didn't find the time to sit down in a quiet place. Bits and pieces:
If you're going to put your company's website name on the back of a truck where it will be glanced at by passerby, it should be something easy to read -- i.e. something other than www.dogsdigit.net. Let's just say I had to read it twice to get it right.
When you're the King of Web Frameworks, you can wear whatever the hell you want to. I spotted DHH this afternoon after his keynote, and he was sporting testarossa red shoes.
Talk 1 this morning was on "Full-stack Web App Testing with Selenium and Rails." Geek out! This is a testing program that actually drives your web browser automatically, which makes it much better than forcing your kids to test your web app out (it doesn't cry or demand toys as payment).
Talk 2 was more of a product pitch, about using Amazon's EC2 service. While it is an incredibly cool service, the "testimonial" did mention a few kinks yet to be worked out. This is probably how we'll do all datacenter stuff in 10 years, and we'll wonder why we ever provisioned our own physical servers.
Talk 3 was from Rabble (I have to call him that because I heard another speaker address him that way in casual conversation) about going back and adding tests to your "legacy" Rails apps. Legacy Rails apps. I feel old already! Basically he talked about how to reform your wayward programming practices and move toward proactive testing.
Talk 4 was probably my favorite, "Standing on the Shoulders of Giants" by Adam Keys. Adam spoke about the value of reading source code written by others, especially code written by the "cool kids" of the Rails community. This is an area I've meant to look into for awhile, but never got around to. No more procrastination! It looked like too much fun to miss.
The last time slot of the day didn't have anything of interest, so I took the MAX into downtown and headed for Mecca, aka Powell's City of Books. I should have set an alarm on my phone or something, but I didn't and so I spent a little over an hour and a half happily browsing the stacks. I almost bought the Bach and Beethoven action figures but couldn't figure out who would want them.
Now tomorrow, you may be in for a real treat: I have been invited to a bout of the local Roller Derby league, the Rose City Rollers. Wait, what? The story of how I got to this point is too long to type, so just hold your breath and wait to see if I actually make it to the derby.
Where are the pictures? Well, I left my USB cable in the hotel room. I'll have to post pix in the morning. You'll just have to let my words paint a picture in your head for now.
If your mom ever tells you you won't accomplish anything sitting on your rear end, tell her you know better. Tanga (think woot with a less rigid schedule and, generally, more interesting products) offered up a challenge on their blog this afternoon: find TangaJoe and get $25 in credit. This evening while I was lounging at the OCC, who should sit down across from me but the wanted man himself. I don't normally go around asking people if they are TangaJoe, so I used the comments section of his blog to see if I had him. Score! Thanks to TangaJoe (and Tanga the company) for being such a good sport. Now I can finally get that Microsoft wireless keyboard and fingerprint reader wait, what? Oh well, maybe tomorrow they'll have something better.
Apparently those symbols on restroom doors aren't as universal as I thought (saw an Asian-looking fellow hurriedly leaving a women's restroom).
I have been surprised by the percentage of females here -- it's gotta be above 10%, and I can't remember another tech conference with anywhere near those numbers.
Oh yeah, the tutorial: Thomas Fuchs admitted that the documentation for scriptaculous "sucks." That was worth the price of admission for me.
I'm currently eating a "Oregon Chicken Breast Sandwich." At the risk of getting in trouble back home... I've never seen a breast like this before.
Someone is recording a podcast... in the main hall. During lunch. They deserve all the background noise they get (and if you hear someone blowing their nose really loudly in the background... yeah, that was me).
I had several good lunch conversations, including one with a fellow whose badge said he was with Real Girls Media Networks. I expected... something else.
The weather in the Pacific Northwest is not at all like the weather in Northwest Arkansas. I probably should have taken this into account when packing.
If you've ever wondered what a sea of nerds might look like... gaze upon the very thing:
Some nasty rumors have appeared on a certain blog regarding my behavior during a recent card game. I won't stoop to comment on what may or may not have happened during the game, but I think the outcome speaks for itself.
Hey, if I'm gonna make a "back to blogging" post, it might as well be about something important...
I've decided to sell the FJ. It's a great bike, but I feel like it's a bit much for the type of riding I'm doing right now. I'm also noticing these dotted lines on my state map more nowadays, the ones that indicate "unpaved road." I've decided to look for a good used dual sport and see what that's like (note to loyal non-moto readers: a dual sport is a motorcycle that's equally at home on the street or in the dirt). I have no dirt experience whatsoever, so if you like comedy you'll want to be around the first time I try it. Guaranteed yuks! The bike is on the Grassroots Marketplace, and I have a flickr photoset too. It's a 1990 Yamaha FJ1200 with 31K miles, in about the condition you'd expect. Price is $2300 (negotiable, of course). Special consideration will be given to trade offers for dual sports.
I've been quiet about my experiences (trials?) with video game trading services lately, mainly out of disappointment. When I wrote about them back in September, I gave the nod to Gamershare over Goozex -- due in part to the Crazy Name Penalty assessed against Goozex. Bad move; apparently crazy names are the new black. Since then, I've amassed a sizable number of Gamershare points (30 at last count) and managed to use them for... absolutely nothing. That's zero trades in six months. Why? Because there's zero Xbox 360 inventory on the site. While there are maybe 10-15 360 games that display as "available," they're effectively dead entries. The jerks who listed them never respond to trade requests, so the games cycle on and off the available list every few weeks. I even tried browsing for games from other platforms, hoping to at least recover my investment and broker the games elsewhere. No luck -- apparently all platforms are equally SOL. I contacted Gamershare in February to ask if they planned on doing anything about the situation, and I did receive a reply ("we'll be rolling out new features in March, we may consider injecting games into the system"). The date was far enough away that I interpreted it as "never" and gave up. I resigned myself to losing the points I had on Gamershare and going with someone else. Someone else... ah yes, Goozex -- the guys with the crazy name. Apparently I misunderestimated their emphasis on community-building, because they seem to have a pretty good thing going on now. I've kept an eye on their inventory, and it seems to be significantly higher than I've ever seen on Gamershare. Why? No one knows for sure, but I'm starting to wonder if Gamershare's free game offer backfired on them by attracting less committed customers who were just in it for the free game (thus draining games from the more committed customers without replacement). The real proof that the tide had shifted came when I actually requested a trade through Goozex -- I received the game in less than a week. Gamershare may be down, but they're by no means out. This morning I received an email from the site advertising "Important Changes on Gamershare." Apparently they were acquired by GottaPlay, so they'll be offering both open-ended rentals (think Netflix) and trades. Trade prices have been jacked up from $1 to $3, but the price now includes a prepaid postage label with tracking. As cheap as I am, that still sounds like the way to go if it cuts down on "lost" trades.
For now, it looks like I'm back where I started. I plan on using my current Gamershare points as quickly as possible, then making a decision on whether to stay or jump ship. So far Goozex looks like a much stronger community (and therefore a stronger company), but Gamershare could still pull off an upset. Stay tuned.
I've been spending a little time lately on updating The Secret App to remove cruft (Login / User Engine being the two main sources of said cruft). Now that I'm no longer locked into an old revision of edge, I have noticed that Rails's ActiveRecord behavior seems to have changed a bit. Before, I could get away with saying @widget = current_user.widgets.create!(params[:widget]) Now, that gets me a big fat nil in @widget.user_id. Unfortunately, @widget = current_user.widgets.new(params[:widget]) gives me the same darned thing. The only way I could get the user_id to fill properly was with @widget = current_user.widgets.create(params[:widget]) Maybe it's something I am doing wrong, but I haven't found it yet. I wouldn't put much effort into it, but I really like the clean syntax I get from #create! and so it has gotten under my skin. Any ideas? Anyone? Bueller?
A recent change in the way Rails deals with incoming requests caught me a bit off guard. I was used to being all loosey-goosey with my routes, like saying
/categories/show/34-Detachable-Widgets.html
and having Rails happyily translate that into a request for /categories/show/34. However, when I caught up to edge a few days ago, my tests started failing. Wah? Further investigation revealed that the culprit was that flagrant .html hanging there on the end (why? because I can). After a bit of digging on the Rails mailing list, I finally found my buried treasure: a post by Jeremy Kemper mentioning that Rails now considers . a "URL separator." Ergo, your route
:controller/:action/:id
becomes
:controller/:action/:id.:format
and all's right with the world again. This allows us to force a format just by using it as the extension (i.e. trigger a specific response via responds_to), so I don't mind the change. I just wish someone had mentioned it a bit more loudly... like I'm doing now.
I love a good cheat sheet; anything to condense a big ol' reference site into a page or so that I can flip to when I need it. However, no one has made a good cheat sheet (or even a good reference, period) for the new RESTful Rails stuff. The best one-post reference I've found is simply_restful in Rails Core on David Goodlad's blog. Plenty of bloggers rah-rahed about simply_restful and gave a few examples of how to set it up, but David includes something unique: a table of all the auto-generated named routes and how to use them. I swear, I must have spent half an hour looking for exactly that information. Ah, sweet spoonfeeding! Thanks again to Mr. Goodlad for putting that out there.
"I expect I'll probably
be a little more like Clinton," Beebe said. "I like members of the
General Assembly. Virtually all of them are friends of mine. I was a
product of the legislature, so I understand some of the nuisances of
the way they think and act."
I think he meant to say nuances, but you never know.
While browsing Amazon tonight for a new television, I was presented with the following offer:
Yes -- Amazon suggested that since I'm looking at a large-format television, I might be interested in buying two of them. First I was flattered, but now I'm starting to feel a bit patronized. Are they trying to make some kind of subtle statement about how many times I've looked at this TV on their site?
This also brings up the question of how these "Better Together" offers are generated in the first place: is it via humans (obviously not very smart ones), or from past purchases... by people who impulse-buy a second television.
Children make memories as a river makes stones; what appears at first to be a swirling mass of chaos reveals, on closer examination, countless specimens of exquisite beauty. The riverbed is our gold mine, each stone tumbled and polished to perfection. We sift and examine, and eventually decide that we want to take the whole riverbed home. We know that the river never stops moving, never stops changing, despite our wishes to the contrary. The best we can do is to gather a handful of our favorites to take home. I think I found a keeper this afternoon. On arriving home from work, I found α at her desk. I asked what she was up to, and she said, "I'm doing my work. My homework." Without missing a beat, she returned to her addition worksheets. This is a child who was too sick to go to school today. They don't even give her homework when she is at school, so she makes up her own assignments. To quote Homestar Runner, "I know, can you believe it?" A child doing homework by choice, for the sheer joy of learning; I think I'll hang onto that one.
So this little motorcycle rally came to town a few weeks ago... maybe you've heard of it. Something like 75,000 motorcycles and 300,000 people converging on onetwo three small sections of our fair city. Luckily, our intrepid local bureaucrats were quick to educate the visitors on appropriate rally behavior. Signs were posted on most roads leading into down proudly proclaiming, "WELCOME TO FAYETTEVILLE, PLEASE RIDE QUIETLY." Uh huh. For most of the cruisers I see, this could only be accomplished by turning off the engine and coasting. But exhaust systems are a whole 'nother story.
The focus of the rally revelry is Dickson Street, a 4-block entertainment district just east of the UA campus. Dickson was known for a few good restaurants/bars and too many smelly hippies when I was in school, but it has been "made up" significantly since those olden days. Most of the vacant buildings have been remodeled or torn down, and there are more restaurants than I could visit in a year. For the duration of the rally, the smelly hippies were replaced with smelly bikers (the latter are distinguished from the former by their slightly cleaner clothes).
OK, so maybe I'm stretching the truth just a bit. As this was my first time to attend "the event" I wasn't quite sure what to expect. I was semi-familiar with what bikers expect to see at a rally, but what I ended up seeing was considerably tamer than my fevered predictions. The main activities of the crowd seemed to be walking, smoking, and attempting to enter any of the 5 bars on the street. All of the bars were filled to capacity, so the bouncers would throw out a few patrons every couple of minutes and drag a few more in to keep things in balance.
If I had to sum up BB&BBQ in a word, it would be LOUD. Just loud. The internal-organ-vibrating thud of an endless string of bikes was a constant reminder that internal combustion engines are nothing more than a series of controlled explosions. Even if you're not into bikes, the rally still offers plenty to see and ingest. I'll be going again next year -- but I'll probably take along my earplugs.
So it's been a little while since my last post. OK, a month. There have been plenty of blog-worthy events and topics since then, but a dearth of time in which to discuss them. Moving into a new house consumes enough time that I feel like I could have built it all over again. We're slowly getting everything unpacked, organized, and put away, so the house is less of a stressor now.
Topics for near-future posts: Ruby/Rails search engine choices, my continuing travails with loving two game trading services at once, and my take on Bikes Blues & BBQ. Promise.
After my recent rundown of game trading services, you might get the feeling that I'm feeling shortchanged. You would be right -- sending out four games and receiving zero in return (so far) doesn't give me a warm feeling. However, I think I discovered one reason for my lack of received games thus far. After filing my second claim with gamershare stating that I hadn't received a game mailed to me several weeks ago, I mused to myself, "Self, let's make sure we didn't make a small typo in our address." I went into my account page, and found to my delight that no small typos were present. However, my enthusiasm was somewhat muted by the fact that I had the wrong frickin city in my mailing address. Oh, that might be important...
In my meager defense, we did just move and I can be a bit absent-minded at times. However, I should have checked my own work after the first time the game didn't make it to me. If you're reading this and you've been mailing King King for the Xbox 360 to some idiot over and over for weeks... I'm sorry. Really.
UPDATE: the game sender was smarter than I could have hoped for, and managed to correct the address before resending the game the last time. I received it today in perfect shape. Carl Narcisse, you're a good egg. Thanks for putting up with me.
Dear Anonymous Wire Thief, My name is Jim Kane, and it appears that you visited my under-construction home recently. I know this because when I went there yesterday to install a pair of speakers, I discovered that one of the wires I previously ran was missing. The way I discovered this was by digging through 16 inches of fiberglass insulation for 15 or 20 minutes. The only problem with your caper was that you left the other wire in place. Maybe you didn't notice the other wire, or perhaps you were "interrupted." In any case, no hard feelings here. Just get in touch with me, and you can come pick up the other wire anytime. I'll even wrap it around your neck so you won't lose it.
I'm a man of many contradictions, or as one friend put it, "the most extravagant frugal person I know." Hey, it's not easy! For one thing, this fancy schmancy Xbox 360 of mine has an appetite for expensive games. I'm not the type to go out and drop $60 on a game without a fight, so I have looked high and low for ways to lessen the pain. There are several options out there: renting (so-so selection, expensive), online rental services (looooong transit times), used games (woopty doo a whole $5 off). What's a cheapskate gamer to do? I thought I had found my angle about a month ago, when I stumbled across a pair of game trading services. Gamershare and Goozex both act as matchmakers for gamers who want to trade their used games. The services give gamers credit when they send games out, and deduct credit when they receive games. Simple enough? It would seem so, and I had a small stash of Xbox games to play with. With the skepticism of Forrest Gump, I jumped in and started trading.
Gamershare was the first service I tried (since it was the first one I found). I listed 5 of my older games (I had to send a request to have Silent Scope added to their database) and within a few hours I had a trade request. Boo ya! The next day I packed up the game, case and all, and went to mail it off. The postage was about $3, so that was my first shock: those things are heavy! I quickly realized (since they told me several times on the site) that I didn't need to send the plastic case. After that I just sent the cover and manual along with the disc. Much better on the wallet. Sending out games is fine and all, but I was really interested in the receiving end of things. I wish I could say something positive about it, but... I'm still waiting for my first game to arrive. About a week after I signed up, I noticed that King Kong was available (one of the first available 360 games I saw on the site). I jumped right on it, and after 5 or 6 days it finally showed up as "sent" on my account page. It was supposedly sent out on the 17th of August with an incorrect state abbreviation, and is now on its way to me a second time. We'll see. Yes, the problem with this "peer to peer" system is that you're relying on your fellow man to send you the game as promised, when promised. Depending on your worldview, this may be a real stretch.
The other major problem with Gamershare (for me anyway) is the lack of Xbox 360 games available for trade. I probably shouldn't complain too loudly about this since I have yet to put a 360 game up myself, but the site administrators do not appear to be seeding any Xbox 360 games at all. It's frustrating to have plenty of GamerPoints but nothing on which to spend them.
Finally, the site itself is not without its flaws. I've encountered a few instances where "mailed on" dates changed after the fact, and tonight I found out that I can't get a 17-point game even though I have 20 points in my account. To their credit, all of my inquiries to them have elicited prompt and courteous responses. They seem to be on the ball with customer service, so I'm sure they'll fix whatever is wrong with my point total. I'm just not sure it will happen in time for me to get the game.
The second site in this not-very-crowded space is Goozex. They start out in second place because I found them second, and because their name would fit in great on the Web 2.0 Company or Star Wars Character quiz. I tried to look past that and took a spin around the site. The first thing I noticed was a much larger number of available games (i.e. more than one) for the Xbox 360. Hallelujah! I quickly ran into one of the website's main problems though: the search feature was very non-intuitive. If you clicked on the Xbox 360 logo to search for 360 games and you want to search for games on any console, you... click on the Xbox 360 logo again. Even though it's not highlighted or otherwise emphasized. Demerits for bad usability.
My next "oh darn" moment came when I realized that I couldn't request any of the available games! Gamershare starts new users out with 9 GamerPoints, which is enough to request one recent game without contributing to the system. While it probably contributes to the situation I mentioned above (no available games), it does let the new user try the system out without risk. Goozex starts new users out with one "trade credit" offers 200 game points after a successful trade, but doesn't give out enough to get a game right off. So, with all of my games sent away via Gamershare, I had exactly one title left to offer on Goozex. Offer it I did, and it was picked up after a few days... by Goozex. Interesting... they're buying games FROM their customers? I guess it's a form of seeding (I have read that they are adding games to the pool as well) and it's a great idea. I now have about 300 points, which is half of what I'd need to get an available 360 game.
So what's the take-away here? It's much too early to pick a winner at this point (if either of the current services survives) so you may want to keep your trading conservative until a clear favorite emerges. Getting stuck with unusable trade points is worse than a pocketful of Chuck E. Cheese tokens -- at least you can trade those for a plastic spider. Tags: goozex, gamershare, xbox, videogame
So after my last post about Mr. Clark's Rails no-nos list (now with extra followup!), I decided to act on Rob Sanheim's suggestion: that a site be created detailing the deprecated parts of Rails and solutions for same. I first thought of a blog, but I'm lazy and I don't want to write it all. Deciding that the Official Rails Wiki would be a much better (and easier) repository, I went there and found the perfect page already waiting for me: Deprecated Patterns. I filled it in, with the requisite bad wikiformatting (can't we all agree on what ' * ' means?). If you care enough to add an item, please play along with the best practices set forth below:
Present a solution along with the problem.
Explain why the old way is bad and the new way is better.
Keep it simple.
The resulting page should provide a ready resource for those who want to play catch up.
Kevin Clark recently posted an interesting article titled "Things You Shouldn't be Doing in Rails." Some of the suggestions were sorely needed (especially the one about asking good questions on the Rails-talk mailing list), but I thought a few of them were either underdeveloped or plain wrong:
Scaffolding: I've been thinking about this quite a bit recently, and I believe that the chorus of "don't use the scaffolding" is missing the point. Even if newbies don't use the scaffolding in their production code, they will use it to learn The Rails Way. In the absence of well-developed online docs, most users are going to do it the way the scaffold did it -- for better or worse. I'll pronounce myself fully guilty here (but on the road to recovery). The payoff from a few hours of cleanup on the scaffold generation code to make it generate clean, idiomatic code is that more people see it done the right way. Surely that's worth the time taken to accept a few (already made) patches?
Namespaced Controllers: Kevin is on the right track here -- this is one of the first things I wanted to do with my first application. There's a flawed assumption behind all of this that wasn't mentioned: that you need different controllers for administrators and normal users. Even though it's a pretty clear violation of the DRY principle, no one seems to mention this when they're talking about this issue.
I'll leave the rest of his points as-is, since they are in fact good suggestions. It seems that most readers either didn't like the author's tone, or felt that he was "scaring" recent / potential converts away from the Church of Rails. Maybe that's true, but I think the original idea (presenting a list of deprecated idioms and features in Rails) is certainly a good one. One commenter proposed a site for that purpose; now that's an idea I could get behind.
It's one or two weeks until we close on the new house. The house we've been waiting on for multiple months. The house that has no stairs. The house that DOES have a flat motorcycle-friendly driveway. Secrecy laws prevent me from actually posting any photos of the house in question. I can neither confirm nor deny that it looks awesome, and lacks only a yard to bring its curb appeal to full flower.
People have been telling us for some time that "the next part will go really slowly." I didn't think that was going to happen, as every day seemed to bring a new appliance or coat of paint. Now, the next week seems like it's going to be a month long. I am not a patient person by nature, but I've waited this long so I think I can gut it out for another week. After that, I'll just go sit in front of the house until they let me in.
Mice, apparently. You see, it's 6:59AM and I'm sitting outside of our garage watching strangers peruse through our belongings (a fine Arkansas tradition). As an added bonus, about fifteen minutes I noticed a small brown blur darting among some of our stored items. Yep, a field mouse. I hope (HOPE) he found his way inside the garage this morning as I was setting out stuff. The alternative is too unpleasant to contemplate at such an early hour.
If little bearded men in red peaked hats aren't your thing, perhaps you'd prefer a garden zombie? I'm not sure if he'd keep birds away, but the neighbor kids would probably stay the heck out of your yard. [from Rocket Jones] Tags: zombie
[Dustin is on his honeymoon, so somebody has to provide the pleasant distractions.] While searching for something worthwhile this morning (I promise), I ran across an intriguing puzzle known as Petals Around The Rose. The puzzle involves five six-sided dice, but beyond that would-be solvers are pretty much on their own. I solved it after about 5 minutes of head-scratching and muttering, which puts me quite a bit ahead of a more famous geek who took quite a bit longer. Oh, and Googling will eventually get you to the answer... but the stain of cheating will forever blot your soul. Don't say I didn't warn you.
Mongrel is the cool new thing in Rails deployment (even the main Rails site uses it now), but making it run well still requires some fussing and fiddling. Two tips I recently ran across are worth mentioning:
If you're using Pound (the best option until lighttpd's proxy support improves), you may want to adjust the TimeOut value therein. It's really really short.
If you're using MySQL, there is a mismatch between the interactive_timeout variable in MySQL server and the timeout Rails uses. Add the line ActiveRecord::Base.verification_timeout = 14400 to config/environment.rb to prevent... unpleasantness.
My mongrel installation is still having hiccups once a day or so, but these two tips together have improved its stability quite a bit.
If you're drinking the latest flavor of Railskool-aid, you are no doubt hard at work rewriting all of your controllers to conform to RESTful principles. Good for you! In your rush to coolness, however, don't forget to do the janitorial work of testing those great new actions. I recently added Accept-based processing to one of my controller actions, and I wanted to test the XML response separately. I couldn't figure out how to send the Accept: header in a test GET request for the life of me, until I stumbled upon Francois Beausoleil's post about respond_to order. The simple answer:
@request.env['HTTP_ACCEPT'] = 'application/xml'
Stick that into your test method right before your get / post, and you should be good to go.
If you're a Rails developer who wants users to actually visit your application once in awhile, it would help to pay some attention to the little white box at the top of your browser. Right now, it probably says:
http://localhost:3000/bacon/show/31
While the URL appears clean to us programmer-types, there's plenty of room for improvement. The main problem is that the ID, 31, has meaning only in the context of your application. When the URL shows up somewhere else, it's just a number. This matters a tiny bit to humans, and a lot more to search engines. We'd like to put something there that tells what 31 actually is. In my last app, my first attempt at URL beautification looked like this:
http://localhost:3000/bacon/show/Wood-Smoked
That's a good start: it loads the URL with more information about what's being displayed, and the dash as word separator is search engine friendly. However, this setup still has problems: what if two bacons have identical names? This actually happened in my app, where several categories were named "General". Also, what if we change the name of a bacon? Then, references to the old name in the URL won't work. That stinks!
I'll spare you the further thought exercise and say that someone else has already done the hard work for you. His post on Transparent opaque changeable permanent URLs is a masterful dissection of both problem and solution. In short, his solution is to put both the id AND the title / whatever into the "slug" (that thing at the end of the URL that we're concentrating on), and to redirect users if they get the ID right but use an old or incorrect title. Sweet! If you're like me, however, you wished for one more thing: spoonfed Rails code. I found some of that, too, at URLs on Rails. Finally, the author mentions implementation of the redirect for incorrect slugs but doesn't show the code. He's right, it's easy, and here's how I did it:
@bacon = Bacon.find(params[:id]) if params[:id] != @bacon.to_param headers["Status"] = "301 Moved Permanently" redirect_to :id => @bacon and return end
Now you should have all the code you need to build bulletproof, search engine-friendly URLs into your app. Enjoy the bacon!
To start, a little shameless self-promotion: the Eponym Blog Directory was officially and for real opened up yesterday, to the wild cheers of... well, just me. Its unveiling coincides with the upgrade to the Eponym Blog Search, which was pretty much a requirement since the two sites are tightly linked. I'd encourage you to check both of them out, and let me know what you think. One of the nice side benefits of working on the directory is that I get to view a variety of good blogs. One in particular caught me today, both for its content and its intent. Ten Years of My Life is a photoblog in which the author intends to post (at least) one photo per day for ten years. Since the author in question is both a dad and a sweet photographer, it's a very enjoyable photoblog. Beyond that, his stated goal (to chronicle ten years of his life through photos) strikes me as a great gift to one's descendants. Your kids may inherit a stack of vacation photo albums and several tapes / DVDs / reels of home movies, but 3650 photos taken over ten years will tell stories about your life that none of the other stuff does. Check him out. No, seriously, check him out!
The other day, I ran into an odd problem with Rails migrations. I needed to add an index to a MySQL TEXT column, and such indexes are required to include a prefix length (who knows why). Anyway, I discovered that I couldn't just tack the prefix length onto the column name because ActiveRecord was blindly quoting the entire string. I carped about it lightly on the #rails IRC channel, and forgot about it for a few weeks. Today I decided to take a few minutes and see how hard it would be to fix that little wart. Turns out it wasn't tough at all. Behold my first [PATCH] ticket! It's not exactly RJS, but hopefully someone will find it useful (and hopefully it won't break anything else).
"Have you ever had a dream, Neo, that you were so sure was real? What if you were unable to wake from that dream, Neo? How would you know the difterence between the dream world and the real world?" more»