Posted by Chuck Vose
Thu, 26 Apr 2007 21:25:00 GMT
Arrow keys doing funny things when you use vi in iTerm 0.9.5? It’s because we’re too used to messing with things. Set your Default bookmark’s keyboard type back to Global.
“When the terminal type of your sessions is set to one of those “xterm” types, iTerm handles the arrow keys, the home key, and the end key in a special way.” says the FAQ while not actually addressing the solution.
But who can complain? Global works well now! Hooray!
Posted in Programming | Tags arrow, iTerm, keyboards, keys, vi, vim
Posted by Chuck Vose
Wed, 25 Apr 2007 20:21:00 GMT
At On & On Creative we have a lot of sites on a common rails backend. It’s incredibly flexible so we can offer a lot of support to customers but because there are so many customers with different needs testing has become a huge pain. Not only does it let us run tests custom to each client, it provides a way to import the data to the test db really easily and it’s way faster than loading the fixtures each time you start a test. Yay!
After googling around I happened upon this caboo.se article about how to run without fixtures at all. It’s a very indepth article with lots of good things in it; far be it for me to try to compete.
Instead, here’s the low down on how we prepare each of our sites for testing.
Add the following to the end of your rails_root Rakefile:
class Rake::Task
def detract(prerequisite)
@prerequisites.delete(prerequisite)
end
end
%w(units functionals integration recent uncommitted).each do |task|
Rake::Task["test:#{task}"].detract('db:test:prepare')
Rake::Task["test:#{task}"].enhance(['environment'])
end
Add the following to lib/tasks/fixtures.rake. Make sure to look at the two commented lines:
# This code courtesy of the "Rails Recipe's book":http://www.pragmaticprogrammer.com/titles/fr_rr/ I believe.
namespace :db do
namespace :fixtures do
desc 'Create YAML test fixtures from data in an existing database. Defaults to development database. Set RAILS_ENV to override.'
task :dump => :environment do
# Remove the limit if you want to. It's a timesaver mostly
sql = "SELECT * FROM %s LIMIT 0,1000"
# Add tables you don't want dumped.
skip_tables = ["schema_info", "plugin_schema_info", "engine_schema_info", "sessions"]
ActiveRecord::Base.establish_connection(:development)
(ActiveRecord::Base.connection.tables - skip_tables).each do |table_name|
i = "000"
File.open("#{RAILS_ROOT}/test/fixtures/#{table_name}.yml", 'w') do |file|
data = ActiveRecord::Base.connection.select_all(sql % table_name)
file.write data.inject({}) { |hash, record|
hash["#{table_name}_#{i.succ!}"] = record
hash
}.to_yaml
end
end
end
end
end
Then the fun easy stuff happens:
rake db:fixtures:dump RAILS_ENV=production
rake db:fixtures:load RAILS_ENV=test
rake test:plugins PLUGIN=your_plugin
If you want to commit the fixtures to the repo you can but it seems a waste to me since you might be regenerating them often.
Also, check the two comments in the fixtures.rake, it could be doing things you don’t expect.
Posted in Rails, Programming | Tags fixtures, plugins, Rails, rake, testing
Posted by Chuck Vose
Sun, 22 Apr 2007 23:56:00 GMT
Background / Analysis
Recently a fellow asked me to help him diagnose a slowdown in his rails stack at the Ruby Brigade meeting in Seattle.
After going through the normal procedures of checking mysql indexes, talking about caching, and checking the code for bizarreness I still couldn’t find anything really out of the ordinary.
Finally we turned to Firebug and found that the images were taking an eternity to download. This had happened to On & On Creative earlier on this year so the solution was quick at hand.
Solution
RailsMachine and the mongrel docs themselves recommend the following code for apache:
# Redirect all non-static requests to cluster
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://NEF_mongrel_cluster%{REQUEST_URI} [P,QSA,L]
But there’s a hidden gotcha that I still haven’t fully figured out. Sometimes, usually when images aren’t in the top level of /images, apache will not match the RewriteCond and pass the image to mongrel instead of loading it itself.
Mongrel is terrible at serving images and static content from the filesystem. In the words of Zed Shaw, “This means mongrel will serve images, javascript, files, and everything else. It’s quite fast at this, but Apache can do it better.”
1 http://mongrel.rubyforge.org/docs/apache.html
So if you see a slowdown on images, you run mongrel through apache’s mod_proxy_balancer, and you used the config from the mongrel website or from RailsMachine/Slingshot’s capistrano script, try this code and see if it helps:
# Redirect all non-static requests to cluster
RewriteCond %{REQUEST_FILENAME} !.*(jpg|gif|png|js|css)$
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://NEF_mongrel_cluster%{REQUEST_URI} [P,QSA,L]
Did It Work?
Checking the rewrite logs
My computer is exceedingly slow so I can’t rely on my browser to tell me how fast an image is really downloading. If you’re like me it might be worth watching the rewrite logs to see if the images are being passed through rather than being rendered.
Drop this into your virtual host configuration right after the RewriteEngine On:
RewriteLog logs/myapp_rewrite_log
RewriteLogLevel 9
Then check the apache logs folder (often /var/log/httpd or /usr/local/apache2/logs) for the myapp_rewrite_log. After loading a page it should look something like this:
init rewrite engine with requested uri /images/drivers_panel.jpg
applying pattern '^/(.*)$' to uri '/images/drivers_panel.jpg'
RewriteCond: input='/var/www/apps/NEF/current/public//images/drivers_panel.jpg' pattern='!.*(jpg|gif|png|js|css)' => not-matched
pass through /images/drivers_panel.jpg
Rather than this contrived example:
init rewrite engine with requested uri /images/extra/dirs/my_image.gif
applying pattern '^/(.*)$' to uri '/images/extra/dirs/my_image.gif'
RewriteCond: input='/var/www/apps/myapp/current/public/images/extra/dirs/my_image.gif' pattern='!-f' => matched
rewrite '/images/extra/dirs/my_image.gif' -> 'balancer://myapp_mongrel_cluster/'
forcing proxy-throughput with balancer://myapp_mongrel_cluster/
go-ahead with proxy request proxy:balancer://myapp_mongrel_cluster/ [OK]
Checking the rails logs
The rewrite logs are cool and handy so I put them first but you should also be seeing entries in your development.log or production.log.
Try the following snippet, you may be surprised to see the results:
cat development.log production.log | egrep '(jpg|png|gif|js|css)' | less
Posted in Rails | Tags Apache, firebug, image, mod_proxy_balancer, mod_rewrite, mongrel, proxy, Rails, slow
Posted by Chuck Vose
Sat, 17 Mar 2007 21:18:00 GMT
If you’re getting errors about Verdana not being found, specifically:
“unable to read font `/Library/Fonts/Verdana’ (Magick::ImageMagickError)”
try:
sudo apt-get install applesystemfonts
cp /sw/lib/X11/fonts/applettf/Verdana.ttf /Library/Fonts/
sudo gem install rmagick
Posted in Rails
Posted by Chuck Vose
Thu, 08 Jun 2006 16:21:54 GMT
My boss doesn’t know the phrase “Woot, ding!” or the proper response of “gratz”; I don’t know whether to feel sympathy for him or be greatly relieved…
Posted by Chuck Vose
Wed, 24 May 2006 20:13:00 GMT
One of the things sorely missing from Rails (and with good reason) is a function to find all the children in a tree. Below is my attempt at it, you can drop it in any model that acts_as_tree and call all_children to get a flattened list of all children, grandchildren, etc.
def all_children
all_children = []
all_children << list_children(self)
return all_children.flatten
end
private
def list_children(branch)
all_children = []
for child in branch.children
all_children << list_children(child)
end
if branch.children.empty?
return branch
else
all_children << branch
return all_children
end
end
There’s probably a lot of reasons for this not existing but sometimes you need the limited functionality that this provides and can work within the constraints of making sure that no children have two parents.
The other approach is to use acts_as_nested_set but you sometimes lose valuable data such as the self_and_siblings function from acts_as_tree.
Posted in Rails
Posted by Chuck Vose
Mon, 08 May 2006 07:19:00 GMT
One of the biggest fears of all system admins and developers is publishing work to a live server and having it break everything. Naturally we all go to great lengths to make sure this doesn’t happen but even the most well-tested code in the simplest environment still breaks sometimes.
In addition to these fatalities is the less intrusive but equally damning maintenance that sometimes just has to happen in the middle of the day whether there’s users in the system or not. I’m sure you can think of a few scenarios and horror stories.
At any rate I’ve come to realize that it’s extremely important to be able to tell the people in the system that things are going to break for a bit. This is fortunately extremely easy in Rails; a quick three or four lines in the application.rb will do it. In PHP it’s easy if there is even a little planning that went into the project.
Despite the ease I don’t think this is very common in the world of small-to-medium businesses and this seems like a shame.
Letting your users know what’s about to happen or what happened a moment ago will increase their sense of security in many cases and in the very least will keep them from calling you in a panic.
Blissful silence.
Posted in Programming | no trackbacks
Posted by Chuck Vose
Mon, 08 May 2006 05:15:00 GMT
Intro and Concept
One of the first things I tried to do in Rails was to figure out how to make a nice, generic website that anyone could update. After about sixteen iterations I’ve finally stumbled on one that I think will finally work.
As of now it’s only partially complete. I’m really only using this method to generate the titles and meta information but each time I have to make a change to the website I find more and more information going into what I call the welcome message.
The idea is as follows:
- Making an action for each page is almost always rediculous and hard to update. So that’s pretty much out.
- Making a loader page that loads a Page object and displays the content works for the most part if you don’t have special content (and as long as you remember to change the :parameter if you ever try to paginate a series of pages.)
- Making the content an optional part of an initialize function in the application.rb will ensure that you can always access page related information on any page (ever dynamic pages).
In order to do this I have a function called `initialize` in my application.rb that parses the @params and looks through the database for a entry in the welcomes table. As I said, I’m only using parts of this but it would be easy to extend; initially this was just to display a welcome message on any page they wanted.
If there’s an entry in the welcomes table with controller params[:controller], action params[:action], and id == params[:id], then it returns a raft of information such as the page title, a background image, meta values, etc. These override the defaults in the page (and there must be defaults) and make the page dynamic.
The beauty of this approach is that it’s very easy to take an action that actually has an action (such as /admin/delete_user) and pop a new title on it, or meta values, or custom css, or whatever you can think of. If you have this table contain content you could have a blank template by default that gets overridden by the content in the row.
Steps
- Create the table and figure out what you want to be able to apply to any action. Titles and meta values are a great start. Make sure to make a unique index on the controller, action, and id rows (This is very important).
- Create an initializer function that searches this new table for the controller, action, and id in the params.
- Create before_filters in each controller you want this to be available in. This may be possible in the application.rb but I haven’t tried it (and it can be extremely picky).
- Create forms that make editing these items easy. Definitely note that it’s entirely possible to have /page/page_loader override /page/page_loader/3. This may be intended and a good idea but it’s pretty important to note that it could completely wreck things until you figure out why things aren’t working.
- Lastly, create sane defaults in the initializer function for pages that don’t have entries. This is incredibly important.
Conclusion
I realize that I breezed over all the details, this was intentional. Because I’ve not actually done this entirely in a site (only as far as titles and whatnot) I don’t want to give fake code samples. I’ll get there eventually but it may be a while until I start a new project.
At any rate, the idea is sound and is working in part very well in my sites so far. There are a lot of gotchas, mostly in the defaults, but there’s also a lot of room to innovate. The idea of the defaults cascading is a wonderful extension especially when so many sites are in tree/nested set formations.
Keeping the attributes away from the actual code is a great way to make it easy for customers to interact with the website. Customers often want to change little things and it’s important that they be able to change as much as possible even when the code is mostly hidden in a template or you’ll end up making little changes for the rest of your existence.
Posted in Rails, MySQL | no trackbacks
Posted by Chuck Vose
Fri, 21 Apr 2006 14:32:28 GMT
I’m finally learning, oh yes.
The reason IDE’s make it so difficult to copy folders around is because it’s an incredibly difficult process. In order to copy in Subversion you have to copy the folders/files, delete any .svn directories in each level of a folder, then those folders/files have to be added to the repo.
Very complicated process which has been killing me lately. I should have known better; how not DRY of me to copy a folder…
Posted in Programming | no trackbacks
Posted by Chuck Vose
Thu, 20 Apr 2006 18:39:00 GMT
Holy crap I finally figured out why unit tests exist! To give me something to think about in the shower. Yep, simple as that.
No, wait, there are two really good uses off the top of my head: packaging and testing filesystem crap.
The first use is if you’re exporting a plugin for later use (or for general distribution). In this scenario there’s a fairly good chance that the user importing your plugin has messed up their install or is using a database that isn’t the same version or even the same type as the one you’re using.
In either case if you have unit tests and none of them fail then you know that the database probably isn’t at fault.
The second use is for filesystem crap. I can still count the number of times I’ve messed up the permissions on a folder only to find it after a half hour of debugging. This should never happen and there are wonderful tools to prevent it. `ri File` and `ri FileUtils` should get you started if you’re curious.
Specifically I’ve been working on a photo upload admin because I don’t understand file_column. In this I occasionally have to make a directory (okay, every time I upload something that isn’t a graphic) and it would be really nice to know that when I post it onto our production server that it’ll work when I release it into the wild.
Under this column is a wonderful addition to test_helper to check that things are correctly set in other places. Since rake is seperate from the dispatchers it could check their permissions, check the permissions of the public and log folders, and a myriad of other wonderful tests that could help newbies get on their way.
Rake is already pretty good at this but it serves as an excellent example of one use for unit testing.
Posted in Rails, Programming | no trackbacks