Category Archives: rails

On this page:

Tracking and organizing my clothes: substituting mathematics for fashion sense

Thumbnails of clothes

Inspired by my sister’s photo-assisted organization of her shoes, I decided to tackle my wardrobe. Taking an inventory would make it easier to simplify, replace, or supplement my clothes. Analyzing colour would help me substitute mathematics for a sense of style. Combining the images with the clothes log I’ve been keeping would make it easier to see patterns and maybe do some interesting visualizations. Geek time!

I took pictures of all my clothes against a convenient white wall. I corrected the images using Bibble 5 Pro and renamed the files to match my clothes-tracking database, creating new records as needed. AutoHotkey and Colorette made the task of choosing representative colours much less tedious than it would’ve been otherwise. After I created a spreadsheet of IDs, representative colours, and tags, I imported the data into my Rails-based personal dashboard, programming in new functionality along the way. (Emacs keyboard macros + Rails console = quick and easy data munging.) I used Acts as Taggable On for additional structure.

It turns out that the math for complementary and triadic colour schemes is easy when you convert RGB to HSL (hue, saturation, lightness). I used the Color gem for my RGB-HSL conversions, then calculated the complementary and triadic colours by adding or subtracting degrees as needed (180 for complementary, +/- 120 for triadic).

Here’s what the detailed view looks like now:

image

And the clothing log:

image

Clothing summary, sorted by frequency (30 days of data as of writing)

image

Thoughts:

  • White balance and exposure are a little off in some shots. I tweaked some representative colours to account for that. It would be neat to get that all sorted out, and maybe drop out the background too. It’s fine the way it is. =)
  • Matches are suggested based on tags, and are not yet sorted by colour. Sorting by colour or some kind of relevance factor would be extra cool.
  • Sorting by hue can be tricky. Maybe there’s a better way to do this…
  • My colour combinations don’t quite agree with other color scheme calculators I’ve tried. They’re in the right neighbourhood, at least. Rounding errors?
  • I’ll keep an eye out for accessories that match triadic colours for the clothes I most frequently wear.
  • Quick stats: 28 casual tops, 15 skirts, 12 office-type tops, 8 pairs of pants, 5 pairs of slacks – yes, there’s definitely room to trim. It would be interesting to visualize this further. Graph theory can help me figure out if there are clothing combinations that will help me simplify my wardrobe, and it might be fun to plot colours and perhaps usage. Hmm…

Other resources:

Context-switching and a four-project day

Context-switching among multiple projects can be tough. I’m currently:

  • working full-time on one project (a Drupal 6 non-profit website)
  • consulting on another (helping an educational institution with Drupal 7 questions)
  • supporting a third (Ruby on Rails site I built for a local nonprofit, almost done), and
  • trying to wrap up on a fourth (PHP/AJAX dashboard for a call center in the US).

I’m doing the Drupal 6 development in a virtual machine on my system, with an integration server set up externally. Consulting for the second project is done on-site or through e-mail. The Rails site is on a virtual server. The dashboard project is now on the company’s servers (IIS6/Microsoft SQL Server), which I can VPN into and use Remote Desktop to access. I’m glad I have two computers and a standing desk (read: kitchen counter) that makes it easy to use both!

Today was one of those days. I helped my new team member set up his system so that he could start working on our project. He’s on Mac OS X. It took us some time to figure out some of the quirky behaviour, such as MySQL sockets not being where PHP expected them to be. Still, we got his system sorted out, so now he can explore the code while I’m on vacation tomorrow.

In between answering his questions, I replied to the consulting client’s questions about Drupal and the virtual image we set up yesterday. That mainly required remembering what we did and how we set it up. Fortunately, that part was fairly recent, so it was easy to answer her questions.

Then I got an instant message from the person I worked with on the fourth project, the call-center dashboard. He asked me to join a conference call. They were having big problems: the dashboard wasn’t refreshing, so users couldn’t mark their calls as completed. It was a little nerve-wracking trying to identify and resolve the problem on the phone. There were two parts to the problem: IIS was unresponsive, and Microsoft SQL Server had stopped replicating. The team told me that there had been some kind of resource-related problem that morning, too, so the lack of system resources might’ve cascaded into this. After some hurried searching and educated guesses about where to nudge the servers, I got the database replication working again, and I set IIS back to using the shared application pool. I hope that did the trick. I can do a lot of things, but I’m not as familiar with Microsoft server administration as I am with the Linux/Apache/MySQL or Linux/Apache/PostgreSQL combinations.

