Archive for June, 2005

odds and ends

It seems that if you use find_first(:id) and are in production you get caching even if :id changes. I had this in several places in clubrs and changing the calls to find() fixed the issue.

This is cool. I use a void field instead of deleting records so FK constraints won’t fail and so the data is there if it ever is needed again.

I had a validation for User :login field:

validates_uniqueness_of :login

And the problem was if a user was voided, the record was still in the db and so the validation would fail, even though I’d like it not to.

Dig into ActiveRecord and find the magic :scope attribute. You send this along and only records that match the value of your new record for the given scope field will be returned:

validates_uniqueness_of :login, :scope => "void"

The new record had a default value of 0 for void; the old voided record had a 1 and so wasn’t considered in the validation.

Worked like a charm. Every time I think I’m going to have to extend the framework or hack around it I seem to find a nice little path already trodden. :)

Validating a date

I can’t find a built-in rails method to validate a given date. E.g., that February 30th should not be allowed for a date field. However, rails does throw an exception which you can catch and add your own error.

begin
  success = @person.update_attributes(@params[:person])
rescue ActiveRecord::MultiparameterAssignmentErrors
  @person.errors.add(:birthdate, ' entered is not a valid date')
end

Somebody let me know if I’m missing something here. It seems that since this exception is thrown that the framework would have the validation available.

Where the page cache doth lie

So I had some pages I was trying to update, but after making the changes I didn’t see them reflected. Just basic html layout stuff. I was sharp enough to remember I’d played with page caching the night before:

caches_page :signup, :login

I’d enabled caching in development mode by adding this to the end of environment.rb:

ActionController::Base.perform_caching = true

I switched that back to false and restarted the server, but the pages were still not updating. I figured they must be written out somewhere, but I couldn’t find where the default path was.

I looked in the action controller docs and read all about action caching, page caching and so forth, but didn’t see anything that pointed to why I couldn’t get my pages updated.

Finally, a while later I was syncing up with subversion and noticed a couple additional files under public:

  • public/login.html
  • public/signup.html

Doh! Gee, I guess that makes sense….

update:

here’s the docs

Setting session temp directory

Speaking of sessions…if you’re using the default PStore sessions, you can set the directory you want them in:

ActionController::CgiRequest::DEFAULTSESSIONOPTIONS[:tmpdir] = “#{RAILS_ROOT}/sessions/”

This will also help you keep in mind that you’ll have to go in there from time to time and clean em out.

Mung in your Session?

If you’re working away on a rails app and have made a change to an object that is held in a session, you may get an error about some mung in the session and then the whole app seems to die. You probably need to clear out the session cache. It holds a serialized version of an object that it can’t un-serialize any more since you went and changed it. On Windows that’s here:

C:\Documents and Settings\[username]\Local Settings\Temp\ruby_sess.

Delete any ruby_sess. and you should be back at it.

Typo on DH

Here’s what I did to get typo running at DreamHost:

First, confirm from the shell:

which ruby  -> should be /usr/bin/ruby
gem list  -> should include rails 0.13.1, etc.

You’ll need to edit dispatch.fcgi and dispatch.rb to have the correct path to ruby.

I set up typo in my web root. If you don’t want that, I’d highly suggest setting up a sub domain and pointing it to the public folder of typo:

/home/cgiusername/public_html/typo/public/

Then edit the .htaccess file to point it to use .fcgi:

RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

And set the permissions of at least the dispatch.fcgi and dispatch.rb to 755:

chmod 755 public/*

It’s a good idea just to do the whole public directory.

Next, if you’re on Windows run:

dos2unix public/*

Before I set up the sub domain I was having problems getting the app to handle the requests right. It is definitely easier to use a whole separate host if you have any spare ones. I’ll probably go back and set up several hosts such as:

blog.convergentarts.com
wiki. " "
forum. " "

etc. because it is both a lot easier to get your app running, but you also have some nice division of your htdocs so you don’t overwrite your wiki when you change your blog.

Caveat on configure.rb

If you use the configure script, you may want to remove it from your production instance. (You may also want to remove all the sql scripts for the same reason.) It would be potentially disastrous to execute that script on your production app and reset your database to pristine condition. :P I may try to add a user confirm to the script if the environment comes back as ‘production’.

Script to load your database

If you have a bunch of database DDL and DML files to load to get your app configured, here’s a little script I wrote that might help. It is set to be run from your db directory alongside your .sql files. You can have your type tables in subdirectories if you like – I do. Here’s my folder layout:

db
  configure.rb --> the script below
  create.sql
  drop.sql
  types
    exec-1
      ability_types.dml
      costs.dml
      ...
    exec-2
      divisions.dml
    exec-3
      teams.dml

The script will run the top level sql first assuming it is the db definition. It then goes through all the lower directories and loads them up. In the example above the divisions.dml depends on types from exec-1 being loaded, teams.dml depends on divisions.dml, etc.

Here’s the script (configure.rb):

require 'yaml'

# You can comment or delete the puts calls --
# they're just so I can follow along and feel all warm and fuzzy.

# you may need to hard-code your env if it isn't in your environment settings:
RAILS_ENV  = ENV['RAILS_ENV'] || 'development'

CONFIG_DIR = File.dirname(__FILE__) + "/../config/"

db_settings = YAML::load(File.open(CONFIG_DIR + "database.yml"))
db_host = db_settings[RAILS_ENV]['host']
db_user = db_settings[RAILS_ENV]['username']
db_pass = db_settings[RAILS_ENV]['password']
db_name = db_settings[RAILS_ENV]['database']

DB_CONNECT = "-u #{db_user} --password=#{db_pass} -h #{db_host} #{db_name} "

# This runs the drop.sql and create.sql first
# reverse is used to execute a 'drop.sql' before a 'create.sql'
# you may want to tweak for your situation
Dir["**/*.sql"].reverse.each do |f|
  cmd = "mysql " + DB_CONNECT << " < " << f
  system cmd
  puts cmd
end

# Then all the dml gets loaded
Dir["**/*.dml"].each do |f|
  cmd = "mysql " + DB_CONNECT << " < " << f
  system cmd
  puts cmd
end

DreamHost adds Rails support

It is unofficially offical as announced in the DreamHost discussion forums and through communications with those involved.

This is a new install of Typo running on Apache/FastCGI here at DreamHost.

I’d like to thank DreamHost for taking this up quickly. It isn’t easy to turn a big ship like theirs, but they’ve gone from talking about getting this installed in mid March to getting it running by mid June. That’s pretty good considering.