Programming

I am going through the Type Aloud code trying to improve queries, implement some fragment caching, and generally clean anything up that I can before flipping the proverbial switch on this bad boy. I came across something a few weeks ago that, combined with the awesomeness that is Arel, makes my life a hell of a lot easier writing queries.

These named scopes have been around in Rails for awhile now, but as always I am coming late to the party. Because Type Aloud contains “draft mode” where stories and chapters can both be in an unpublished state I need to be able to call only the chapters and here is a quick, simple way to do that on the model.

scope :published, lambda {
   joins(:story).where(:disabled => false, :stories => {:disabled => false}).includes(:story, :user)
}

The named scope will filter out any chapters that are not published or any chapters in stories that are not published. This is very important when displaying, let’s say, a random chapter for reading that may not have yet been published in an existing story. The last statement at the end there will eager load the story (and user) because there really is never an instance where I don’t want the story (user) records associated with this. Here are the queries that are executed.
And here and the queries that are executed from this little snippet.

SELECT `chapters`.* FROM `chapters` INNER JOIN `stories` ON `stories`.`id` = `chapters`.`story_id` WHERE (`chapters`.`disabled` = 0) AND (`stories`.`disabled` = 0)
SELECT `stories`.* FROM `stories` WHERE (`stories`.`id` = 1)
SELECT `users`.* FROM `users` WHERE (`users`.`id` = 2)

And of course, this is what the signature looks like from the controller.

@chapter = Chapter.published.limit(1).first

For this particular operation it resulted in a 0.5ms improvement in time spent during the Active Record phase. That may not sound like a lot, but it actually is a 19 percent time optimization. Good stuff!

I have been running into a problem recently with my development over at Type Aloud; some of my column data types differ from MySQL (my development database) and PostgreSQL (my production database). I store two copies of the story in the database: the first is the “human readable” version that uses the Markdown syntax and the second is the HTML version of that syntax so it is easier to fragment cache and display when someone is viewing the chapter. This problem is particularly irritating because when it first happened in MySQL the text was merely truncated, but in PostgreSQL it correctly does not allow the insertion into the table if the text is too long.

For the past couple of days I have been doing some light searching trying to figure out a way to have a RDBMS specific database migration, and I once I did some pecking in the ActiveRecord::Migration class I was able to figure this out pretty easily. I figured that I would share it below since it took me a little while to find it. Now normally I do not believe in migrations being platform specific, but in this case because I wanted to actually have the application work on two types of platforms (in this case, two RDBMS).

class AddLongtextToPostgresql < ActiveRecord::Migration
  def self.up
    case ActiveRecord::Base.connection.adapter_name
    when 'PostgreSQL'
      execute "CREATE DOMAIN longtext as text"
      execute "ALTER TABLE chapters ALTER COLUMN html TYPE longtext"
      execute "ALTER TABLE chapters ALTER COLUMN body TYPE longtext"
    else
      puts "This migration is not supported on this platform."
    end
  end
 
  def self.down
  end
end

One of the features that was omitted from the Type Aloud beta launch earlier this year was the ability to work on unpublished stories and chapters. My testing period in early December showed that the workflow of most of the users was to develop their story in some offline editor such as Word or Pages first, and then pasting in the finished product into the text area making slight modifications when needed for markup.

A few friends brought this to my attention and this afternoon I started cooking up some changes to make it possible to “publish” and “depublish” stories and chapters from the website. Any story that is created first begins in an unpublished state (draft mode) which needs to be explicitly toggled by the owner before it goes live on the site. At any point in time the user has the option to take their story offline making it unpublished again. It should then immediately become unavailable across the site. I am working on making sure that comments and subscriptions correctly disappear when a story becomes unpublished as well.

One good thing is that I do not plan on deleting subscriptions and comments on stories (chapters) when someone decides to depublish a story. This is assuming that the story will eventually come back because it was not deleted. When a story is deleted, the chapters, comments and subscriptions will follow.

It has been a few weeks now since I launched the “unofficial” Type Aloud beta and I have been quietly working on improvements after having some good friends and family pound the site. My aim is to have announce a bigger and better version within the upcoming weeks (sooner, if possible) as I believe there are only a few kinks left to work out of the system. At this point I am going to take some time and actually write some content for the site and work on promoting this bad mamma jamma.