I felt myself starting to stress out, so I deliberately slowed down while I was making the changes, and I took a short nap afterwards to reset myself. (Coding or administering systems while stressed is a great way to give yourself even more work and stress.)

After the nap, I was ready to take on the rest. The client for the Rails project e-mailed me a request to add a column of output to the report. I’d archived my project-related virtual machine already, so I (very carefully) coded it into the site in a not-completely-flexible manner. I found and fixed two bugs along the way, so it was a good thing I checked.

Context-switching between Drupal 6, Drupal 7, and Rails projects is weird. Even Drupal 6 and Drupal 7 differ significantly in terms of API, and Rails is a whole ‘nother kettle of fish. I often look things up, because it’s faster to do that than to rely on my assumptions and debug them when I’m wrong. Clients and team members watching me might think I don’t actually know anything by myself and I’m looking everything up as I go along. Depending on how scrambled my brain is, I’d probably suck in one of those trying-to-be-tough job interviews where you have to write working code without the Internet. But it is what it is, and this helps me build things quickly.

On the bright side, it’s pretty fun working with multiple paradigms. Rails uses one way of thinking, Drupal uses another, and so on. I’ve even mixed in Java before. There were a few weeks I was switching between enterprise Java, Drupal, Rails, and straight PHP. It’s not something I regularly do, but when the company needs it, well… it’s good exercise. Mental gymnastics. (And scheduling gymnastics, too.)

I like having one-project days. Two-project days are kinda okay too. Four-project days – particularly ones that involve solving a problem in an unfamiliar area while people are watching! – are tough, but apparently survivable as long as I remember to breathe. =)

Here are tips that help me deal with all that context-switching. Maybe they’ll help you!

Look things up. It’s okay. I find myself looking up even basic things all the time. For example, did you know that Ruby doesn’t have a straightforward min/max function the way PHP does? The canonical way to do it is to create an array (or other enumerable) and call the min or max member function, like this: [x,y].max. Dealing with little API/language quirks like that is part of the context-switching cost. Likewise, I sometimes find myself wishing I could just use something like rails console in my Drupal sites… =)

Take extensive notes. Even if you’re fully focused on one project and have no problems remembering it now, you might need to go back to something you thought you already finished.

Slow down and take breaks. Don’t let stress drag you into making bad decisions. I felt much more refreshed after a quick nap, and I’m glad I did that instead of trying to force my way through the afternoon. This is one of the benefits of working at home – it’s easy to nap in an ergonomic and non-embarrassing way, while still getting tons of stuff done the rest of the day.

Clear your brain and focus on the top priority. It’s hard to juggle multiple projects. I made sure my new team member had things to work on while I focused on the call center dashboard project so that I wouldn’t be tempted to switch back and forth. Likewise, I wrote the documentation I promised for that project before moving on to the Rails project.

Breathe. No sense in stressing out and getting overwhelmed. Make one good decision at a time. Work step by step, and you’ll find that you’ll get through everything you need to do. Avoid multi-tasking. Single-task and finish as much as you can of your top priority first.

I prefer having one main project, maybe two projects during the transition periods. This isn’t always possible. Programming competitions helped me learn how to deal with multiple chunks of work under time pressure, and I’m getting better at it the more that work throws at me.

What are your tips for dealing with simultaneous projects?

2011-06-30 Thu 16:19

Negative optimization

Checking on one of my projects (a Ruby on Rails survey site), I realized that it was running painfully slowly, taking 30 seconds to render a page.

The first thing I checked was memory. I was on a 256MB slice at Rackspace Cloud. Was the server running out of memory and swapping to disk? I put in the recommended settings for Apache+Passenger+Rails on 256MB:

RailsSpawnMethod smart
PassengerUseGlobalQueue on
PassengerMaxPoolSize 2
PassengerPoolIdleTime 0
PassengerMaxRequests 1000
RailsAppSpawnerIdleTime 0
PassengerStatThrottleRate 5

The website was still crawling. I reviewed the logs and found that ActiveRecord was taking a while. The Internet had a few performance optimization tips, so I checked out the survey controller to see if I could improve performance by preloading information.

As it turned out, I was already preloading information. So I tried turning off preloading by removing the :include directives for my queries.

The system went back to a decent speed.

You see, I’d been working with lots of associations, and eager loading had probably resulted in a gazillion rows in my result set.

Moral lesson: Test your system before and after you put in something to improve the performance, because you just might be making your performance worse. ;)

Oh well. Live and learn!

2011-06-07 Tue 16:19

Rails: Preserving test data

