Merb 0.9 on Ubuntu Linux 7.10

written by allen on March 2nd, 2008 @ 10:51 AM

The Merb application framework is getting close to a 1.0 release. Merb takes many of the ideas of Ruby on Rails and does them one better. RoR was designed for developers and applications, but has not been the best to run in production. Merb was written from the ground up with performance and scalability. But as a result, its like travelling abroad in that things are similar but not exactly the same as you are used to developing with RoR.

The platform of choice of most rubyists these days is OS X, with its fine unixy-goodness and groovy Textmate editor. Ubuntu Linux provides most of these features for a fraction of the price! Also, since these applications are generally deployed on the Linux OS, it makes sense to know how to get things running on that platform as well. Let’s roll up our sleeves and get to work.

I used Justin’s post as a starting point on what to do. Open up a terminal window and start.

Get the Git

First, we install the git version control system which merb uses. Note the current Debian git package has a minor bug requiring the /etc/mailname file. Create that file with your hostname in it for now.

sudo apt-get install git-core
vi /etc/mailname

Gems

I assume you have been using Ruby before and have a modern Ruby and RubyGems installed. If not, go do that now. I’ll wait.

Justin recommends having these gems. All seem a good idea, but mongrel erubus and rspec seem more necessary if you are trying to cut down. Merb requires rack, and a ORM like Rails’ ActiveRecord, Sequel, or Datamapper, which it looks like it prefers. Merb is built upon the Rack web server abstraction library.

Like Merb, Datamapper is thread-safe to allow multiple requests being handled. However, it is not yet fully developed like ActiveRecord and may not be as production-ready. If you are porting an application from Rails, you may want to continue using ActiveRecord.

sudo gem install mongrel json json_pure erubis mime-types rspec hpricot mocha rubigen haml markaby mailfactory Ruby2Ruby -y
sudo gem install rack
sudo gem install datamapper -y

Install Merb

Merb is available in gem form, but they may not be as up to date as we would like. So let’s git them from the git repository. If you are having problems, try the http:// protocol instead of the git:// protocol. Merb in divided up into merb-core, merb-more, and merb-plugins in order to let you craft the server with just the parts you need. We need to go into each repository and “install” it in your gems.

mkdir trymerb
cd trymerb

git clone git://github.com/wycats/merb-core.git
git clone git://github.com/wycats/merb-more.git
git clone git://github.com/wycats/merb-plugins.git

cd merb-core
sudo rake install

cd ../merb-more
sudo rake install
# has link_to, etc
cd ../merge-assets 
sudo rake install

cd ../../merb-plugins/merb_helpers/
sudo rake install
cd ../merb_activerecord/
sudo rake install
cd ../merb_datamapper/
sudo rake install
cd ../merb_rspec/
sudo rake install

Whew! That’s going to get old fast. The upcoming gems will be better.

Merb with PostgreSQL

PostgreSQL is my RDBMS of choice. MySQL would work similarly. Ubuntu needs your PostgreSQL header files, so we load them first.

sudo apt-get install libpq-dev
sudo gem install do_postgres

Now let’s go roll an app!

The MyBlog Merb Application

To show off our merby goodness, we will build the “hello world” of ruby web applications, the blog.

cd trymerb
merb-gen myblog
cd myblog
createdb myblog_development

The createdb command is for postgresql, please substitute the create database for your db of choice.

Edit config/init.rb file and enable the following configurations.
  ### Uncomment for DataMapper ORM
  use_orm :datamapper

  use_test :rspec

  ### Add your other dependencies here
  dependencies "merb_helpers", "merb-assets" 
Now create your /config/database.yml
  ---
  # This is a sample database file for the DataMapper ORM
  :development: &defaults
    :adapter: postgresql
    :database: myblog_development
    :username: the_user
    :password: secrets
    :host: localhost

  :test:
    <<: *defaults
    :database: myblog_test

  :production:
    <<: *defaults
    :database: myblog_production

Merbful Authentication

Optionally, we add in authentication, the “Restful Authentication” plugin port to merb. Read me about here

cd trymerb
git clone git://github.com/hassox/restful-authentication.git
cd restful-authentication
git checkout -b merbful_authentication origin/merbful_authentication
sudo rake install

cd trymerb/myblog
merb-gen authenticated user_model session_controller

Our post resource

Restful merb resource that is. This creates the controller, model, and view. If you are using ActiveRecord, I would also expect a migration. For Datamapper, the columns are defined in the model. Use rake to create the tables from the model. (For Postgres, use the datetime type instead of the timestamp type you would use in Rails.)
merb-gen resource post title:string content:text created_at:datetime
rake dm:db:automigrate
Edit config/router.rb to enable these actions:
  # RESTful routes
  r.resources :posts

 # Change this for your home page to be available at /
  r.match('/').to(:controller => 'posts', :action =>'index')

Starting Merb

