Saturday, 6 November 2010

Good Design

Good design should be innovative.

Good design should make a product useful.

Good design is aesthetic design.

Good design will make a product understandable.

Good design is honest.

Good design is unobtrusive.

Good design is long-lived.

Good design is consistent in every detail.

Good design is environmentally friendly.

Last but not least, good design is as little design as possible.

Dieter Rams
Former Design Director, Braun

Quote from Objectified by Gary Hustwit.

Sunday, 6 September 2009

Sending Email Using Gmail and Action Mailer

I've used this for a new site, which I'll be mentioning very soon. It took me quite some time to figure out and get right.

The first thing to do is download the smtp_tls.rb file. I saved it in my Sinatra app, under lib.

Next create a file called mailer.rb in the same lib directory with the following contents:
require 'lib/smtp_tls'
require 'action_mailer'

class Mailer < ActionMailer::Base
def my_email(from_email, from_name, message)
recipients "marktucks@gmail.com"
from from_email
subject "Contact from " + from_name

body :name => from_name, :email => from_email, :message => message
end
end

Mailer.template_root = File.dirname(__FILE__)
Mailer.delivery_method = :smtp
Mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => "587",
:domain => "YOUR_DOMAIN",
:authentication => :plain,
:enable_starttls_auto => true,
:user_name => "YOUR_USERNAME",
:password => "YOUR_PASSWORD",
:raise_delivery_errors => true
}
Mailer.logger = Logger.new(STDOUT)

NB: I did have the from address as from_email "<" + from_name + ">" but it recently gave me a syntax error, so I removed it which fixed this issue.

As our class above is called Mailer, create a directory under lib called mailer, which is where our email template will go. As we have a method called my_email in our Mailer class, we need to call our template my_email.erb with the following simple contents:
Enquiry from <%= h @name %>,
Email: <%= h @email %>
Message:
<%= h @message %>

The variables match the ones we passed in from our Mailer class on this line:
body       :name => from_name, :email => from_email, :message => message

Lastly, we send the email:
begin
Mailer.deliver_my_email(@email, @name, @message)
@sent = true
rescue Exception => e
@sent = false
end

As shown in the ActionMailer docs, we are just calling a dynamically generated method, which simply prefixed deliver_ to to the name of our my_email method from the Mailer class. This method will raise Exceptions if something goes wrong, so we've rescued this if it happens so our lovely users aren't exposed to it.

Comments, better ways of doing this, general discussion welcome just throw me a comment.

Tuesday, 23 December 2008

Unit Testing Using Context

Jeremy McAnally has released a gem called context allowing contexts in Test::Unit tests. It's all the rage, even those crazy Rails guys are doing it (although I did check out some of their unit tests earlier and couldn't find any).

Anyway, I'm way behind on my TDD and BDD and all other testing acronyms so I decided to give it a go. These are way simple tests and I actually did it the normal Rails way initially before "converting" to the context way of doing it.

I've got converting up there in quotes because it was really, really simple and I hardly did anything which is fantastic because the easier something that's good is to do, the more people will eventually do it; think Rails conventions.

Getting Started

Get the gem:
$ gem sources -a http://gems.github.com
$ sudo gem install jeremymcanally-context
That is outlined as the install procedure, but you can't just use it as you must require that bad boy for your Rails app to use it - so put this in your test_helper.rb:
require 'context'
This allows it to be used in all tests that require the test_helper. I've also put some other helper methods (where else) in here, just simple stuff like:

def get_post(*id)
if id.nil?
Post.new
else
Post.find(id)
end
end
I also noticed that in your individual Unit Tests you don't need to explicitly put
fixtures :comment
and the like because
fixtures :all
is declared in this file allowing you to just access your fixtures like so:
comment = comments(:comment_1)
Here I have a comments.yml fixture which can be accessed via
comments
and I have an individual record
:comment_1


On to the test, finally

So here's my edited Unit test class:
require File.dirname(__FILE__) + '/../test_helper'

