Posted by Chris
Thu, 05 Jun 2008 06:55:00 GMT
So, this is a pretty basic “for work” thing I ran into.
Managers like forms with little red asterisks next to required fields, and there doesn’t seem to be any straightforward way to query an ActiveRecord class to determine which fields are required.
Since AR already has to perform the validation, it seemed only right to lump it with the responsibility of keeping track of its own details.
So far, I’ve knocked up a small plugin within an existing rails app, which currently deals with presence and uniqueness validations, by providing the methods:
- validates_presence_of?(field)
- validates_uniqueness_of?(field)
to inspect the model classes.
Without further ado, here’s the prototype code:
module ActiveRecord
module ReflectiveValidation
def self.included(mod)
mod.extend ClassMethods
validation_methods.each do |method|
arr_name = "#{method}_fields".to_sym
mod.class_inheritable_array(arr_name)
mod.write_inheritable_array(arr_name, [])
end
end
def self.validation_methods
[
:validates_presence_of,
:validates_uniqueness_of
]
end
module ClassMethods
ActiveRecord::ReflectiveValidation::validation_methods.each do |method|
module_eval(
<<-eos
def #{method}(*fields)
write_inheritable_array(:#{method}_fields, fields)
super(fields)
end
def #{method}?(field)
#{method}_fields.include?(field)
end
eos
)
end
end
end
end
I’m looking at fleshing it out, handling more validations, and hopefully dealing with things like length requirements.
Oh, and actually hosting the plugin somewhere.
Posted in Ruby on Rails | Tags ActiveRecord, plugins, rails, ruby | no comments
Posted by Chris
Thu, 28 Feb 2008 02:57:00 GMT
Just a quick bitch about something I came across in setting up Redmine.
Removing members from a project in the admin interface was silently failing for me.
It turns out that Redmine, rather sensibly, updates the project so that no issues are automatically assigned to the user being removed from the project. This makes a call to ActiveRecord::Base’s update_all method.
This was the call that was failing, and it was all down to the fact that ActiveRecord was passing my postgres database an update query with an “ORDER BY” clause, which is apparently the sort of fucking retarded feature that mysql decided to implement, and which some useless dick chose to support in AR.
Really, what’s the point of ordering your update statement?
I don’t know who to be more pissed off at over this, but given past experiences with mysql I’ll pin it on them.
FUCK YOU AGAIN, MYSQL!
Posted in Ruby on Rails | 1 comment
Posted by Chris
Wed, 27 Feb 2008 16:37:00 GMT
After a variety of headaches setting up a redmine instance on an Ubuntu server, I thought I’d write a quick guide on how to do it quickly.
First step
Install Ubuntu.
What flavour you go with is up to you.
Packages from apt
Install packages
as root, run:
aptitude install apache2 ruby rubygems subversion ruby-pkg-tools \
ruby1.8-dev build-essential postgresql libdbd-pg-perl libapache2-svn \
libapache-dbi-perl libapache2-mod-perl2 libdigest-sha1-perl
If you want to go with mysql rather than postgres, you can drop the postgresql and libdbd-pg-perl packages, and install the mysql equivalents, but you’re on your own in setting up the database.
Ruby gems
Install gems
as root, run:
gem install rails mongrel mongrel_cluster postgres-pr --include-dependencies
Add gems to $PATH
I did this by adding the line:
export PATH=/var/lib/gems/1.8/bin to the end of /etc/profile
Set up the database for Redmine to use
Switch to postgres user
as root, run:
Create the redmine user
createuser redmine --no-superuser --no-createdb --no-createrole --login --pwprompt --encrypted
Create the redmine database
createdb --owner=redmine --encoding=utf-8 redmine
Switch back
For the tutorial, I’ll be using the password “redmine” for the redmine user.
Redmine itself
For this setup I’ll be using the 0.6 stable branch of redmine via svn, and installing it under /var/www/rails_apps/redmine-0.6
Create the directory and checkout Redmine
mkdir /var/www/rails_apps
cd /var/www/rails_apps
svn co http://redmine.rubyforge.org/svn/branches/0.6-stable redmine-0.6
Configure database access
Create the file config/database.yml within the redmine directory with the following contents:
production:
adapter: postgresql
database: redmine
host: localhost
username: redmine
password: redmine
Bootstrap the database
In the Redmine directory, run:
rake db:migrate RAILS_ENV="production"
rake redmine:load_default_data RAILS_ENV="production"
Configure mailing from Redmine
Setting up a mail account for redmine is your own business, then change this section of config/environment.rb:
config.action_mailer.smtp_settings = {
:address => "127.0.0.1",
:port => 25,
:domain => "somenet.foo",
:authentication => :login,
:user_name => "redmine",
:password => "redmine",
}
to this:
config.action_mailer.smtp_settings = {
:address => "mail.yourdomain.com",
:port => 25,
:domain => "yourdomain.com",
:authentication => :login,
:user_name => "mail_user",
:password => "mail_password"
}
or whatever’s appropriate for your setup.
Check that everything’s set up correctly
From the redmine directory run:
mongrel_rails start --environment=production
You should be able to view the redmine site at localhost:3000 and log in using the username “admin” and password “admin”.
Setting up subversion
Create the repository location
as root:
mkdir /var/svn
chmod 0750 /var/svn
Serve the repository path through Apache
Enable the necessary Apache modules
as root:
a2enmod dav
a2enmod dav_svn
a2enmod perl
Configure site and delegate authentication to Redmine
Copy the file Redmine.pm from the extra/svn directory in Redmine to /usr/lib/apache2.
Create a file under /etc/apache2/sites-available with an appropriate name (e.g. svn.yourdomain) with the following contents:
<VirtualHost *>
ServerAdmin support@yourdomain
ServerName svn.yourdomain
PerlRequire /usr/lib/apache2/Redmine.pm
<Location /svn>
DAV svn
SVNParentPath "/var/svn"
AuthType Basic
Authname "Redmine Project Tracking"
Require valid-user
PerlAccessHandler Apache::Authn::Redmine::access_handler
PerlAuthenHandler Apache::Authn::Redmine::authen_handler
PerlSetVar dsn DBI:Pg:dbname=redmine;host=localhost
PerlSetVar db_user redmine
PerlSetVar db_pass redmine
</Location>
</VirtualHost>
Enable the site and restart apache:
ln -s /etc/apache2/sites-available/svn.yourdomain /etc/apache2/sites-enabled/svn.yourdomain
/etc/init.d/apache2 restart
Check it’s up
Now, if you point your browser to http://svn.yourdomain/svn you should be prompted for a username and password. Don’t worry about authenticating yet, that’s for when you actually have a project repository to go poking around in.
Serve Redmine through apache and mongrel_cluster
Set up the cluster
Create the file config/mongrel_cluster.yml under the Redmine directory with the following contents:
user: root
cwd: /var/www/rails_apps/redmine-0.6
port: "9000"
environment: production
group: root
address: 0.0.0.0
pid_file: log/mongrel.pid
servers: 2
Check the cluster works
In the redmine directory, run:
mongrel_rails cluster::start
You should be able to get to Redmine on ports 9000 and 9001 of your server.
Have the cluster start at boot
As root:
mkdir /etc/mongrel_cluster
ln -s /var/www/rails_apps/redmine-0.6/config/mongrel_cluster.yml /etc/mongrel_cluster/redmine.yml
cp /var/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/mongrel_cluster /etc/init.d
chmod +x /etc/init.d/mongrel_cluster
/usr/sbin/update-rc.d -f mongrel_cluster defaults
Install some more Apache modules
As root:
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_balancer
a2enmod rewrite
Configure the redmine site through Apache
Create /etc/apache2/sites-available/redmine.yourdomain with the following contents:
<VirtualHost *>
ServerAdmin support@yourdomain
DocumentRoot /var/www/rails_apps/redmine-0.6
ServerName redmine.yourdomain
ErrorLog /var/www/rails_apps/redmine-0.6/log/error.log
ProxyPass /images !
ProxyPass /stylesheets !
ProxyPass /javascripts !
ProxyPass /favicon.ico !
ProxyPass /static !
ProxyPass /holding !
ProxyPass /templates !
ProxyPass / balancer://redmine_cluster
ProxyPreserveHost On
<Proxy balancer://redmine_cluster>
BalancerMember http://127.0.0.1:9000
BalancerMember http://127.0.0.1:9001
</Proxy>
RewriteEngine On
# Redirect all non-static requests to cluster
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://redmine_cluster%{REQUEST_URI} [P,QSA,L]
</VirtualHost>
Enable the site and restart apache:
ln -s /etc/apache2/sites-available/redmine.yourdomain /etc/apache2/sites-enabled/redmine.yourdomain
/etc/init.d/apache2 restart
Have Redmine manage your repositories
Tell Redmine that it’s managing your repositories
In the Redmine site, go to Administration -> Settings.
Tick the box labeled “Enable WS for repository management”
Set up automatic repository creation
Check that repository autocreation works
Add a project through Redmine with the identifier “test”
On your SVN server run:
ruby /var/www/rails_apps/redmine-0.6/extra/svn/reposman.rb --redmine redmine.theoru.com --svn-dir /var/svn --owner www-data --url http://svn.theoru.com/svn/
You should get the following message:
repository /var/svn/test registered in Redmine with url http://svn.theoru.com/svn/test
repository /var/svn/test created
Make the server do your dirty work for you
Add the following line to /etc/crontab:
10 * * * * root ruby /var/www/rails_apps/redmine-0.6/extra/svn/reposman.rb --redmine redmine.yourdomain --svn-dir /var/svn --owner www-data --url http://svn.yourdomain/svn/
Restrict access to Redmine’s web services’ API
Add the following section to /etc/apache2/sites-available/redmine.yourdomain:
<Location /sys>
Order allow,deny
Allow from ip.of.svn.yourdomain
</Location>
Restart apache:
/etc/init.d/apache2 restart
Relax, it’s done
Redmine and SVN should be happily up and running.
Once an hour, the cron job you set up will check for any newly registered projects and create an SVN repository for each new project at http://svn.yourdomain/svn/#{project_identifier} and register this location with the project.
To allow repository browsing, you will need to add appropriate credentials (e.g. project manager login) to the repository settings of the project.
Enjoy!
Posted in Ruby on Rails | Tags projects, redmine, svn | 6 comments
Posted by Chris
Thu, 20 Dec 2007 00:03:00 GMT
The latest post over at Coding Horror, “Nobody Cares What Your Code Looks Like” is one of the strange posts that pop up occasionally where it seems that Jeff Atwood has missed the point entirely.
The elegance/ugliness of the code behind an application is immensely important in the maintenance and extension of any software, and particularly for open source software where it’s crucial that people want to work on your code.
The mind boggles, really. Well, at least I got through that without making a jab at Jeff for his VB use.
Posted in Ramblings | no comments
Posted by Chris
Sun, 11 Nov 2007 11:10:00 GMT
I’ve started on a new job hunt after being stuffed around and finally fired from a small, and dysfunctional web development company.
Looking around, I’ve realised that I should have been building up a public portfolio, of sorts, before now.
So far, the only thing I’ve released into the wild has been a small, capistrano module, for a very specific, and in my mind ill conceived, application. All the interesting stuff I’ve done has long been scrubbed from my hard drive, in compliance with long-winded NDAs from previous employers (including a rather nifty library for controlling mobile phones through their inbuilt modems to simulate and test network response/reliability).
I suppose my rambling boils down to the advice that you should, if possible, release your work to the public, and if you can’t, you damn well better be knocking up some personal projects to show off your skill.
Off to try to find something interesting to develop, I guess.
Posted in Ramblings | no comments
Posted by Chris
Thu, 06 Sep 2007 01:38:00 GMT
So, I hit an odd problem in one of the apps I’m working on that I needed to render custom text onto images.
RMagick made that job pretty easy, but I didn’t want to clog up space on the server with a whole bunch of images that were only being viewed once.
The solution turned out to be fairly simple in the end, using send_data in the controller.
I’ll let the code speak for itself:
Controller (in StoreController):
def gift_preview
require 'RMagick'
text_params = {
:width => 200,
:height => 120,
:xpos => 240,
:ypos => 340,
:colour => 'black'
}
image = Magick::ImageList.new( File.join( "#{RAILS_ROOT}/public/images", 'gift_box.jpg' ) )
text = Magick::Draw.new
text.font_family = 'times'
text.pointsize = 15
text.font_style = Magick::ItalicStyle
text.annotate(
image,
text_params[:width],
text_params[:height],
text_params[:xpos],
text_params[:ypos],
params[:message] ) {
self.fill = text_params[:colour]
}
send_data( image.to_blob, :type => 'image/jpeg' )
end
The important part of this is the last line that sends the image back as a binary blob with an appropriate content type (adjust for your image format).
In the template I have:
<%= link_to_function "Gift Preview",
"$('gift_image').src='#{url_for( :action => 'gift_preview' )}?message=' + $F('order_message')" %>
“order_message” is a text area, and $F is a very handy prototype function that grabs it’s current contents, and “gift_image” is an image tag for displaying the custom image.
Clicking on this link sets the image source to the gift_preview action, passing the current message, then the controller returns the new custom image, never writing it to disk.
The code can do with some tidying, but for now, this is working for me (and it’s a prototype, so :P).
Enjoy! And for more RMagick detail, head here.
Posted in Ruby on Rails | no comments
Posted by Chris
Sun, 17 Jun 2007 10:48:00 GMT
After a lot of stuffing about I finally found a solution to the problem that I was having with the URL for this blog.
The basic problem was that the link http://www.drinkingbird.net/blog (without the trailing slash) was being rejected with a 400 Bad Request error.
I spent ages trying to get this to work with awkward rewrite rules in the parent directory, when I should have been looking in the public directory of the rails app. The solution is well enough explained over at LavaFactory.
I just made one small refinement, which is to change:
RewriteRule .*/blog/(.*) http://www.drinkingbird.net/blog/$1 [L,R]
to
RewriteRule (.*)/blog/(.*) $1/blog/$2
to satisfy my relentless desire to avoid configuration tied to a particular domain.
Posted in Typo, Ruby on Rails | no comments
Posted by Chris
Sun, 10 Jun 2007 11:51:00 GMT
I thought I’d post a quick summary on what I went through to get Typo up and running on Site5, since it’s a bit more tricky now that the SiteAdmin interface no longer contains an automatic install script.
I decided to go the gem route on this, so that’s the only way I’m going to talk about. If you want to install from SVN trunk, you’re on your own.
First, you’ll want to set up your account with a local gem installation directory, as detailed in this forum thread.
Then, ssh into your account (if you’re not still there), and type:
There’s a good chance this will fail the first time, with an error on attempting to install the sqlite3-ruby gem. This can be solved by opening a ticket with Site5’s support, and asking to have the sqlite-devel package installed on your server, then trying again.
Once the gem is installed, you just need to run
typo <installation directory>
then manually kill the mongrel process it spaws immediately after installation (I’d lay money on site5’s servers doing this automatically if you don’t anyway).
From here, it’s all fairly easy:
Edit the environment.rb file in typo’s config directory, and uncomment the line:
ENV['RAILS_ENV'] = 'production'
and add the line:
ENV['GEM_PATH'] = '/home/<your_username>/<path_to_gems>:/usr/lib/ruby/gems/1.8'
Create the file public/.htaccess in the typo directory as:
# General Apache options
AddHandler fastcgi-script .fcgi
Options +FollowSymLinks +ExecCGI
RewriteEngine On
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
ErrorDocument 500 /500.html # You may want to edit this file
Setup a mysql database for the blog’s production db, and configure it in config/database.yml. Example config:
production:
adapter: mysql
database: username_blog
username: username_blog
password: secret
host: localhost
Then run
rake db:migrate RAILS_ENV=production
to load the schema.
If you installed your blog anywhere other than under your public_html directory, you’ll need to create a symlink to the blog, e.g.
ln -s /path/to/typo/public public_html/blog
Hopefully this ends up helping someone. If not, well at least it gave me an excuse to get to grips with some of typo’s editing syntax. If I’ve missed anything, please bitch at me, so I can fix it.
Posted in Typo, Ruby on Rails | 2 comments
Posted by Chris
Sun, 10 Jun 2007 11:17:00 GMT
Well, here goes. After years of steadfast resolve I’ve given in, and started up my own little, self-centred part of the web.
There was a bit of fiddling about to get this thing up and running, but now that’s done I’ve just got to figure out what to write here :).
Hopefully there’ll be some useful tech stuff, eventually, but knowing my general approach to unmoderated speech, it might get a bit buried in pointless rambling and poorly directed vitriolic outbursts.
Oh well, maybe I’ll try to keep this thing under wraps for a while until I can write something without sounding like an angsty teen with a large vocabulary.
Posted in Ramblings