There's this project I've been wanting to do for some time now, but haven't been able to due to a much bigger project that keeps dragging out and taking much longer to complete that I originally hoped. I finally decided to just take a break from that other project for a while and hammer this little thing out... and, it's done(ish).

There's still some things that I'd like to add, but all the core functionality is there and working. So, I'd like to finally present you with .... CramDex.

CramDex is a flashcard studying tool. Of course you can build your own decks of cards and in the true spirit of Web 2.001, you can study other people's decks and they can study yours. Sounds pretty bland, but there's more. CramDex doesn't start out flashing all of the cards in your deck at you. It randomly picks a few, and starts you on those. It tracks your progress on each, spending less time on flashcards you know, and more on those you don't. As you prove that you know certain flashcards it starts to introduce more cards, and once you've demonstrated that you've mastered a particular card, it's "set aside" and only rarely shown again (just often enough to re-enforce that knowledge). So you're constantly focusing your efforts on learning new and difficult material, and not wasting time "studying" things you already know.

Initially, new flashcards are presented as a multiple choice question, showing you either the 'Question' side of the card and giving you several possible answers, or the 'Answer' side with several possible questions. After a few of those it starts to give you just the 'Question' side, and a field to type the answer into (spelling, punctuation and capitalization counts). The 'Question' side of the card can either be words (eg. "What's the capital of Mazatlán?"), or a picture. I've got one sample deck in there now that shows maps of US States and you need to identify the pictured state.

So, go check it out, pass the link to friends, and let me know what you think. It's still not very pretty at the moment, but I have to say, I think my design skills are starting to improve... just a little.

Comments: 0 [add comment]
  • ICandy

At my day job we have several Rails apps that we've built and continue to maintain and enhance. We often add features that are usable in all of our applications, so although they're often initially developed in one app or another, they quickly get turned into plugins that we can share across all of our apps.

My boss and fellow Rails developer Aaron Baldwin has been typically hacking on plugins that are strictly internal and wouldn't be of much use to anyone outside of our organization, whereas I've been fortunate enough to get to work on things that are more generic and thus releaseable to the broader community. So, it's particularly noteworthy that Aaron released his first public Rails plugin this week, and this is one of those plugins that, now that I've used it, I don't know how I could have ever coded Rails without it.

Here's what it's for. When writing integration tests you often test that certain elements exist on the page. The problem though, is that when one of these tests fail, all you're told is that an element of some type was expected, but none were found. Was the element really not there? Or is there a typo in your test? Or on the page? Or... what? I've found myself in this scenario desperately wishing I could just see the page that the test was testing in my browser window so I could look for myself.

Enter ICandy. ICandy is a Ruby on Rails plugin that automatically displays the page from failing integration tests in your browser window. You can also manually trigger certain pages to open in your browser, if you desire. It's been tested to work with Safari and Firefox on Mac and Firefox on Ubuntu.

Comments: 0 [add comment]
  • Floriduuh

After all the recent controversy in Florida Floriduuh over updating their K-12 science education standards to start teaching kids actual science (and the strident minority who were offended by that), and the even more recent attempt to completely undermine the new standards and grant teachers the "Academic Freedom" to ignore standards completely and teach whatever the hell they wanted (a battle still going on in several other states), now comes... Wizardy!

Substitute teacher Jim Piculas does a 30-second magic trick where a toothpick disappears then reappears. But after performing it in front of a classroom at Rushe Middle School in Land 'O Lakes, Piculas said his job did a disappearing act of its own. The charge from the school district — Wizardry!

So, on that note, I'd like to propose the state name be officially changed to "Floriduuh", and a new State Motto, "Floriduuh, The Most Retarded Place on Earth" and while we're at it, let's just declare that citizens of Floriduuh, especially anyone educated there, are now officially known as Floridiots. So, go ahead and call your favorite Floridiot and congratulate them... just be sure to speak slowly and use small words.