Open a new terminal window and start merb from your app directory
cd trymerb/myblog
merb
Now point your brower to http://localhost:4000/ and you should be able to see it. The resource generator does not yet build the ERB files out like Rails’ scaffolding. So we have to write that ourselves.

Note that this is where some of the differences between Rails and Merb shows up. Merb has its own routing using the url() helper. Read more about it here .

url(:posts)       #=> "/posts" 
url(:new_post) #=> "/posts/new" 

@post = Post[1]
url(:post, @post) #=> "/posts/1" 
Edit the app/views/posts/index.html.erb and add in a simple post listing.
<h1>My Blog</h1>

<% @posts.each do |n| %>
  <h2><%= n.title %></h2>
  <div2><%= n.content %></div>
<% end %>

<div>
  <%= link_to "Write new", url(:new_post) %>
</div>

Edit the app/views/posts/new.html.erb and add in the compose form. Feel free to embellish your HTML. I added the hidden field to remember how to do it if I need to figure it out again.

As you see, the field control helpers are different, but self-explanatory. They were actually the hardest part to figure out since they needed to be installed from the proper repository and enabled in the init.rb file. The source code also shows more of what you need to do.

<h1>Write a new post</h1>
<%= error_messages_for :post %>

<% form_for(@post, :action=>url(:posts), :method=>"post") do %>
  <%= hidden_field :name=>:wave, :value=>'hello' %>
  <%= text_control :title, :label=>"Title", :size=>50, 
    :maxlength=>250, :style=>"font-weight:bold;" %>
  <br /><%= text_area_control :content, :label=>"Rant", :rows=>15, :cols=>50 %>
  <br /><%= submit_button  "Save" %>
<% end %>

That should do it! Enjoy your new merb blog app.

More Things with merb

The Merb console

The merb object has some things worth exploring, like the app object in Rails.
merb -i
irb(main):001:0> merb.show_routes

Debugger

Like with Rails 2.0, call the “debugger” function where you want a breakpoint. and start merb like this:
merb -D

Merb on Thin

You can run the Thin web server with Merb.
sudo gem install thin
merb -a thin

Disclaimer

This was my first experiment using Merb on Ubuntu, and I am thrilled that it works so well already. This is not quite a recipe for starting from scratch. Some instructions may be convoluted, unnnecessary, copied here incorrectly, or just plain wrong.

Merb is the exciting new direction for developing ruby applications. Ezra is addressing the shortcomings we have in developing and deploying robust applications in ruby. The Rubinius and Merb projects are doing a lot to make this happen.

Email on Rails

written by allen on August 6th, 2007 @ 05:04 PM

I am giving a talk this evening at the Philly On Rails meeting on an introduction to email and sending and receiving email with a Ruby on Rails application.

I am referencing the slides and a sample application in case anyone needs to reference them!

Email Basics

written by allen on August 6th, 2007 @ 02:06 PM

What is email exactly? It is quite different from the view we see in our MUA, (Thunderbird, gmail, mutt, pine, etc.). Let’s review the basic of email mechanics, shall we?

Email consists on an Envelope and the Message Data. The envelope is

  • Return Path: The email address to return the message if undeliverable
  • Recipients: The email address(es) of the recipients of the message

The Message Data is the meat of the mail,

  • RFC822 Headers such as Subject, From, To, Date, etc. Headers can span multiple lines by starting the subsequent line with a white-space. A blank line signals the end of the header and the start of the body follows. Non-standard header names begin with the “X-” prefix, used to denote experimental features. These usually have meaning only to the software that placed them there.
  • Body, text, html, etc. Using the MIME standard, the body can be made to include alternate versions of the message based on markup, and also attach files to the message.
  • File Attachments. Usually, binary files are encoded in Base64 no non-printable characters. This increases the file size by about 33% when encoded in the message.

Note that the From and To headers in the headers are really informational. It is the envelope recipient list that determines who it was from.

Also, since the From header can be virtually anything, it is easy to spoof the sender or even the full message. Even the recipient return path can be bogus. Therefore, email is not secure as such (except for PGP/GPG signings), and should not be trusted outright.

Since each email server that passes the message along prepends a Received header to the top of the message, you can generally trace its path to see if it came from a source server that is a proper MTA for the sender. Of course, you can only trust the received headers from servers as far back as you trust; they can also be tampered with.


To: you@example.com
From: me@example.com
Date: 20 Jul 2007 09:21:51 -0700
Message-ID: <521.1090340511@example.com>
Subject: Simple Email Message

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas
ultrices sem sed urna accumsan cursus. 

Content-Type and MIME Types

