Understanding the &: Ruby syntax

The symbol.to_proc method was something I hesitated to use for a long time because I found it be unclear and something that went against Ruby’s clear and easy to understand syntax. Though this subject is old news its something I’ve found that goes against ruby’s clarity over cleverness standards.

The Proc Object

A Proc object is block code that can be accessed as an Object. A proc when defined associates itself to a set of variables (local) and can be used at later point of time in the context of those variables

The official definition

So lets consider a simple example

def test(&block)
   puts  block.class.to_s  # "Proc"
   block.call  # would execute the block of code
end

test{puts "Bazingaaa" } # Bazingaa

So the result would be

"Proc"
Bazingaa

Its just a block of code that you can run whenever you want.

Now Ruby symbols have a to_proc method which allows you to convert a symbol to a proc.

 :test.methods.include?('to_proc')
 => true

:someSymbol.to_proc # Would yield a proc object #

Now if we go through the array.map code from the Ruby library, we see that it executes a block of code on each element of the array.

  array.map     {|item| block }  -> an_array
 p  [1,2,3,4,5].map(Proc.new{ |x| x + 1 }) # 2,3,4,5,6

If we create a simple block and pass it to the map method it would execute the code in the block for each element.

So the &: is actually &symbol and not &:something. Since the conversion of the to_proc method is not explicit the code

p [1,2,3,4,5].map(&:to_i) 

is actually

p [1,2,3,4,5].map(&(Proc.new{|x| x.to_i}))

The to_proc method as found in Rails 2.3.5

  def to_proc
      Proc.new { |*args| args.shift.__send__(self, *args) }
    end

Hope this helps someone

Advertisements

Including Url Helpers in Models

The title itself may set off alarm bells among MVC purists and I agree that it is a clear violation of the MVC pattern. In an ideal world there shouldn’t be any url generation done in the models and if the need arises for the use url_helpers in your model then one can safely assume that something is not how its supposed to be.

One of my personal projects had me generate urls from my model for a post which was to be passed on to a Twitter module to be posted as a tweet. Now clearly the data generation belongs to the model and hence I concluded that this is where the code belongs.

So how do we get the UrlHelpers in the model

Before Rails 3 it was

 include ActionController::UrlWriter

and assuming that you have the default_url_options for host set you could access any url.

In Rails 3 ActionController::UriWriter is deprecated and what needs to be included is

include Rails.application.routes.url_helpers 

and everything works as advertised.

Rails version 3.0.1 actively includew Rails.application.routes.url_helpers with deprecation warnings on inclusion of ActionController::UrlWriter

I am sure there is a more elegant work around to do this but till I figure it out this should work.

Javascript: Awesomeness

I have been working with Javascript for over a year now and have been using it as language to manipulate the DOM. I had never taken Javascript seriously enough or thought of it to be a real language till a few months back when I had to start working with Orbited.

Recently I went back to understand the basics of Javascript and I decided to go through some of the things that I found were really awesome. Now most of this stuff may be lame for experienced programmers but I hope this helps someone who starting off.

Objects

I knew that Javascript had primitives and Object types. So going through a small example here

var s = "Mary had a little lamb";
alert(typeof s); // This would display 'string'

var ss = new String("Bazingaa");
alert(typeof ss); // This would display 'Object'

If you notice, without really having the need to define an object javascript still lets you call methods on primitives types. For example

 var s = "Soft Kitty";
alert(s.length); // 10

Javascript creates transient objects for all primitives types so that methods may be called upon them and destroys them when no longer needed. (How cool is that!).

So now the question is are strings passed by reference or by value, because all primitives types are passed by value and Objects passed by reference. The answer is, its hard to tell, but it doesn’t matter as strings are immutable so basically you cannot change the value stored in them and when you do you are in fact creating a new object.

Website for this, Really?

I happened to meet one of my school friends online and exchanged a couple of emails. Part of the conversation was about the school reunion that he was looking after along with another friend. Since he happened to be collecting details (I’m guessing excel, at least) and sending emails via facebook and gmail, seemed like an obvious situation to suggest that he use some website that helps him organize these events since facebook wasn’t really cutting it and his reply was “and a website for all this…hehe…dude”

I am not completely sure if I was the one who was completely out of my mind to suggest a website or see this as a reason to build something new (since facebook is for most, the one site to rule us all), but what surprised me was how disdainfully he dismissed the suggestion considering he would be spending the same if not more time doing the same thing on facebook.

Im sure facebook does this well, but there is more to an event that just sending invites :).

WMD Editor, Storing data as Markdown and not HTML