Update: May 9th 2008

By any reckoning, University of South Florida professor Lorena Madrigal, Ph.D., was the perfect choice to speak for this Friends of Brooker Creek Preserve event.

A respected scholar in the field of human evolution, on a day marking the birthday of the creator of the science of evolution, giving a speech in a setting inextricably linked to the study of biology, which indeed would reflect upon Darwinism, was considered too controversial?

http://www2.tbo.com/content/2008/may/08/me-evolution-darwin-day-big-problem/

Could only happen in Floriduuh! (Well, honestly, it could happen elsewhere (probably has), but it didn't this time, and I've got a great theme going here.) Come on Floridiots, keep the great material comming.

Comments: 2

I recently added attachment_fu to a personal Rails project that was already using GateKeeper and ran into some stumbling blocks. It took me some time to dig into attachment_fu's inner workings and some experimentation to figure out the best way to get to the two plugins to play nice together, so here's some tips for anyone else who might try this themselves someday.

attachment_fu is a Ruby on Rails plugin by Rick Olson that facilitates file uploads and is the successor to Rick's acts_as_attachment plugin. GateKeeper is a Ruby on Rals plugin by yours truly that provides a natural language DSL to easily setup and manage highly complex RBAC permission rules at the model level.

I'm going to use 'Picture' as my attachment_fu model for these examples. Typically with attachment_fu, this model would probably look something like...

class Picture < ActiveRecord::Base
  belongs_to :user
  has_attachment :content_type => :image, :max_size => 50.kilobytes, :thumbnails => {:thumb => 'x42'}
end 

Now, with gatekeeper, you might expect to just add a couple simple permissions so the owner can create, update and destroy the picture and share it with other users, such as....

class Picture < ActiveRecord::Base
  belongs_to :user
  has_attachment :content_type => :image, :max_size => 50.kilobytes, :thumbnails => {:thumb => 'x42'}
  
  ## Permissions ##
  crudable_by_my_user
  readable_by_anyone
  #################
  
end 

Note that the readable_by_anyone permission assumes that you have a 'is_anyone?' User instance method that always returns true.

There are two problems with the above. First, you're going to have issues the first time you try to access the thumbnail version of the image. Second is that the above is using the default :db_file storage method which actually adds a another ActiveRecord model, and which GateKeeper will immediately lock down tight. If you're not using thumbnails or the :db_file storage method, then the above is probably all you need. Everybody else, keep reading.

First, let's address the thumbnail issue, since that's the easiest to deal with. In order to support thumbnails, attachment_fu's instructions tell you to add a 'parent_id' column to your 'pictures' table. attachment_fu then automatically provides a 'parent' association on thumbnails that point back to the original uploaded image. You're going to want thumbnails to just inherit their GateKeeper permissions from the original image, so that anyone with permission to read or delete the original image can do the same to the thumbnails. To do this, just add a 'crudable_as_my_parent' permission to Picture. (Notice that that says as_my_parent, not by_my_parent.) This will allow anyone who can read the original to also read the thumbnail, and anyone who can destroy the original to also destroy the thumbnail.

class Picture < ActiveRecord::Base
  belongs_to :user
  has_attachment :content_type => :image, :max_size => 50.kilobytes, :thumbnails => {:thumb => 'x42'}

  ## Permissions ##
  crudable_by_my_user
  readable_by_anyone
  crudable_as_my_parent
  #################
end 

Ok, that was actually pretty easy. The :db_file storage method is just a little more challenging. If you're using :filesystem or :s3 as your storage medium for uploaded files, then you should be fine since neither of these use extra ActiveRecord models to access the files, so GateKeeper won't get in the way. However, if you're using :db_file, here's what you want to do. First, create a db_file.rb file in /app/models and make it look something like this (changing all three (3) occurances of 'picture' to match whatever your attachment_fu model is).

