Rails 2 foxy fixtures and named_scope/has_finder closure issues
has_finder :all_active, { :conditions => {:status_id => Status.active_ids} }
This work in production, where the ids don’t change, but since we are using the newer fixture approach on this model the ids are created dynamically. Given how fixtures load, the table will probably be populated with the old values, at parse time for that class, then the test will run, and the fixtures will reload, and they will not match anymore.
This is easily fixed, when you realize what is happening:
has_finder :all_active, lambda {|| { :conditions => {:status_id => OtherModel.active_ids} }}
Running Internet Explorer on Mac through Wine
While Parallels is awesome and all, for web developers, I got tired of having to run a whole VM at all times for testing. I decided to see if I could get IE running through WIne, and just use my Parallels install for a final browser test. I basically followed these directions. with a couple additions:
- X11 wasn’t running my .bash_login, so I moved the entire file to .bashrc, and then made a new one that sourced (“source ~/.bashrc”) so that both the OS X terminal and X1 got all my bash set-up stuff.
- I added “export DISPLAY=localhost:0.0” to my new .bashrc
- I copied the contents of my Basecamp/Parallels install font folder to my ”.wine/drive_c/windows/fonts/”
So now I can just run IE through X11 for my day to day testing. I didn’t get IE7 running, because the betas of that had some issues on OS X, but when they have it polished I’ll give it another shot.
autotest reminding you to test one thing at a time 2
I was fixing a bug via TDD (Test Driven Development) and having a bit of trouble. I couldn’t quite get my test to test for the conditions that prevented the bug. As I went upstairs to grab a snack, I realized that my problems was I was conflating two tests together.
I use autotest a lot, but sometimes when I’m doing something I shut it off, because I want to manually run one particular set of tests at need. With a system not quite speedy enough, that sometimes makes sense.
But, as part of my Eureka moment I realized that the reason I had turned off autotest, in this case, was that I wasn’t taking small enough baby-steps. I was breaking too many things at once. If I had tested for each individual thing, and developed by each small test, like I realized to do later, I could have kept autotest on without it blowing up at me.
Dynamic Scaffold Resource test helper now sucks less
I added a couple instance variables that can optionally be set so that the test helper can actually be used in something beyond the skeleton of the plugin’s own test environment. You can use it in an authenticated environment now, because you can set @scaffold_session_params and you can use it on resources that have validation in their models, because it will use @scaffold_dummy_object for the create and edit test, if you set it.
Didn’t change the core of the plugin itself, but the testing piece really was useless, so I had to add this just to use it on the project I made the plugin for in the first place.
Debug failing test with assert_dom_equal
assert_dom_equal('foo', @response.body)
right before the failing tests and you’ll get the full response body for the test dumped to your console.
It’s useful for discovering things like the fact that you forgot the = in <%= yield %> in your test layout.
"Extending" classes: redefining an instance method from a module via alias_method
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'
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
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
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
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.
Older posts: 1 2

Articles via rss or email