A brief introduction to Ruby, Sinatra, and Haml
Ruby and Sinatra make it ludicrously easy to make a webapp, but getting started, as with any new language or framework, can be daunting. By the end of this part, you'll have a simple template that talks back to you!
Destructors in Ruby? Not quite…
So I was curious to see how destructors work in Ruby, and...they don't. Or rather, the method we do have, ObjectSpace.define_finalizer, is rather restrictive. But it does leave a loophole -- the callback method receives an object_id.
Cool free hosted tools for your Ruby webapp
Some of these are obvious (i.e. get exceptional, hoptoad), many of these aren't Ruby-specific, but I thought it might be nice to put all these in one place, at least for my sake.
Exception tracking
Get Exceptional limit: 1 app
Hoptoad limit: 1 project, 2 users
Bug tracking:
there's github, of course, if you're already using that...
16bugs limit: 1 project
I'm not including full hosting platforms, like Google Code here, but you could use those, too
One-off emails (i.e. signup)
Sendgrid limit: 200 emails/day
GMail allows 500 emails/day, but doesn't offer all the doodads that Sendgrid does
Mailing list (i.e. newsletter)
Mailchimp limit: 500 subscribers, 3000 emails total a month
Customer Support
SnapABug limit: 10 reports/day
uservoice limit: 100 unique users/month
GetSatisfaction limit: 0 official reps, not hosted on your url
Analytics
There's a ton of options in this space, but I use:
Google Analytics limit: no limits, because it's The Goog
Clicky limit: 1 website, 3000 hits/day
Metrics, Monitoring
New Relic limit: no troubleshooting, optimization, etc
User Avatar Hosting
Gravatar limit: none
Authentication
OpenID
RPX limit: up to 6 providers, instead of 12
Time tracking/invoicing
Harvest limit: 2 projects, 4 clients, 1 user
Help desk thing
Just kidding, couldn't find any free hosted help desk apps
Anything else I'm missing that every webapp needs?
Design pattern/flow for building a website
So here's how I normally do things:
- Do as much of the models as possible in this first pass, skipping validation but including schema stuff
- Stick a couple things into the controllers that I think I'll need
- Build out some of the views, giving them some basic styles
- Revisit the models to add validation, helper methods
- Build out the rest of the views, give them real styles
- Muse about specs, then give up before starting
- Put more stuff into the controllers
- Iterate on random components until you're done
Needless to say, I'm getting to the point where my lack of organization kills my mini-projects before I hit step 4, sometimes even sooner than that. So I'm going to try a slightly more...conventional (or widely suggested, at least) approach:
- Create controllers with just enough information so that your pages will display. No setting variables yet or other logic!
- Fill out the views with as much HTML and fake data as you need. Site have a sign-in page? Leave a link to "force sign-in" the user that simply sets them to an authenticated state. All it should do is set a session variable
- Spec out the models. Don't check for validation yet, just check for core functionality, i.e. there is a User table, the first user has a name of Foo and email of bar@baz.com, etc.
- Fill out your model code so that the specs pass -- this includes migrations with sample data (these can be removed in a later migration).
- Spec out your controllers/views.
- Fill out your controllers/views so they pass specs.
- Do the rest of the little things that need doing, like validation, error messaging, authentication, styling, etc.
- Revel in having finished a project.
Hopefully I'll get further than step 3 this way! I'm going to try to focus more on content/frontend instead of getting bogged down in the backend, and I want to actually write specs.
Any comments/suggestions?
Announcing: Ramastic, a skeleton for Ramaze
This is something I've been working on since slightly before my original call for suggestions a while back. It's not done yet (I'd say it's somewhere around 75% done) but I want to get it out there before I totally lose steam on it. There are a few inline styles I was planning on removing, but haven't gotten around to, so...apologies. If you find it of use, please leave a comment.
And yes, it doesn't look that great. But I'm expecting you to restyle everything anyway and possibly blow away the templates entirely in your instantiation of the skeleton.
Now, without further ado, here are features and screenshots:
Features/requirements
- Built on Bones
- Edge Rack/Innate/Ramaze
- Haml/Sass
- Sequel + sqlite3
- Blueprint CSS
- jQuery, jQuery UI
- OpenID (via RPX)
- RestClient
- Crack
- UUID
- Rack-flash
Screenshots
Repository
Thanks for looking!
Ideas Needed for Mr. Bones skeleton built on Ramaze
If I were to make a skeleton using Mr. Bones that was built on Ramaze, what would people like to see in it? It's for my use first, but the community's use a close second if I can generalize it enough. I was thinking along the lines of openid support, having a decent home page and logged-in-user gateway, appropriate nav-bars, haml+sass, jquery+ui, etc....thoughts? What do you find yourself doing at the beginning of every website project that you'd like to not have to repeat every time you start a project?
re-"require"-ing: how's the speed?
What this is about
So I like the design that, when you need a particular library in your code, you require it in right there in the method/class (JIT library-loading, so to speak), even if it means the require directive will get executed more than once. Running through irb you can tell that calling require twice on the same library is usually much faster the second time, but how much faster?
Read on for benchmarks!
Gotcha with Sequel and Association Caching
One thing to remember with Sequel is that it caches associations -- for an hour, by default. Normally this is good -- if I say my_model.my_associated_models twice in one request, I'd like that to be cached. But at least with Ramaze, where you can access a variable that persists between requests (via session, like session[:user]), you have to remember that associations on that session object get cached, too. So what does that mean? That means if you have a user view their posts (with session[:user].posts), and then they go make a post, and then they come back to view their posts again...the new post won't be in the list of posts! So you have two basic options here, that I know of -- either a) manually kill the cache by putting session[:user].refresh on the action that alters the associations of session[:user], or b) put session[:user].refresh in a place that gets executed at the beginning of every request.
Ruby 1.9 and OpenSSL on Ubuntu
Having trouble getting openssl working on your Linux box and Ruby 1.9 (or 1.9.1, specifically)? Here's something to give a try...
Partial success!
For a good chunk of yesterday, I was trying to ""port"" my exceedlingly simple Ruby application to Windows. The hitch? It uses Gosu (game engine), Chipmunk (physics engine), ImageMagick (popular graphics tool), and RMagick (wrapper for ImageMagick in Ruby). With the help of RubyScript2Exe it almost, almost worked. Gosu and Chipmunk had no problem, as they had no-strings-attached .so files and apparently were programmed well. ImageMagick, despite trying to be a pain in the ass by making me include an extra dozen DLLs in my project folder, actually did end up working. But RMagick...when moving the generated app to a new computer that didn't have ImageMagick installed freaked out with a weird "address not accessible" error or something. After some fiddling I gave it up as a lost cause and dropped support for ImageMagick+RMagick. The only reason they were there in the first place is because I wanted to load SVG files whenever possible, and possibly have some dynamic graphic generation, but...the former isn't that great anyway, and the latter will have to be done other ways, if at all.
So, yes, Ruby+Gosu+Chipmunk play just fine with RubyScript2Exe on both Windows and Linux.