class CommentTest < Test::Unit::TestCase

context "A new comment" do
test "should be valid with both name and body" do
comment = Comment.new(:name => 'My User',
:email => 'myuser@example.com',
:url => 'http://www.example.com',
:body => "Here's my comment for ya!")
assert comment.valid?
assert comment.errors.empty?
end

test "should be invalid with name but no body" do
comment = Comment.new(:name => 'My User',
:email => 'myuser@example.com',
:url => 'http://www.example.com')
assert !comment.valid?
assert comment.errors.invalid?(:body)
end
end

context "An existing comment" do
test "should be valid" do
comment = comments(:comment_1)
assert comment.valid?
assert comment.errors.empty?
end
end
end
As you can see it's pretty much the same as any normal Rails Unit test, except for a couple of minor changes / improvements:
  1. The class inherits from Test::Unit::TestCase instead of ActiveSupport::TestCase
  2. We've added two context blocks in there to wrap our tests, creating a more readable and elegant test
  3. We're not
    def
    ining our test methods, we instead have test blocks, which, again, makes the whole thing read like a sentence; some would say the sign of beautiful code
  4. We can also have before and after blocks (my before block is kinda lame but yours could do whatever you want, creating multiple objects for use in your tests for example, so you don't have to create new ones for every test) much like setUp and tearDown in JUnit
On the second and third points; if you read your tests out loud they should flow like a sentence. So in the simple tests I have created we have:

"A new comment should be invalid with no body or name" - the context and the test name form a flowing sentence. "An existing comment should be valid" etc.

All of my tests start with the word should, but there is no reason they couldn't start with anything else as long as they create a sentence like structure. They could be rewritten "A new comment could be accepted as long as a user is present", it's a bit more verbose, but it still reads like a sentence and everyone looking at that test will know what it's meant to be testing.

There is still a lot to learn, like Mocks, Integration Tests, Functional Tests and even more on Unit Tests - like writing them before the code.

But my first foray was an enjoyable one and something I will definitely keep doing and I hope this is a help to even just one person and gives them a boost to create their own tests, making their software more stable and maintainable.

Thoughts, comments, corrections and/or improvements welcome.

Rebuild the locate database on Mac

Just because I always forget.
$ sudo /usr/libexec/locate.updatedb

Sunday, 9 November 2008

Merb 1.0

So Merb 1.0 was released 2 days ago during RubyConf, just
sudo gem install merb
to update.

I had to update my config/dependencies.rb file to read
merb_gems_version = "1.0"
and also
sudo gem install webrat
, which is a Ruby Acceptance Testing plugin. Here's the Git repo if you want to check it out.

Thursday, 6 November 2008

Getting the Database name in Merb and DataMapper

After a lot of searching and banging my head against my keyboard I finally found how to get the database name for my Merb application:
Macintosh:ruby-rss-feeds marktucks$ merb -i
...
>> repository(:default).adapter
=> #, @name=:default, @transactions={}>
>> repository(:default).adapter.uri
=> #
>> repository(:default).adapter.uri.path
=> "sample_development.db" # YAY!

I'm sure there must be a better way to do this. A Rails::Configuration.database_configuration equivalent? But I just cannot find it. The
Merb.config
doesn't seem to have a database property / method. You can get stuff like the host (
Merb.config[:host]
).

Any suggestions / better solutions are welcome.

Friday, 26 September 2008

iTunes Library from PC to Mac

About a couple of months ago I switched from my PC to a MacBook and have never looked back since. I don't miss anything from my PC, except my iTunes Library. And contrary to my colleague's advice it seems as though you can't just copy all that iTunes guff from your PC to your Mac.

So I found this article on how to convert my iTunes library and copy all the music files from the PC to the Mac.

One small edit to this post is that in new iTunes 8, "Import Library" is now, for some confusing reason; File > Library > Import Playlist. "Consolidate Library" is also under File > Library.

It almost worked like a charm, but apparently it couldn't find some of my music, maybe something to do with the special characters in my Library.xml?