I’m using Cucumber for testing my Rails project. The standard practice for automated testing in Rails is to make each test case completely self-contained and wipe out the test data after running the test. The test system accomplishes this by wrapping the operations in a transaction and rolling that transaction back at the end of the test. This is great, except when you’re developing code and you want to poke around the test environment to see what’s going on outside the handful of error messages you might get from a failed test.

I set up my test environment so that data stays in place after a test is run, and I modified my tests to delete data they need deleted. This is what I set in my features/support/env.rb:

Cucumber::Rails::World.use_transactional_fixtures = false

I also removed database_cleaner.

You can set this behaviour on a case-by-case basis with the tag @no-txn.

Running the tests individually with bundle exec cucumber ... now works. I still have to figure out why the database gets dropped when I do rake cucumber, though…

2011-04-24 Sun 16:21

Rails: Paperclip needs attributes defined by attr_accessible, not just attr_accessor

I wanted to add uploaded files to the survey response model defined by the Surveyor gem. I’d gotten most of the changes right, and the filenames were showing up in the model, but Paperclip wasn’t saving the files to the filesystem. As it turns out, Paperclip requires that your attributes (ex: :file_value> for my file column) be tagged with attr_accessible, not just attr_accessor.

Once you define one attr_accessible item, you need to define all the ones you need, or mass-assigning attributes with update_attributes will fail. This meant adding a whole bunch of attributes to my attr_accessor list, too.

If you’re using accepts_nested_attributes_for, you will also need to use attr_accessible there, too.

Sharing the note here just in case anyone else runs into it. Props to Tam on StackOverflow for the tip!

2011-04-01 Fri 12:41

Rails: Exporting data from specific tables into fixtures

Rails is pretty darn amazing. There are plenty of gems (Ruby packages) that provide additional functionality. They’re like Drupal modules, except with more customizability (not just hooks) and fewer pre-built administrative interfaces (you win some, you lose some).

For example, the client asked me, “Can we edit the static content?” Now if I had asked about this as a requirement at the beginning of the project, we might have gone with Drupal instead–although the Rails Surveyor still feels cleaner than a CCK-based survey type, so we might’ve stayed with Rails.

Anyway, we were well into Rails now, so I looked for a content management system that I could integrate into the Rails 3-based website. After some experimenting with Refinery CMS (looks slick, but couldn’t get it to do what I wanted) and Comfortable Mexican Sofa (looked pretty geeky), I settled on Rich CMS. I nearly gave up on Rich CMS, actually, because I’d gotten stuck, but the web demo helped me figure out what I needed to do in order to enable it.

We’re still emptying and reloading the database a lot, though, so I wanted to make sure that I could save the CmsContent items and reload them. I didn’t want to back up the entire database, just a table or two. There were some gems that promised the ability to back up specific models, but I couldn’t figure it out. Eventually I decided to use the table-focused Rake code I saw in order to export the data to fixtures (seems to be based on code from the Rails Recipes book).

task :extract_fixtures => :environment do
  sql  = "SELECT * FROM %s"
  skip_tables = ["schema_info"]
  ActiveRecord::Base.establish_connection
  if (not ENV['TABLES'])
    tables = ActiveRecord::Base.connection.tables - skip_tables
  else
    tables = ENV['TABLES'].split(/, */)
  end
  if (not ENV['OUTPUT_DIR'])
    output_dir="#{RAILS_ROOT}/test/fixtures"
  else
    output_dir = ENV['OUTPUT_DIR'].sub(/\/$/, '')
  end
  (tables).each do |table_name|
    i = "000"
    File.open("#{output_dir}/#{table_name}.yml", 'w') do |file|
      data = ActiveRecord::Base.connection.select_all(sql % table_name)
      file.write data.inject({}) { |hash, record|
        hash["#{table_name}_#{i.succ!}"] = record
        hash
      }.to_yaml
      puts "wrote #{table_name} to #{output_dir}/"
    end
  end
end

Being a lazy programmer who doesn’t want to remember table names, I also defined the following Rake tasks:

task :save_content => :environment do
  ENV["TABLES"] = "cms_contents"
  Rake.application.invoke_task("myproj:extract_fixtures")
end
task :load_content do
  Rake.application.invoke_task("db:fixtures:load")
end

Then I can call rake myproj:save_content and rake myproj:load_content to do the right thing. Or rather, my co-developer (a new IBMer – hello, Vijay!) can do so, and then check his work into our git repository. =)

Now we can re-create the development database as often as we’d like without losing our page content!

2011-04-24 Sun 16:29