Typo Plugin is live : permalink with ID is 1.0ish 4

Posted by Tim Connor Tue, 24 Oct 2006 18:51:00 GMT

So typo-permalink-with-id is fully operational. Your Rebel friends are doomed. For subversion or other project details go the project site at http://code.google.com/p/typo-permalink-with-id/.

To see it in operation try going to this article via the wrong permalink, like /articles/2006/10/24/25-tims-typo-plugin-is-so-cool.

Funny Rails shirts : test of the emergency broadcast system

Posted by Tim Connor Tue, 24 Oct 2006 18:46:00 GMT

This is a test of the new plugin.

Hey, look, funny Rails shirts

"Extending" classes: redefining an instance method from a module via alias_method

Posted by Tim Connor Tue, 24 Oct 2006 07:50:00 GMT

The Typo plugin is finished, but it’s gotten late and I should review it before deploying and releasing it into the wild. A quick post on more I learned, though….

I had to do a fair bit of research to get the second part of the plugin working – the part where I overload/redefine a controller method from my plugin, specifically the permalink method of an ArticlesController. You can spend a lot of time reading about the intricacies of how mixins work in ruby, without getting working code. Dig through ruby-talk and you’ll learn about the difference between include/extend, what happens to “self” in different cases, the reasons for the odd module nesting and, ultimately why the ClassMethods convention caught on.

It’s not so straight-forward to overload a method, apparently, in ruby. God knows I tried each different nesting include/extend combo 6 times, with no luck. Then I came across an easier way for my case, alias_method. While that usage wasn’t exactly what I wanted, the only problem was that it did too much. I just had to drop off the unneccessary bits, and walla:

module TypoPermalinkWithId
  ....

  module ModifyArticlesController
    def self.included(base)
      base.class_eval do
        alias_method :permalink, :modified_permalink
      end
    end
    def modified_permalink
      article = this_blog.published_articles.find_by_permalink(*params.values_at(:year, :month, :day, :title))
      redirect_to article.permalink_url and return if article.nil? and article = Article.find_by_id(params[:title].to_i)
      redirect_to article.permalink_url and return if article.nil? and article = Article.find_by_title(params[:title])
      display_article(article)
    end
  end
end

ArticlesController.send :include, TypoPermalinkWithId::ModifyArticlesController

Testing plugins : Remember to require 'action_controller/test_process'

Posted by Tim Connor Tue, 24 Oct 2006 07:32:00 GMT

Before I could even get started on actually coding the second piece of the Typo plugin, I spent a lot of time wondering why I was getting the following error when trying to run my tests:

NameError: uninitialized constant ActionController::TestRequest

I kept looking at the the other plugin I’ve been working on which the tests run just fine on and scratching my head. It turns out in the working plugin I had stashed the “require ‘action_controller/test_process’” line in the testing controller I made, so I didn’t notice the difference. I’ll be moving that back for clarity tomorrow, but remember kids, if you are doing controller driven tests outside of Rails (like in a plugin) put in that line.

ActiveRecord Observers are a very handy thing for plugins

Posted by Tim Connor Sun, 22 Oct 2006 21:58:00 GMT

While developing the first piece of the typo-permalink-with-id plugin I spent a lot of time trying to get the module extend/include and module_eval stuff just right so that my code had everything it needed to not through an error when trying to add a after_create to the app code itself. After a bunch if google around I found exactly what I need in teh v2 Agile book. It wasn’t something plug-in specific, but it is a godsend to plugin writers: ActiveRecord:Observer.

Instead of trying to get your after/before code properly mixed into the app code, you can have it nice and cleanly attached via an Observer. All of a sudden my code became very simple.


module TypoPermalinkWithId
class ArticleObserver < ActiveRecord::Observer
observe Article
def after_create(article)
article.permalink = “#{article.id}-#{article.permalink}”
article.save
end
end
ArticleObserver.instance
end

Testing plugins : loading fixtures and environment

Posted by Tim Connor Sun, 22 Oct 2006 21:44:00 GMT

One of the first things I learned working on the typo-permalink-with-id plugin was how to load fixtures from a plugin. I had previously just been mocking out ActiveRecord, but the Typo object model is complicated enough that it was easier to just schlup their envirnment.rb and then load their fixtures into my tests.


