capetown.rb
After a bit too much wine at last night’s Geekdinner I suggested to the gathered crowd that I’d be attempting to put together a Cape Town Ruby user group. Previous efforts by others last year didn’t quite pan out.
As a first step towards that, I’d suggest that you join the Clue mailing list at RoRza, until we get our own list together. If any of you have organised this kind of thing before I’d be keen to hear from you too (nick[at]codevader[dot]com).
apache2 & mod_fcgi
Sometimes its the little things that take the fun out of programming. Rails has most of these little things wrapped up in site deployment.
A little thing that wasted some time for me today…
Rails’ default /public/.htaccess is set up for Apache/fast_cgi. So if you try to use that with Apache2, all that’s going to happen is you’ll see your dispatch.fcgi file spat back in plaintext. Apache2 uses mod_fcgi, so the correct line in the .htaccess file should be
AddHandler fcgid-script .fcgi
and
AddHandler fastcgi-script .fcgi
should be commented out.
Railsconf Europe
I was originally intending to attend the just completed Railsconf Europe, but there was just a little (ok, a lot) too much work happening to let me slip out of the country for a few weeks. There will be more conferences in the future when I will be able to make it, although I hope I don’t have to wait another year before the next European one. Visiting the US involves a few too many flying hours for my liking, especially to a location like Portland. Anyway, we’ll see.
So I’ve been reading about the interesting talks at Railsconf Europe. The slides for all of the presentations are here. And a Google Blog search will turn up a lot of opinion and summaries of the various presentations. The most interesting summary I found was this one of DHH’s keynote address.
Very interesting is Sun’s serious support for Rails, and to hear the creator of Struts and JSF (and Sun employee), Craig McClanahan, saying that after using Rails for web application development, working with Java feels unpleasant. With Sun and JRuby I think Ruby and Rails is most certainly headed for the enterprise, which is great news for all Rails developers. It makes our selling job easier and provides us with more opportunities.
Rules to live by
# Write specs before coding
# Do the simplest thing that works
# Refactor early and often
Sending emails from your Windows Development Environment
I recently installed exception notification plugin for the application I am developing.
I wanted to make sure that everything was setup correctly on my local machine before deploying to the preview link we set up for clients. The catch however, is that I am stuck on windows – pending the arrival of my Dell. As anyone who develops rails on windows knows, its an uphill battle.
So, I set out to get my development environment on my localhost to send exception notifications to my gmail inbox.
This post on ExceptionNotifier was useful - http://rubyurl.com/lsu
and from the Rails Wiki - http://rubyurl.com/BZa
For config of the plugin I had these lines in my environment.rb
ExceptionNotifier.exception_recipients = %w(#{my codevader email})
ExceptionNotifier.sender_address = %("Application Error" <#{my codevader email}>)
ExceptionNotifier.email_prefix = "[Sitename Here] "
Next up, I changed this line in my development.rb
config.action_controller.consider_all_requests_local = true
to
config.action_controller.consider_all_requests_local = false
Errors are displayed on screen for local requests so to get the email to be sent instead of the onscreen display you need to convince rails that all the requests it sees are external.
Next, this line needed to change since I wanted to know why my mail wasn’t sending.
config.action_mailer.raise_delivery_errors = false
became
config.action_mailer.raise_delivery_errors = true
Delivery Method.
Make sure your delivery method is set to:
ActionMailer::Base.delivery_method = :smtp
Lastly, I needed to change the default smtp settings:
The default server settings in ActionMailer::Base, starting on line 197, is:
@@server_settings = {
:address => "localhost",
:port => 25,
:domain => 'localhost.localdomain',
:user_name => nil,
:password => nil,
:authentication => nil
}
Overriding these settings in development.rb with these settings below worked for me.
## Actionmailer settings
ActionMailer::Base.smtp_settings = {
:address => "smtp.#{some available smtp server}.net",
:port => 25,
:domain => 'TheLuggage'
}
I struggled a very long time before discovering that on Windows, the domain name is the name of your computer. In my case ‘TheLuggage’.
This is by no means an in depth look at the workings of ActionMailer or ExceptionNotifier, these are the settings that worked for me. However, if you developing rails on Windows, life is hard enough, hopefully this will make it a little easier.
Bending a django database to play with rails
I’m currently porting my band’s website from python/django to ruby/rails so here is the first installment. I don’t fancy recapturing to data or writing sql export and import scripts, so I’m just going to re mold the database to rails conventions in-place seeing as I’m discontinuing the old version. I have this table in the current database that stores news posts for the front page of the website:
table_name: blog_post
id : integer (primary key)
subject : varchar (200)
text : longtext
tags : varchar (200)
created : datetime
modified : datetime
author_id : integer (foreign key, user table)
The Django model
class Post(models.Model):
subject = models.CharField(maxlength=200)
text = models.TextField(help_text="""
*italics*
**bold**
- list item
http://www.codevader.com
""")
tags = models.CharField(maxlength=200)
created = models.DateTimeField(auto_now_add=True, editable=False)
modified = models.DateTimeField(auto_now=True, editable=False)
author = models.ForeignKey(User);
monthstr = ''
class Meta:
app_label = "blog"
ordering = ['-created']
def __str__(self):
return self.subject
class Admin:
list_display = ('subject', 'created')
and here is my new rails version:
#Migration
class CreatePosts < ActiveRecord::Migration
def self.up
rename_table('blog_post','posts')
rename_column(:posts, 'created','created_at')
rename_column(:posts,'modified','updated_at')
add_index(:posts, 'author_id')
end
def self.down
rename_column(:posts, 'created_at','created')
rename_column(:posts, 'updated_at','modified')
rename_table('posts', 'blog_post')
end
end
#Model
class Post < ActiveRecord::Base
belongs_to :user, :foreign_key => :author_id
validates_presence_of :subject, :text
end
#Controller
class PostController < ApplicationController
layout 'admin'
before_filter :login_required
active_scaffold :posts do |config|
list.columns = [:subject, :user, :tags, :created_at]
end
end
Ok, I’ve used some cheap tricks here, I’ve already done the authentication using acts as authenticated and that’s where the before_filter method comes from. I’ve also installed active scaffold to save me creating the admin CRUD pages(which only the band get to see anyway). One of the things that turned me on to django initially was it’s slick admin interface that comes baked in. Now that I’ve been working in rails for a little while I’ve come to appreciate the plugin architecture and I try to avoid coding unique solutions to common problems like admin CRUD.
I initially tried to keep the table as is and bend rails around it(in fact, the original title of this entry was ‘how to bend rails to play with a django database’). Our old django site won’t work against the migrated database (which is fine for me in this particular project). If you need to keep the database intact the files would something look like this, although this approach is not recommended and it is untested, I ran into issues using active scaffold without an updated_at column, I don’t even want to bother paddling up stream:
I ran into a few issues when using active_scaffold on a model looking something like this:
#Model
class Post < ActiveRecord::Base
set_table_name "blog_post"
before_create :run_before_create
before_save :run_before_save
belongs_to :user, :foreign_key => :author_id
validates_presence_of :subject, :text
def updated_at
return modified
end
def run_before_create
created = Time.now
end
def run_before_save
modified = Time.now
end
end
Thanks to Raaum’s rails reader for showing me some of the unconventional ActiveRecord manipulation, as well as encouraging me to stick to the ActiveRecord conventions.
until next time…
Junebug Wiki
One of the systems we plan to use to keep organized is an internal wiki. The solution I decided on was Junebug, which is pretty minimalist and runs on the Camping framework. It includes its own webserver, but I wanted to put some security over it so the whole world won’t be privy to our business.
So the solution was to reverse proxy through Apache2. The Junebug installation page included a config file to get this going, but it wasn’t working for me. After going in circles for a while, I ended up with the following configuration:
<Virtualhost *:80 *:8000>
ServerName my.server.name
ProxyRequests Off
SSLEngine on
SSLCertificateFile /etc/apache2/apache.pem
# Proxy ACL
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
# Proxy directives
ProxyPass / http://localhost:3301/
ProxyPassReverse / http://localhost:3301/
ProxyPreserveHost On
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
# Turn rewriting on
RewriteEngine On
RewriteLogLevel 0
# Redirect non-static requests
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ http://localhost:3301%{REQUEST_URI} [P,QSA,L]
DocumentRoot /home/myuser/cvwiki/public/
<Location />
AuthType Basic
AuthName "Restricted Files"
AuthUserfile /path/to/passwd/passwords
Require user myusername
</Location>
#Logfiles
ErrorLog /home/myuser/cvwiki/error-cvwiki.log
CustomLog /home/myuser/cvwiki/access-cvwiki.log combined
</Virtualhost>
This reverse-proxies Junebug through Apache. Also it runs over SSL and asks for a password. Getting SSL up and running was as simple as
#openssl req $@ -new -x509 -days 365 -nodes -out /path/to/apache.pem -keyout /path/to/apache.pem
What tripped me up for quite a while was the fact that I had to modify the config.yml file for Junebug so that it would serve requests to localhost, and not to the server’s external IP address. Once that was changed to
host: 127.0.0.1
everything was peachy.
REST and BDD
One of the challenges facing any developer is keeping current with modern methodologies. This is especially so with Ruby on Rails, whose practitioners are probably more open-minded than most when it comes to adopting new ideas that work.
Two practices which have now entered the Rails mainstream are REST and BDD.
REST, which stands for Representational State Transfer, is the use of URLs to represent unique conceptual resources, which are accessible as physical representations through content type negotiation (from http://safari.oreilly.com/9780321501745). That might sound like a mouthful, but the net result is a simplification of how to interact with applications.
BDD is Behaviour Driven Development. BDD is a logical next step from TDD (Test Driven Development). BDD switches the paradigm from one of testing the code you’ve written (or are about to write), to a language of description and specification. Instead of writing tests, we write specifications. The benefit of this is firstly that specs are a more logical thing do be doing before you start coding, and secondly that the language used to describe a specification is far more readable and understandable than the language used in tests.
Unfortunately with both concepts being relatively new, there’s not a lot out there describing the practice of using these techniques. REST seems to get at most a chapter or two in the crop of current books. BDD hasn’t even made it to a printed book yet.
So these are the resources we’ve found to get ourselves up-to-speed…
BDD:
- http://dannorth.net/introducing-bdd
- http://behaviour-driven.org/
- http://video.google.com/videoplay?docid=8135690990081075324
- http://www.oreillynet.com/pub/a/ruby/2007/08/09/…
- http://peepcode.com/products/rspec-basics
REST:
- http://peepcode.com/products/restful-rails
- http://www.b-simple.de/documents
- http://safari.oreilly.com/9780321501745
I hope some of those are useful for anyone trying to learn this stuff.
Team thoughts
To keep this blog active, we’re going to have our whole team blog here.
Some short introductions then…
- Nick (me): I steer the ship, communicate with clients and partners, project manage, do some architecture and whatever programming I can fit in between those things
- Grant: Almost a year-and-a-half Rails experience, and did PHP before that.
- Ivor: An engineering graduate with just over a year’s Rails experience. Previous experience with Flex and Actionscript, amongst other things.
- Robin: Only 6 months with Rails, but more than a year with C# before that. He’s also done enough Python to decide that he prefers Ruby.