This week’s work schedule includes:

  1. Getting the commenting system on stories and chapters working properly.
  2. Finalizing unpublished for stories and draft mode for chapters.
  3. ‘Report this story’ (and chapter) button for flagging either spam or inappropriate content.
  4. Fixing some minor style and navigation issues.

Some longer term issues will be working on proper poem support as well as permissions on story and chapter viewing. I hope to have the beginnings of these worked out in the upcoming weeks after the unpublished, flagging and draft modes are completed. Some improvements that are in the pipeline but aren’t dated yet: user (crowd source) tagging and descriptions, badges and search.

Jan
17

I have been waiting a very long time to be able to say these words. For the past couple of months I have had a bottle of champagne sitting around, waiting, for me to finish the site enough to launch it to the public as a beta. I am glad, honored and relieved that the day is finally here that I can crack open that bottle and drink it (actually, finishing up the last bit of it now). My close group of friends have been pounding away at the site already reporting bugs that I promise I will get on top of as soon as I can.

Type Aloud has been a dream of mine for at least four years now. I envisioned a writing and reading community where people will not only be able to share their stories (and poems) but also get collaborative feedback for both editing, and hopefully, print publishing. Some of the most intriguing writing I have read came from people that were not published professionally. I look forward to being able to read (and write!) much more than I have in the past with this service. My primary goal is not to be profitable: Type Aloud is a service that I want to use myself. I am a lucky man if I am able to break even.

If you have a couple of minutes, or even better some writings that you want published, please take the time and head on over to the open beta page and sign up for a free account. Remember that all work posted to Type Aloud you retain ownership to. In the coming days I will have a proper copyright agreement up on there which will basically amount to you giving us the permission to publish it on the website.

There is much, much, more to be done, but I feel as if the first hurdle has already been past.

The holidays always seem to creep up on me.

This is the first holiday season I have been at my new gig and we’ve been quite busy busting our asses to get everything in line for next year. So the past few weeks I haven’t had a lot of time to get work done on Type Aloud but that all changed earlier this week.

For the past couple of weeks I have been sitting on the code and focusing on getting the design done. That meant learning a lot of interaction in Rails that I did not know before, working on some CSS beautification and generally cleaning up the god awful standard forms that are generated through the Rails scripts. I decided earlier in the week that I would send out an e-mail to all of my testers and let them know I am planning on pushing a release candidate for their testing.

After some successful UX testing tonight I am going to try to push a new candidate each night for the foreseeable future. My plan is to release to beta on New Years eve flipping the switch on-or-around midnight in a ceremonious occasion which will involve the consumption of a lot of booze. But all that hinges on the UX and integration/functional testing that myself and my testers are going to perform.

Next week the goal is to send out the invite to everyone who has signed up for early access and shut off the form in preparation for the switch. So if you’re a writer, reader or poet and you’re interested in getting involved and helping me out feel free to sign up with your e-mail address. Its free, and I won’t sell them to some clearing house.

Good times are ahead!

I have been doing some hacking on Type Aloud and I was looking for an answer to a question that was bugging me: what is the best way to use link_to with a vanity URL setup? I asked my question over at Stack Overflow and I figured I would post the answer to the question here in case anyone was looking as I was.

Inside of my application the route setup is quite simple.

match '/:id', :to => "users#show"
match '/:user_id/:id', :to => "stories#display"

Now I want to be able to make a very simple call inside of my view logic which will print out a pretty URL. Since I am using resource definitions for several controllers I cannot use the normal Rails URL helpers. The answer to my question is actually quite simple, and I already have used it before, but what I wasn’t doing was correctly passing through the objects into the helper. Here are the changes that you need to make to those routes above.

match '/:id', :to => "users#show", :as => "vanity_show_user"
match '/:user_id/:id', :to => "stories#display", :as => "vanity_show_users_story"

And finally inside of your view you would build both links like the following.

<%= link_to @story.name, vanity_show_users_story_path(@user, @story) %>
<%= link_to @user.name, vanity_show_user_path(@user) %>

I hope that this helped you out as much as it helped me! Kudos to the amazing Ryan Bigg for the original answer.