Face Maker: Artificial selection experiment online
Philipp Lenssen kindly gave his permission for me to publish Face Maker, which I've just deployed. I wanted to build an online artificial selection system ever since reading about Richard Dawkins' The Blind Watchmaker programme but Face Maker is an experiment heavily inspired by Philipp's Mutating Pictures project.
A web site is a perfect place to host a project like this that deals with small incremental change. No single user is burdened with devoting hours to 'evolving' the faces. Instead the effort is massively distributed–and continues day and night. Users from all over the world work on collaboratively selecting for face-like appearances.
And participation provides its own rewards. Judging the procession of 'faces' has been strangely hypnotic while using Phillip's site and while working on my own. It's fascinating to see the eerily detailed faces emerging and it's almost tempting to wonder where they come from.
Face Maker differs from the current version of Mutating Pictures in a few ways.
- The images are drawn using curved shapes rather than triangles
- Both black and white shapes are used, overlapping one another
- Images are presented next to one another, the user is invited to select the most face-like image
- When one image 'wins' a round, the loser is removed from the database, and the winner gives birth to one child.
Continuing to borrow from Philipp's approach I plan to use this blog post to collect comments and discussion about Face Maker.
Face Maker was built in a feverish 2-day sprint with Ruby on Rails. It could be that some bugs surface, if they do, please accept my apologies in advance.
One of the original images:

Some faces that went extinct:



