Ruby on Rails: Override Attribute Assignment 1
ActiveRecord models used to provide access to their internal attribute data through the attributes method, but this doesn’t seem to be the case any longer. Have a look at the current source code and you can see why. The attribute hash is cloned before being returned, so changes aren’t applied.
So the old method of reassigning is no longer applicable:
m = MyModel.create(:name => 'test')
m.attributes[:name] = 'value' # Assigns to a clone of m's @attributes
m.name
# => 'test'This limits your options when trying to re-define an assignment method, but there is still a way. For example, to trigger some behaviour when a value is assigned, you can do this:
def name=(value)
# Always force to lower-case
super(value.downcase)
endCalling the base class method of the same name will allow ActiveRecord to handle the assignment properly, and there’s still a way to extend the basic functionality in a model.
Ruby on Rails + Daemons 6
Getting a Rails script to run in the background shouldn’t be hard, but there’s a few issues with the stock configuration that need to be fixed before anything will work properly.
First, the Daemons GEM will switch your current working directory to be ‘/’ which will mean that whatever RAILS_ROOT you have will likely be incorrect. Usually it’s something like “../config/../” which works only if you’re in the “correct” location.
A quick fix for that can be put into your environment.rb file right up at the top, after RAILSGEMVERSION.
RAILS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'), Dir.getwd)Then you need to create a controller script in some directory. scripts/ is probably fine, but you may have a preference for something else.
Here’s an example that launches myscript.rb which resides in the same directory as the controller script.
#!/usr/bin/env ruby
require 'rubygems'
require 'daemons'
Daemons.run(File.join(File.dirname(__FILE__), 'myscript.rb'),
:dir => "../log",
:dir_mode => :script,
:backtrace => true,
:monitor => true
)Nothing special needs to be done in myscript.rb but you must keep in mind that all output will be lost. To log it, you might do something like this before sending any output to STDOUT:
$stdout.reopen(File.open("#{RAILS_ROOT}/log/agent.log", "w"))
$stderr.reopen(File.open("#{RAILS_ROOT}/log/agent.err", "w"))Rails Migrations with Fixtures 4
When creating a model, in addition to creating the base class, Rails will create a fixture file in YAML format and a very rough migration class. In most cases you will want to import some data at first, for example, to create the “Administrator” user.
Here’s a simple way to automatically load in the fixtures within the migration file:
require 'active_record/fixtures'
class CreateMyModel < ActiveRecord::Migration
def self.up
begin
ActiveRecord::Base.transaction do
create_table :my_models do |t|
t.column :name, :string
# ...
end
Fixtures.create_fixtures("test/fixtures", :my_models)
end
rescue
self.down
raise
end
end
def self.down
drop_table : my_models if (MyModel.table_exists?)
end
endNote that if there’s an error in your YAML file you’ll get a failure that might not make any sense. I spent a good fifteen minutes trying to track down a problem that was related to having an “empty” entry. In this case I had a value that looked like:
test:
# ...
With no data in there, the Fixture instance was being given ‘nil’ instead of some data and threw an exception as a result. I think it’s valid YAML, but not valid enough for Fixture.
Social Networking in Disarray 4
I’ve been making an effort to find better sites in the “Social Networking” space beside Digg and Reddit, but few seem even close to that modest standard of usability and popularity.
So many are derivative to the point of being unflattering clones of some other service, or are just so far off base as to be either impractical or inscrutable. Blink this, Shadow that, they’re all shades of bizarre, or worse, mere outlets for spam links.
Delicious will be integrated with Popyula soon, all a matter of collecting the right data, but there’s few others that seem so urgent to introduce.
Popyula: A Blogosphere Popularity Report 1
After a week of steady work I’m finally able to launch my first quick application: Popyula, a site that reports on the ever changing popularity of pages as they appear in blogs.
Right now it’s covering Digg and Reddit but that will be expanded to other popular services in the near future.
For example, here’s a list of all links to YouTube.
While I haven’t gone so far as to slap the Web2.0 requisite “Beta” decal on the site, it is a work in progress.
What’s great is that with Ruby on Rails, Mongrel and Apache 2.2 I was able to make this run really fast on a really low-budget server.
Quick Ruby on Rails SQL Shell Tool 25
This is a simple Ruby script that I put together to launch a MySQL shell for a rails application. It looks within the current directory and parent directories for a database.yml configuration file to read.
#!/usr/bin/env ruby
require 'yaml'
require 'optparse'
config = nil
path = "."
while (File.exists?(path) and (path.length < 255) and !config)
if (File.exists?("#{path}/config/database.yml"))
File.open("#{path}/config/database.yml") do |f|
config = YAML.load(f)
end
else
path = "../#{path}"
end
end
unless (config)
puts "Could not find database.yml"
exit(-1)
end
command = "mysql"
verbose = false
opts = OptionParser.new
opts.on("-v", "--verbose") { verbose = true }
opts.on("-d", "--dump") { command = "mysqldump" }
args = opts.parse(*ARGV)
environ = (args[0] or ENV['RAILS_ENV'] or 'development')
if (config and config[environ])
config = config[environ]
puts config.inspect if (verbose)
exec(command,
"--user=#{config['username']}",
"--password=#{config['password']}",
"--host=#{config['host']}",
"--port=#{config['port'] or 3306}",
config['database']
)
elsif (config)
print "Could not find environment #{environ} in configuration file\n"
exit(-2)
else
print "Could not find or read Rails configuration file\n"
exit(-1)
endFor example, to save a database backup:
% cd svn/myapp/db % rsql --dump > dev.sql
Ruby on Rails Migrations 3
Although I’m a big fan of the concept of migrations, one of the things I’m not especially enamoured with is the way Rails implements them. Each migration is an atomic thing that proceeds, in specific sequence, from others. There’s no room for branching or conditions.
When I’m working in a group development environment I might be producing code that requires a migration alongside another developer doing much the same. Without some degree of co-ordination regarding migration numbers, this will cause a conflict, even if the actual migrations themselves are entirely independent..
It would be nice if the migrations had not only some kind of sequence identifier number but a prerequisites column so that two could share a number and yet be applied correctly.
I wonder if developing an improved migrations system would yield any tangible benefits.
Mongrel Rails Launcher 4
Here’s a quick init.d-type script to launch Mongrel with the appropriate options:
#!/bin/sh
case "$1" in
start)
mongrel_rails start -d -e demo -p 4101 -P log/mongrel-dev.pid
;;
stop)
mongrel_rails stop -P log/mongrel-dev.pid
;;
*)
echo $"Invalid option"
exit 1
esac
This is useful if there’s more than one instance of mongrel running in a particular directory.
Subversion 1.4 and Apache 2.2
The Apache development team has upgraded the apr interface for httpd from version 0 to version 1, where httpd-2.2.3 is now using apr-1.2.7.
This means that a lot of modules not only have to be recompiled, but they need to use the correct apr or they’ll be left hanging.
I thought I had compiled it correctly but I was using the wrong one, as an upgrade from 2.0 to 2.2 had carelessly left them behind.
This is how I got it to hold together on a Fedora system:
./configure --with-apxs=/httpd/bin/apxs \ --with-apr=/usr/local/apache2/bin/apr-1-config \ --with-apr-util=/usr/local/apache2/bin/apu-1-config
Disabling Caps Lock on OS X 4
Eclipsed perhaps only by the regretful Windows Key, “Caps Lock” is a perpetual nuisance on many keyboards. It exists merely to annoy.
The Matias keyboard I have doesn’t put the button in its usual place, instead opting to tuck it away down by the right Control key. There it is less of a pest but it will still get bumped and nudged from time to time.
The best way to eliminate this button altogether, short of prying it from the keyboard, is to map it out using the Keyboard control panel.

Older posts: 1 2