I recently had to add a Rich Text Editor to one of our applications and to one of my personal projects and I opted for WMD Editor, primarily because its a light weight, pure javascript based editor which takes less than 2 lines to install and configure. (Okay, there is no real installation its Javascript) and it lets me preview the text instantly without having to reload or open the formatted text on a separate window. I can’t understand how blog sites overlook this feature and something which stackoverflow has completely nailed. I see sites like Posterous not even providing a preview (if it does exists its well hidden).

The problem I encountered was storing data as HTML. I absolutely hate storing information as HTML and WMD Editor comes configured by default to return HTML data. So a bit of googling helped me figure out how to configure WMD to return Markdown instead of HTML.

You can always convert markdown to html using any simple plugin or gem, (I used RedCloth)

You can get WMD Editor from here

To configure the editor unzip the folder and open the wmd.js file and make the following changes

Attacklab.wmd_defaults = {version:1, output:"HTML", lineLength:40, delayLoad:false};

Change this to

Attacklab.wmd_defaults = {version:1, output:"markdown", lineLength:40, delayLoad:false};

and your good to go.

I found this bit on SO . Thanks to fiskfisk

Hope this is handy.

Edit update:

I just tried RDiscount and its much better than RedCloth and clearly they way to go.

Rails 3 deprecated methods

This is the list of methods that have been deprecated in the Rails 3. The following list has been compiled by Paul Schreiber and has been obtained from one of his answers on Stack Overflow..

I found this extremely useful and this is purely to help others looking for similar information.

Railties now deprecates:

RAILS_ROOT in favor of Rails.root,
RAILS_ENV in favor of Rails.env, and
RAILS_DEFAULT_LOGGER in favor of Rails.logger.

ActionController:

  • The cookie_verifier_secret has been deprecated and now instead it is assigned through Rails.application.config.cookie_secret and moved into its own file: config/initializers/cookie_verification_secret.rb.
  • filter_parameter_logging is deprecated in favor of config.filter_parameters << :password.

ActiveRecord

  • named_scope in an Active Record class is deprecated and has been renamed to just scope.
  • save(false) is deprecated, in favor of save(:validate => false).
  • model.errors.on is deprecated in favor of model.errors[]
  • ActiveRecord::Base.colorize_logging and config.active_record.colorize_logging are deprecated in favor of Rails::LogSubscriber.colorize_logging or config.colorize_logging

ActionMailer

  • :charset, :content_type, :mime_version, :implicit_parts_order are all deprecated in favor of ActionMailer.default :key => value style declarations.
  • Mailer dynamic create_method_name and deliver_method_name are deprecated, just call method_name which now returns a Mail::Message object.
  • ActionMailer.deliver(message) is deprecated, just call message.deliver.
    template_root is deprecated, pass options to a render call inside a proc from the format.mime_type method inside the mail generation block
  • The body method to define instance variables is deprecated (body {:ivar => value}), just declare instance variables in the method directly and they will be available in the view.
  • Mailers being in app/models is deprecated, use app/mailers instead.

Though I haven’t been able find anything about the validate method for the model. I have been facing the following deprecation warning and I am not completely clear if the validate method has been deprecated or if the warning refers to something else

Overwriting validate in your models has been deprecated,
please use Base#validate :method_name instead

Hope this is useful

Getting Rails3 working with Jquery

I’ve been playing around with Rails 3 over the weekend and the changes made with the usage of Protoype and Jquery and the handling of :delete requests with Javascript got me a bit confused so incase your using Jquery and wondering why those DELETE requests show up as GET requests on the server log try having a look at RailsCasts episode 205 and read through the setup with jquery here .

If you’ve added the Jquery file already chances are that your rails.js file is missing or your still using the one from the prototype set. Sorting that out should get you back on track.

Hope this helps

 

Setting up a mail server

Im sure almost everyone is familiar with Posterous’ killer mail-in feature that allows you to email your blog post to update your blog page, so I won’t ramble on about how awesome I find that feature (yet, I’m still using wordpress largely because my blog migration ended up requiring me to reformat all my posts on posterous again and it does not let me preview my blog.)

So my goal was to setup a mail server that would accept incoming posts (emails which could contain anything from your blog post to images ) to update user accounts or databases.

The way I planned this was to use postfix as my mail server that would use a catch-all email address which would collect and save all the emails in a Mail directory and would allow me to use a ruby program to periodically check the Maildir for new mails to process.

The second part of the process is beautifully described in Jason Seifer’s blog on receiving mails with Rails where he also describes how to configure your server but I needed to google around a lot to actually get that done. Though Jason Seifer’s blog describes a technique which allows you to forward your mails directly to a ruby program I decided to stick with Rick Olsen’s suggestion on having a separate daemon process work on a Maildir

I used an Ec2, Ubuntu instance to setup my basic Rails application and I sent in the necessary requests to ensure that the reverse DNS lookup points to my domain.Here’s a brief overview on the things I had to do setup the mailserver .