require ‘test/unit’
require ‘active_record’
require ‘active_record/fixtures’
RAILS_ENV = “test”
require File.expand_path(File.join(File.dirname(FILE), ‘../../../../config/environment.rb’))

class TypoPermalinkWithIdTest < Test::Unit::TestCase

def setup fixtures_dir = File.expand_path(File.join(File.dirname(FILE), ‘../../../../test/fixtures’)) Fixtures.create_fixtures(fixtures_dir, File.basename(“blogs.yml”, ‘.*’)) Fixtures.create_fixtures(fixtures_dir, File.basename(“users.yml”, ‘.*’)) end def test_fixtures_loaded assert_not_nil Blog.find_by_id(1), “blogs.yml not loaded” assert_not_nil User.find_by_id(1), “users.yml not loaded” end

Edit: This idea slightly cribbed from Loading Fixtures in a Migration

Typo Plugin : permalink with ID

Posted by Tim Connor Sun, 22 Oct 2006 21:17:00 GMT

Questions about what dynamic-scaffold-resource does arose, so I was going to write a post about that, as a warm-up for actually doing the documentation. But, then I got distracted by a blogging issue, and ended up solving that with another plugin.

As I mentioned in this post I’ve been wanting to keep Typo’s friendly permalink URL scheme, but mildly modify it to preface the title with the id, allowing for changing the title part of the permalink, but still have it match based on the id. Well, as I was about to write my other post, I noticed that one of the links that got out in the wild before I changed my permalink scheme was the 4th Google result for rails named routes. The result was pointing to a “no post found page.”

Well I did a temporary fix quickly with a little .htacces rewrite magic, but that made me more determined to actually have good fix along the lines I wanted of being able to find the article via an ID prefix, text changes aside.

So I checked out a copy of Typo trunk and messed around with it to see what it would take. I got the code working, after some exploration, and then started porting it to a plugin. Thus I know the functionality works, but it isn’t quite ready for release, as one of the two pieces is still just in the Typo code modifcation.

So what exactly does the tyo-permalink-with-id plugin do? It adds an after_create (since you don’t know the id until it after it has been saved to the DB) hook on the article to prefix the id to the title in the permalink (this is the part already moved into the plugin).


after_create do |article|
article.permalink = “#{article.id}-#{article.permalink}”
article.save
end

It also adds some logic to the code that displays the article based on the permalink. If the full permalink (with ID) isn’t found, look for the article first by the ID prefix, and then by the whole permalink as title (smooth upgrading for your articles which predate this scheme). If the article is found either of those ways it redirects via a permanent-redirect/301, not a 302, since that is where it should really be to the proper permalink address. If it’s not found, it finally falls back to the standard Typo “post not found” message (which I want to upgrade next – make it give a link to the browse by date for that date).

def permalink
article = this_blog.published_articles.find_by_permalink(*params.values_at(:year, :month, :day, :title))
redirect_to article.permalink_url and return if article.nil? and article = Article.find_by_id(params[:title].to_i)
redirect_to article.permalink_url and return if article.nil? and article = Article.find_by_title(params[:title])
display_article(article)
end


So I just need to port that last bit over to the plugin, and we are good to go, and I’ll post an update. I’ll also be posting some bits I’ve learned in doing this. Actually these side-diversions from my main project are definitely helping my Rails and ruby knowledge, which will benefit that project.

User-friendly RESTful permalink

Posted by Tim Connor Wed, 18 Oct 2006 16:23:00 GMT

So I’ve taken to changing my permalinks ala: http://www.notsostupid.com/blog/2006/07/07/urls-on-rails/. Of course, Typo already has user-friendly slugs, but I am now prefacing the article id to the title, for the permalink. My thinking being it would take a minor patch to Typo to allow for this sort of routing, and suddenly I have the freedom to rename my article and permalink at will, without making old links obselete. I mean who hasn’t realized a glaring typo AFTER an article is published. Well, if one ever has readers (not me, of course ;)) then you can’t just go and correct it, without making potential links out there incorrect.

Yes, I realize this scheme isn’t actually RESTful, it just came up in looking into REST stuff, and has some potential advantages.