class DbFile < ActiveRecord::Base
  has_one :picture
  crudable_as_my_picture
  crudable_by_anyone :if => lambda {|db_file| db_file.picture.nil? } #pic already destroyed
end

The first line provides an association for GateKeeper to use to get back to the picture model. The second line tells DbFile to inherit it's GateKeeper permissions from the picture provided by the association. The third line is the tricky one. When pictures are destroyed, Rails will destroy the picture first, then automatically try to destroy the associated db_file (via a ':dependent => :destroy' call). However, when it goes to delete the db_file, there won't be a picture anymore to inherit permissions from, and line two will fail. We can safely assume though that if a db_file is being destroyed and if (and only if) the picture doesn't exist, it too must have just been destroyed by the current user and the db_file should follow suit. You should never have stray :db_file objects left in your database whose associated objects are gone, so there's really no risk in allowing anyone to destroy one in such an orphaned state.

We're almost done, but not quite yet. The last problem is that the DbFile class you just defined will never get loaded by Rails. attachment_fu is going to create it's own DbFile and the permissions you setup will never get loaded or used. So, let's go back to the Picture class and add one line to the very top to force your DbFile class to load before attachment_fu tries to create it's own.

require_dependency 'db_file'
class Picture < ActiveRecord::Base
  belongs_to :user
  has_attachment :content_type => :image, :max_size => 50.kilobytes, :thumbnails => {:thumb => 'x42'}

  ## Permissions ##
  crudable_by_my_user
  readable_by_anyone
  crudable_as_my_parent
  #################
end 

And that's it. GateKeeper and attachment_fu should play nice together now, giving you file upload wonderfulness and model security peace of mind. One last thing I'd like to briefly touch on is the possibility of having more than one attachment_fu model. Let's say you're running a job site that allows users to upload a photo of themselves AND a pdf resume. So, you're going to have both a Picture and a Resume class, and DbFile is going to need associations to both. Note that I haven't actually tried this, but updating your DbFile class that you built above to the following should work just fine. (Continue the pattern for any additional attachment_fu models you want to add to your application.)

class DbFile < ActiveRecord::Base
  has_one :picture
  has_one :resume
  crudable_as_my_picture
  crudable_as_my_resume
  crudable_by_anyone :if => lambda {|db_file| db_file.picture.nil? and db_file.resume.nil? }
end
Comments: 0 [add comment]

Hello Readers, and Happy National Day of Prayer to you.

I'd like to dedicate this post to Madeline 'Kara' Neumann, an 11 year old girl from Weston Wisconsin, who tragically died of untreated diabetes on March 23, 2008, due to her parents insufficient faith and unwillingness to pray harder. President Bush states in his 2008 National Day of Prayer Proclamation, that...

"As we observe this National Day of Prayer, we recognize our dependence on the Almighty, we thank Him for the many blessings He has bestowed upon us, and we put our country's future in His hands."

Clearly, Kara's parents, Leilani and Dale Neumann, failed to recognize their own "dependence on the Almighty," and for this their daughter deserved to die, ... slowly. If they had only prayed harder, called on more friends to help them pray, and sent more emails asking fellow christians around the world to help them pray, maybe this tragedy could have been avoided. Thankfully, these faithless parents are now being charged with second degree reckless homicide and are facing sentences of up to 25 years in prison.

Naturally, there are terrible people in this world trying to undermine the power of prayer, such as the malicious scientists behind this 2006 study showing prayer has no effect, and recklessly subjecting innocent people to crises of faith. Who cares if there's no evidence to support a belief in prayer? There's no harm in believing (except deaths of innocent children), right? And what about those heathens who support a National Day of Reason instead of prayer. How dare they challenge the establishment of a Christian Theocracy to replace the U.S. Government for the purpose of instructing all Americans which god to follow, and how, if they intend to testify on how taxpayer dollars should (or not) be spent. Really, of all the nerve.....

Comments: 0 [add comment]