Open up the required ports and remember to open the SMTP ports (25) to all. (I realized this the after being ridiculed at the IRC channel.) I realized that EC2 opens the port for you but you need to ensure that its open to all or it won’t be reachable from the outside and you’ll end receiving annoying sending Delayed messages all the time.

This is an automatically generated Delivery Status Notification

THIS IS A WARNING MESSAGE ONLY.

YOU DO NOT NEED TO RESEND YOUR MESSAGE.

Delivery to the following recipient has been delayed:

Message will be retried for 2 more day(s)

Technical details of temporary failure:
The recipient server did not accept our requests to connect. Learn more at http://mail.google.com/support/bin/answer.py?answer=7720
[mail.example.in. (10): Connection timed out]

I did not realize this as I was able to telnet to port 25 but the guys at the IRC channel couldn’t. Just in case your curious on how to open a port to all on EC2 have a look at my earlier posts.

Once your done with that its time to add the MX records

A   mail.example.in     123.123.3.11 (delete)       300         2010-10-12 03:37:24
A   example.in          123.123.3.11 (delete)       300         2010-10-11 04:34:53
MX  example.in          mail.example.in (delete)    300     10  2010-10-12 02:03:03
A   www.example.in      123.123.3.11 (delete)       300         2010-10-11 04:34:15
MX  www.example.in      mail.example.in (delete)    300     10  2010-10-12 02:12:51

It could look something like this. I was using name.com but this view may differ based on your provider.

The MX records are crazy important at the time of configuration and here are some useful docs on how you go about adding MX records

Oversimplified DNS
Check if your DNS settings are correct
Getting Started Guide

Once your done with that install postfix,

sudo apt-get install postfix

and your good to go. The configuration steps expect you to respond to certain questions. The answers would be as follows

1. For an internet site (Since your building an web based site)
2. mail.example.com (where example is your domain name)

Time to create the catch all email address that will receive all the email. I created an Ubuntu user called ‘sid’ to whom these mails would be pushed to but there are ways where this need not be an actual user.

Postfix uses a mbox format to store your mails but I read that the Maildir is better and faster and less susceptible to corruption. In case you are curious about the difference here is a nice place to start.

So to manually convert your mbox format to a maildir format

sudo postconf -e 'home_mailbox = Maildir/'

So this would create a /home/sid/Maildir to store all your mails.

DoveCot is package that allows you to configure SMTP-AUTH. You can configure this in other ways but this is the easiest I could find.


“SMTP-AUTH allows a client to identify itself through an authentication mechanism (SASL). Transport Layer Security (TLS) should be used to encrypt the authentication process. Once authenticated the SMTP server will allow the client to relay mail. “

sudo apt-get install dovecot-postfix

Thats pretty much our mail server. Now to allow are mail server to receive mail from the outside we need to check if we can access port 25 (Remember to open this for all) and verify our postfix configuration file (/etc/postfix/main.cf) to check if the inet_interfaces is set to all

inet_interfaces =  all

Try telnetting to port 25 and if you see something like

Trying 11.1.1.111..
Connected to 11.1.1.111.
Escape character is '^]'.
220 example.com ESMTP Postfix

your good.

Next is to setup our catch-all address

Open up /etc/postfix/virtual (this would be an empty file in most cases) and add

@your_domain_name    the_ubuntu_username_you_want_to_forward_mails_to

The @yourdomainname is a accept-all entry that will push all mails that reach your domain to the maildir of the user listed next to it.

You may also have a specific id like post@mydomainname being sent to user sid

save the file and verify if your configuration (/etc/postfix/main.cf) file has the following line

virtual_alias_maps = hash:/etc/postfix/virtual

if not add it and reload postfix

sudo postmap /etc/postfix/virtual

sudo service postfix reload

Thats pretty much all there is to it.

Here are a set of references that been extremely useful to me
ServerFault: Postfix can’t receive external mail
Postfix setup catch-all email accounts using /etc/postfix/virtual
Postfix
Amazon Reverse DNS Request Form

Hope this is helpful.

vn: warning: cannot set LC_CTYPE locale svn: warning: environment variable LANG is en_US.UTF-8 svn: warning: please check that your locale name is correct

This is one of the weird errors I encountered today where, suddenly I could not update my server with my recent commits and the error read as

 svn: warning: cannot set LC_CTYPE locale
 svn: warning: environment variable LANG is en_US.UTF-8
 svn: warning: please check that your locale name is correct

I found the solution on http://shep-dev.com/?p=16 which helped me get rid of the problem. Apparently the problem is that the LANG specified isn’t installed. (Though I have no clue how it got uninstalled, it worked till yesterday evening.)

apt-get install language-pack-en-base

This pretty much gets you back on track and install the en language pack. So thanks to Chris Shepherd of Shep Ajile Development LLC im moving on to the next issue.