Double Shot #513

Spent too much time yesterday fighting with code. Hope to spend more time writing it instead today.

Double Shot #512

Lots of people are excited about Rails and 37Signals being mentioned in Microsoft's annual Form 10-K. I think that's just silly. This isn't any sort of acknowledgement that Microsoft considers us a serious threat; it's a "cover your ass" survey of software and firms whose business overlaps that of Microsoft. For some perspective, go look at other 10-K's; for example, the one for McDonald's says "The Company’s competition in the broadest perspective includes restaurants, quick-service eating establishments, pizza parlors, coffee shops, street vendors, convenience food stores, delicatessens and supermarkets." So, yeah - McDonald's:street vendor::Microsoft:37 Signals. That'd be about right.

  • NoSQL: If Only It Was That Easy - Look at some of the currently-sexy database alternatives by someone who actually evaluated at heavy load.

  • Deployment Script Spring Cleaning - New ideas on using Capistrano with git, from the GitHub guys.

  • Napkee - Convert Balsamiq Mockups to HTML/CSS/JSS/Flex 3 source.

  • Lone Star Ruby Conference - One more week for registration for this Texas conference at the end of the month.

  • Cerberus 0.7 - Lightweight continuous integration, now with Bazaar support and better Git support.

  • RailsBridge BugMash - Contribute to the Rails core - Just a reminder: it's coming up this weekend.

  • complex-form-examples - Ryan Bates takes a shot at showing ways to manage forms with nested attributes.

  • va_cache - Simple caching for Active Record virtual attributes.
  • Double Shot #511

    On the whole, I'm happy I picked Rails to switch to a few years ago.

    Double Shot #510

    I hope a lot of you are planning to participate in the Rails BugMash - it's shaping up to be a lot of fun.

    Double Shot #509

    My latest production, released over the weekend: Rails Freelancing Handbook.

    • cmon - Cutesy HTML preprocessor for columnar/tabular cross-browser layouts

    • Bluefeather - Another alternative/extended Markdown converter.

    • Bag O'Links - By the way, Elad Meidar is also doing a great link blog, in case Fresh Cup isn't enough for you.

    • Installing And Using SQLite With Ruby On Windows - Helpful info for those getting started with Rails.

    • Return of Ruboto! - IRB running on Android. Interesting even if I'll probably never need it for anything.

    • Firefox/Namoroka - What's coming down the pike next now that 3.5 has shipped. Nightly builds are here if you want to live dangerously.

    • lockrun - Tool to prevent cron from launching a new job if an old one hasn't completed yet.

    Recurring Items in a Rails Application

    I recently had to implement some recurring items in a Rails application - we'll call them "entries" here though you can use this technique for appointments, bills, or whatever else. After thinking about it for a while, I settled on:

    • At any point, we needed to know what the next recurrence date was.

    • The potential schedules needed to be data-driven (because the client was unsure what would be needed).


    Here's what I came up with. If your needs are different, you'll no doubt need to alter it. First, the schedule model has a schedule_type, an interval, a specific value, and a description. The combination of these things lets me implement Schedule#next_date to return the fate for the next date given a schedule object and the current date. Here's the model:


    [sourcecode language='ruby']
    class Schedule

    has_many :entries

    attr_accessible :schedule_type, :description, :interval, :specific

    SCHEDULE_TYPE = {:first => 0, :last => 1, :weekly => 2, :monthly => 3}

    def next_date(current_date)
    case schedule_type
    when SCHEDULE_TYPE[:first]
    first_day = (current_date + 1.month).beginning_of_month
    wday = first_day.wday
    if specific >= wday
    first_day + specific - wday
    else
    first_day + 7 + specific - wday
    end
    when SCHEDULE_TYPE[:last]
    if specific == -1
    (current_date + 1.month).end_of_month
    else
    last_day = (current_date + 1.month).end_of_month
    wday = last_day.wday
    if wday >= specific
    last_day - wday + specific
    else
    last_day - wday - 7 + specific
    end
    end
    when SCHEDULE_TYPE[:weekly]
    current_date + interval.weeks
    when SCHEDULE_TYPE[:monthly]
    current_date + interval.months
    end
    end
    [/sourcecode]

    So we can have a schedule that is "first Monday of the month" or "every 3 weeks" among other things. I stock these up using db-populate; here's some of the population file:

    [sourcecode language='ruby']
    Schedule.create_or_update(:id => 1,
    :schedule_type => Schedule::SCHEDULE_TYPE[:monthly],
    :interval => 1, :description => "Every month")
    Schedule.create_or_update(:id => 2,
    :schedule_type => Schedule::SCHEDULE_TYPE[:monthly],
    :interval => 2, :description => "Every other month")

    Schedule.create_or_update(:id => 4,
    :schedule_type => Schedule::SCHEDULE_TYPE[:weekly],
    :interval => 1, :description => "Every week")

    Schedule.create_or_update(:id => 8,
    :schedule_type => Schedule::SCHEDULE_TYPE[:first],
    :specific => 0, :description => "First Sunday of every month")

    Schedule.create_or_update(:id => 15,
    :schedule_type => Schedule::SCHEDULE_TYPE[:last],
    :specific => 0, :description => "Last Sunday of every month")

    Schedule.create_or_update(:id => 22,
    :schedule_type => Schedule::SCHEDULE_TYPE[:last],
    :specific => -1, :description => "Last day of every month")
    [/sourcecode]

    Then the entry model ties into the schedule model. Here are the important (for this purpose) bits of the entry class:

    [sourcecode language='ruby']
    class Entry < ActiveRecord::Base
    belongs_to :schedule
    named_scope :ready_to_recur, lambda { |date|
    {:conditions => ["recurring = 1 AND next_date <= ? AND schedule_id IS NOT NULL AND next_created = 0", date ]} }
    before_save :set_up_recurrence

    def make_next_recurrence
    if recurring? && !schedule_id.nil? && !next_created?
    entry = Entry.create(
    :entry_date => next_date,
    :reference => reference,

    :recurring => true,
    :schedule_id => schedule_id
    )
    update_attribute(:next_created, true)
    end
    entry
    end

    def set_up_recurrence
    if recurring? && !schedule_id.nil?
    self.next_date = Schedule.find(schedule_id).next_date(entry_date)
    self.next_created = false if next_created.nil?
    end
    true
    end
    end
    [/sourcecode]

    Finally, the whole thing is driven by a rake task that we run every night. This task finds all the entries that are ready to recur and creates the next entry:

    [sourcecode language='ruby']
    desc 'Create the recurring entries for today'
    task :daily_recurring_entries => :environment do
    Entry.ready_to_recur(Date.today).each do |entry|
    entry.make_next_recurrence
    end
    end
    [/sourcecode]

    Double Shot #507

    Wait, it's still July? This month may never end.

    Double Shot #506

    Nothing like a busy day to cut down on my linking.

    • URLAgg - Watch us work - Ever wonder what virtual pair programming looks like? Here's a longish unscripted session from Jeff Schoolcraft and Istvan Hoka.

    • WindyCityRails - Early bird pricing for this Chicago-based conference is ending in just a couple of days, time to make up your mind.

    • input_css - Rails plugin to automatically add sensible CSS classes to INPUT tags.

    Double Shot #505

    Looks like my August hours may be starting to fill out. That was a bit too close for comfort.

    Double Shot #504

    I'm sure someone took the weekend off, but apparently it wasn't anyone whose site I read.

    Double Shot #503

    This seems like a good time to remind folks that I've got time free for new and interesting Rails contracts, if you're looking to pick up an extra developer.

    Double Shot #502

    Apparently delay was on people's mind yesterday.

    Double Shot #501

    Life goes on.

    • Sunspot - Solr-powered search with Ruby syntax, including drop-in Rails integration.

    • Major update to Ruby on Rails OAuth Plugin - Including conversion to a gem.

    • My Thoughts on NoSQL - A reasonable look at some of the current contenders in the non-relational database world.

    • Insurance on Rails - Some tips on rewriting legacy green-screen COBOL apps into Rails. Scary.

    • Gestalt - Ruby and Python embedded scripts in web pages via Silverlight. No thanks.

    • RubyGems 1.3.5 - Another version bump for gems. Looks like just a couple of small bug fixes.

    • Redmine Kanban Plugin - Makes Redmine rather similar to Pivotal Tracker's one-page view of everything.

    Double Shot #500

    Yup, 500 of these things. A bit hard to believe.

    • Rails 2.3.3: Touching, faster JSON, bug fixes - No huge changes, but some important fixes and a few minor features. The current plan is for 2.3.x to update every six weeks until 3.0 comes out.

    • Better rake:routes - Better because it lets you specify a controller and only prints the matching routes if you do.

    • Inquiry - Managed service to handle FAQs for your application. Not clear this is something I'd choose to outsource, but that appears to be the way of the future.

    • constructor - Named argument style initialization for any Ruby class. Not new, but potentially useful.

    • Ruby 1.9.2 preview 1 released - And the march of progress continues.

    • What would you like in a code quality tool? - Cogent is planning a tool that you can just point at your repo. Fill out their survey for free access to the product when it exists.

    • Git User's Survey 2009 - In case you'd like to offer the git developers some detailed feedback on your use of their tool.

    Double Shot #499

    Another productive weekend - may have a new project to announce shortly.

    • What do we need to get on Ruby 1.9? - Wycats inquires. For me, the fact that I can't run a Rails app with a database using mainstream gems is a showstopper. Not interested in science projects when I'm trying to do paying work.

    • Memcached 1.4.0 - Now released, including dead-simple Amazon EC2 AMIs for those who want to cache in the cloud.

    • Nmap 5.0.0 released - I used port scanners a lot more when I was on Windows, but I still keep some eye at what's going on.

    • Kii - A new entrant in the open-source Rails wiki sweepstakes.

    • Test::Unit 2.0.3 - Huh, I hadn't realized T::U was still under active development.

    • The Lazy developer: Tweak your MySQL - Elad offers some memory tuning suggestions.

    • Big Old Rails Template - I've done some updating to this template, which I talked about here.

    Double Shot #498

    Early morning with small child and thunderstorms.

    Double Shot #497

    Up late deploying stuff last night, so just a couple of quick links this morning.

    • snail - Start of an ambitious attempt to build a plugin to format international mailing addresses.

    • Firebug 1.4.0 - Officially released, and nicer than 1.3. Of course those of us on the bleeding edge have moved to 1.5 alpha builds already.

    Double Shot #496

    It looks like the Fairy Godmother Department's lunch hour may be over.

    • Many Ways to Tag Taggables - Tobias hunted down all the Rails tagging libraries he could find. Looks like he settled on acts_as_taggable_on, which is the one I use too.

    • fleakr - Flickr API integration gem recommended by a couple of my readers.

    • read_from_slave - Read your Rails data from a MySQL slave database, while ensuring that writes go to the master database.

    • Programming Contest! Win iPhone 3GS & $2,000 Cloud Credit - Engine Yard is planning a contest that is going to make Twitter even more annoying for a while.

    • Choosy - OS X utility ($12) to let you choose a browser when you click on a link.

    • Ruby Versions - SSH access to a bunch of new and archived flavors of Ruby.

    Double Shot #495

    Time to get back on the daily sales and marketing wagon. Contract, where are you?

    • Build Guild - Spreading social/technical gathering of web folks. I'd be tempted to start an Evansville/Newburgh chapter if I actually knew any other web folks around here.

    • wikicloth - Mediawiki markup for Ruby.

    • flickr_fu - I may need a flickr interface in Ruby soon. This one looks promising.

    subscribe via RSS