When you want to create more complex email messages, say with alternative content or attachments, you need to construct your message using MIME containers and body parts.

  • Content-Type: Use this header in your email message to identify the MIME type of your content
  • text/plain is the default MIME type of email. This is viewable by all mail clients.
  • text/html denotes an HTML formatted body or part. This is only viewable in GUI-based clients that support HTML.
  • multipart/alternative is a MIME container that holds the text, HTML or other versions of the main message. Only one of these (the best one it can show) is viewable by the user’s mail client.
  • multipart/alternative is a MIME container used for attaching files to the message body. The first part is the body part (which can also be another container), and the rest are attachments.
  • multipart/related is a MIME container that wraps included graphics referenced from an HTML body. These graphics are shown “in place”, such as a logo in the letterhead, instead of being seen as attachments.
  • The boundary parameter of the Content-Type header is used to provide a unique identifier to define the start and end of the body parts within a MIME container. Lines starting with two hyphens followed by the boundary value is the split point in the message. The final boundary line is the two hyphens, boundary value, and two more hyphens.
  • image/png is a PNG graphic file, also a image/gif or image/jpeg could be used.
  • application/pdf is a pdf attachment, which could be any application-defined file
  • Stir to combine…

Each MIME body part (attachment, container, or message version) itself has a small MIME header set to indicate its content-type, encoding, and other information.

Here is an example message that is composed of a text and HTML body alternatives, with an image attachment called out from the HTML version, plus another image as a regular attachment. The structure of the MIME parts is


multipart/mixed (Holds the body part plus attachments)
    multipart/alternative (groups the different version of the message body)
        text/plain
        multipart/related (groups the HTML part with images it references)
            text/html
            image/jpeg
    image/png (attachment)

Here is how this looks in the email message.


To: you@example.com
From: me@example.com
Date: 20 Jul 2007 09:21:51 -0700
Message-ID: <521.1090340511@example.com>
Subject: Complex Email Message
MIME-Version: 1.0
Content-Type: multipart/mixed;
        boundary="mm001" 

This is a multi-part message in MIME format.

--mm001
Content-Type: multipart-alternative; boundary=mb001

--ma001
Content-Type: text/plain

This is the plain text body

--ma001
Content-Type: multipart-related; boundary="mr001" 

--mr001
Content-Type: text/html
Content-Transfer-Encoding: quoted-printable

This is the <em>HTML</em> body
<IMG=20SRC=3D"No%20AttachName"=20alt=3D"Picture=20(Metafile)">

--mr001
Content-Type: image/jpeg; name="logo.jpg" 
Content-Transfer-Encoding: base64
Content-Description: Picture (Metafile)
Content-Location: No%20AttachName

Qk2ewgIAAAAAADYAAAAoAAAAJAIAAG4AAAABABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
....

--mr001-- 

--ma001--

--mm001
Content-Type: image/png; 
    name="elroy-jetson.png" 
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
    filename="elroy-jetson.png" 

R0lGODlhMgAvAPcAAAAAAJQAAPfOjP//////////////////////////////////////////////
.....

--mm001-- 

Content-Transfer-Encoding

Note the use of quoted-printable in the above HTML segment. Quoted-printable encoding escapes special characters with an equal symbol (=) followed by the 2-character hexadecimal ASCII representation of the character value. For example, any equal symbols in the body are replaced with ”=3D”, where 3D is the hexadecimal representation of the equal symbol in the ASCII collating sequence.

Web browsers do something similar when sending special characters in the URL, but using a percent (%) symbol as the escape symbol.

Quoted-printable also wraps text so lines do not become too long. An equal symbol at the end of the line (=\n) indicates the line is wrapped. Email standards define the maximum length of a line to be 77 (?) characters, but since this is not a hard limit, most email software is flexible about this limit.

Binary files are usually encoded in Base64. The Base64 method maps every 6 bits to a printable character. Ruby has a Base64 helper class


require "base64" 
enc   = Base64.encode64('Send reinforcements') # -> "U2VuZCByZWluZm9yY2VtZW50cw==\n" 
plain = Base64.decode64(enc)  # -> "Send reinforcements" 

SMTP: How Email is Tranferred

Email is delivered via SMTP, Simple Mail Transport Protocol. This is a simple state-machine which accepts email through a “command line” interface, usually over port 25. Open a telnet connection to any MX(mail exchanger) host on port 25 to try your hand at delivering a mail manually.

Here you can really see that the email envelope is powerful, it requires 3 part of the email message:
  • Return Path (MAIL FROM)
  • Recipients: (RCPT TO)
  • Message: (DATA), which is ended by a single period on the last line.

220 example.com mailfront ESMTP
MAIL FROM: <me@yahoo.com>
250 2.1.0 Sender accepted.
RCPT TO: <you@example.org>
250 OK
DATA
354 End your message with a period on a line by itself.
Subject: Hello there
From: Me <me@yahoo.com>

I just love SMTP!
.
250 2.6.0 Accepted message qp 16590 bytes 226
QUIT
221 2.0.0 Good bye.

The new Girders blog

written by allen on March 6th, 2007 @ 05:21 PM

Alt-Ctrl-Delete!

A new blog, new host, new language (ruby), and new blog software (mephisto).

Options:

Size

Colors
  • orange
  • blue
  • green
  • pink
  • cyan
  • red
  • violet