Step through each model inside a rake task
Sometimes you need to run a rake task that needs to 'know' about all the models in your application.
Here's one such situation that I've run into a couple of times. You've installed (or created) an 'act_as' type plugin that automatically creates a record in another table (eg. 'feed_items') when a new instance of the model it's been applied to (eg. 'post') is created. But because the plugin was added after data had been added to the db you now need to go back and make sure all the Post records have a corresponding record in the feed_items table. If a Post item is found without a FeedItem then one needs to be created.
Rake is good choice for creating this kind of synchronising task that you might need to run more than once. If you don't already have one, create a file called myapp.rake (substituting your app name of course) in myapp/lib/tasks.
Here's the skeleton I use when building tasks like this. Paste this into your myapp.rake file and save it.
desc "Iterates through models in the app and does something with each of them"
task :do_something_with_models => :environment do
models=[]
path="/app/models"
Find.find(path) do |p|
if FileTest.directory?(p) and p!=path
Find.prune # don't recurse into directories
next
end
if p =~ /.rb$/
puts p
models << File.basename(p,".*").classify
end
end
models.each do |m|
puts m
# Insert code here to do something useful with each model.
# You can retrieve a collection from the model like this
# eval("collection=#{m}.find(:all)") …
end
end
To run this task, cd to the root directory of your application and type
rake do_something_with_models
If all is well you should see a readout of the detected models. Now you can insert code into the models.each loop to do something useful for your application.
N.B This method will only 'see' the models which have corresponding .rb files in your models directory, so models that get created by plugins won't be detected.
Here's a task from a real application that attaches feed items to existing records that should have them. I'm sure it could be improved and optimised, I'm adding it here in case it's useful for others to build on.
desc "Creates feed items for records that might be missing them"
task :create_missing_feed_items => :environment do
orphan_counter=0
fixed_counter=0
models=[]
path="/app/models"
Find.find(path) do |p|
if FileTest.directory?(p) and p!=path
Find.prune # dont recurse into directories
next
end
if p =~ /.rb$/
models << File.basename(p,".*").classify
end
end
models.each do |m|
c=eval("")
if c.respond_to?("new") # is the class an active rcord class that can be instantiated?
n=c.new
if n.respond_to?("feed_item") # has the acts_as_feedable plugin been applied to this model?
c.find(:all,:include=>:feed_item).each do |o|
if o.feed_item.nil?
orphan_counter=orphan_counter+1
if f=FeedItem.attach_to_existing_feedable(o) # try to create a feed item
puts " id: no feed_item found, I'm creating one."
fixed_counter=fixed_counter+1
else
puts " id: no feed_item found, but I failed to create one!"
puts o.to_yaml
end
end
end
end
end
end
puts " records were found needing feed items."
puts " feed items were added to existing records."
end
page_cache_directory gotcha
Lately I started my long overdue experiments with caching. I had some difficulty confirming to myself that rails page caching was working. Following fingertips lazy sweeping article (check it if you didn't already it's can be very handy) I had configured my application to store cache files in public/cache instead of public. The fingertips technique results in the deletion of the contents of the cache folder when doing its 'sweeping' so it's important that this isn't the public folder itself.
Running the application locally (in production mode) the cache files were being generated correctly, but weren't being served back the next time the page was accessed. Eventually it became clear why this was happening. Although I'd modified the public/.htaccess rewrite rules so that apache would know where to find the new cache directory, I wasn't running Apache locally so when I tested this on my own machine the cached files were ignored, and regenerated on each request.
So far I haven't figured out how to configure mongrel to look in the correct place for the cached files but this isn't so pressing since caching does work as expected on the production server.
For anyone in a similar position; to confirm that pages you're seeing in your browser are being served from a cached file (rather than being generated dynamically) cd into your application directory and tail the log file corresponding to the environment your app is running in:
tail -f 100 log/production.log
Then access the page in question with your browser and watch the terminal. Accessing cached pages should bypass rails completely meaning that no new output should show up in the terminal.
seo_urls plugin: Making 'show' pages more findable
Google favours pages when important keywords are reflected in their urls. Normally a page in a rails application that shows a single record has a url that looks like this recipes/show/12. If this particular recipe is for pasta sauce, Google would prefer the url to be recipes/show/12-pasta-sauce. Because rails isn't interested in what appears after the number in the :id part of the url, we are free to add words there to help search engines without affecting how our application functions.
The seo_urls plugin aims to make it easy to create more descriptive urls for 'show' pages and increase your application's visibility to search engines.
Install from the root of your application like so:
script/plugin install http://svn.redshiftmedia.com/svn/plugins/seo_urls
Apply the plugin to a model like this:
# Apply it to a model like this:
end
# Or to use an attribute other than name or title:
end
The plugin looks for 'name' or 'title' attributes and if they are available it uses them to generate a search engine friendly string. to_param method is overwritten so that it returns the the numerical id of the record with the search engine friendly string appended to it.
# An example model
@recipe=>{:id=>12,:title=>"pasta sauce"}
# Without the plugin:
recipe_url(@recipe)=>"/recipes/show/12"
# With the plugin:
recipe_url(@recipe)=>"/recipes/show/12-pasta-sauce"
Displaying TextMate code in your WordPress blog
It can be a little tricky to get code in your Wordpress blog to look as good as it does in TextMate. I began with this article as a guide but departed form it in a couple of places. The following steps describe how I set up code formatting on this blog.
First, install and activate the wpuntexturize Wordpress plugin to suppress curly quote transformations.
In TextMate select the following menu option: Bundles > Textmate > Create CSS from current theme.
Run Edit > Find on the resulting document and replace all instances of '.yourthemename' (eg. '.cobalt') with an empty string (").
Save the resulting file as mate.css inside your WP theme folder and upload to your site.
Modify the header.php file for your theme to include the mate.css file. Add a line beneath the first stylesheet link so that the first two stylesheet links look like this: (substitute the example values here with your own site url and theme name)
To include some code in a blog post, select the code portion in TextMate and then choose Bundles > TextMate > Create HTML from selection (don't use the line numbers option, it makes it fiddly for people to copy and paste your code).
Copy the contents of the generated file and paste them into the Code view of your WP post.
I've noticed that not all code inserted in this way will be faithfully highlighted as it is in TextMate, but most of it is.
Globalize: the select option strop
The second Globalize post in as many days. Since I started I may as well through this one out there too, another one for the great Globalized minds of the interweb. I'm regularly bitten by this problem and didn't uncover a satisfactory workaround yet.
Globalize inelegantly flops when you ask it to load the collection attribute of a model instance if the instances in the collection have translated fields.
To illustrate the difficulty I'm having here's a simple Label <- Release -> Artist type data model that you might find on a multilingual music directory site.
class Label < ActiveRecord::Base has_many :releases has_many :artists, :through=>:releases end
class Release < ActiveRecord::Base belongs_to :label belongs_to :artist end
class Artist < ActiveRecord::Base has_many :releases has_many :labels, :through=>:releases translates :bio # let Globalize handle translation of the artists bio's end
>> Label.create(:name=>"Huge Ape Recordings") >> artist=Artist.create(:name=>"Zombie Gunship", :bio=>"Blah blah, the rest is history.") >> Release.create(:label_id=>1,:artist_id=>1) >> label=Label.find(1) => #"Huge Ape Recordings", "id"=>"1"}> >> label.artists StandardError: :select option not allowed on translatable models (artists.*) from ./script/../config/../config/../vendor/plugins/globalize_extension/lib/globalize/db_translate_ex.rb:31:in `find_every'
I have a feeling (hope) that this kind of thing ought to be possible with Globalize. In either case Google is eerily empty of relevant search results. Can anyone throw any light on this, how are you getting round it?
Localize Models to the rescue
Update: I've just demoed a delightful plugin by Saimon Moore called Localize Models. It's a system that can be used to replace Globalize's model translations. Rather than storing model translations in the main translations table, it uses additional columns with language code suffixes in the model tables. The big relief with this alternative is that there are no restrictions on :select options. Check his page for instructions (NB. The plugin threw errors in rails 1.1.6 but seems to work fine in edge rails).
>> l=Label.find(1)
>> a=l.artists.first
=> # Artist:0x33d4bc4 @attributes={"name"=>"Zombie Gunship",
"bio_nl"=>nil, "id"=>"1", "bio"=>"English bio here."}>
>> a.bio
=> "English bio here."
>> Locale.set(LOCALES['nl'])
>> a.bio="Dutch bio here"
>> a.save
=> true
>> Locale.set(LOCALES['en'])
>> a.bio
=> "English bio here."
>> Locale.set(LOCALES['nl'])
>> a.bio
=> "Dutch bio here"
Lovely!
Globalize: did Locale.base_language eat my functional tests?
Update: No, it didn't! Globalize globalize_languages and globalize_countries fixtures were missing from the functional tests, causing the errors I was seeing. Grab the appropriate fixtures from vendor/plugins/globalize/test/fixtures and copy them to test/fixtures. Make sure you include them in tests that need globalize by calling the fixtures something like so: "fixtures :users, :globalize_languages, :globalize_countries". Thanks again to Saimon for setting things straight. My original post follows.
Lately I've been getting enthusiastic about tests in general, and test driven development.
Already being a bit hooked on the satisfying solidity of tested code, I'm keen to introduce tests into the rails projects I'm busy with.
The (otherwise excellent) Globalize plugin is dunking a filthy fly in the testing ointment. My functional tests are failing and it looks as though it's because a class that Globalize defines, Locale, behaves differently in the test environment than it does in development mode.
I think I isolated the problem to the following: Locale.base_language, and Locale.langauge always report nil in the test environment, but behave as expected (returning a string containing the base language and active language respectively) in development mode.
Here's development mode:
computer:~/sites/globalize_demo m$ script/console
Loading development environment.
>> Locale
=> Globalize::Locale
>> Locale.set_base_language('en-EN')
=> #
>> Locale.base_language
=> English
And here's test mode:
computer:~/sites/globalize_demo m$ script/console test
Loading test environment.
>> Locale
=> Globalize::Locale
>> Locale.set_base_language('en-EN')
=> #
>> Locale.base_language
=> nil
I'm posting about this in the hope that a kindly reader can either point out what I'm doing goofily, or verify that this is a problem with Globalize.
The Tricky Business Of Setting up a Rails Development Environment on OSX
I have a brand new mac running OSX 10.4.7 so i thought that it should be relatively straightforward to get a rails environment set up if i found the right guide. It took me a day to get this working. Here I’m documenting what i think i should have done to have it work first time, for my reference for next time. Perhaps its useful for other people too. Continue reading…
