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.

Mocked out ActiveRecord for testing plugin

Posted by Tim Connor Fri, 20 Oct 2006 06:06:00 GMT

I mentioned this in my previous post, but to make my plugin easier to test I tried to make it not need to touch the DB, which was interesting to do, given that scaffold_resource is very much tied to a model. This was a big inspiration and this the final (as of now) result:


class Resource < ActiveRecord::Base
@count = 1 def self.count() @count end
def self.columns() columns ||= []; end def self.column(name, sql_type = nil, default = nil, null = true) columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null) end def self.find(param) return param == :all ? [Resource.new{ |m| m.id = 1; m.name = 'bob' }] : Resource.new{ |m| m.id = 1; m.name = 'bob' } end def save() @count += 1 and return true if valid? end
def destroy() @@count -= 1 end
column :name, :string
end

Manually setting id in Rails 2

Posted by Tim Connor Fri, 20 Oct 2006 00:12:00 GMT

In testing DynamicScaffoldResource, I have been working on sort of mocking/overloading ActiveRecord so that it doesn’t touch the DB, so I can minimize how much it depends on the root Rails environment to test, since it’s a plug-in.

class Resource < ActiveRecord::Base
  def self.columns() @columns ||= []; end
  def self.column(name, sql_type = nil, default = nil, null = true)
    columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
  end
  def self.find(param)
    return param == :all ? [Resource.new(:id => 1, :name => 'bob')] : Resource.new(:id: => 1, :name => 'bob')
  end

  column :id,            :integer
  column :name,          :string

  validates_presence_of :name
end

Well Rails treats the id as a special field, since it is. I tried letting it implicitely add it, and explicitely as above, but there was no way I seemed to be able to set it manually and access it (maybe the problem is prior to a save?), so my edit named route in the view wouldn’t choke (the show path had no problem with the nil, which I might not have caught for a while). While there is probably some way to open up access to the id column, this mailing list post opened up an alternative that works, just use:


Resource.new{ |m| m.id = 1; m.name = ‘bob’ }

curl-ifying Firefox

Posted by Tim Connor Tue, 17 Oct 2006 23:10:00 GMT

I finally found an extension that lets me use Firefox for testing that I would previously had to use curl for, namely submitting text/xml only requests (for testing REST APIs, for example) or similar. I thought ModifyHeaders would do the trick, but I never really got that working. But TamperData is exactly what I wanted.