Sunday, November 20, 2011

Creating emails with Rails

By default, rails sends emails with the MIME type text/plain, but sometimes you might wish to make your emails look better, by adding links or images and for that you need your mail to have the MIME type of text/html.

The easier way to do this, would be by change the content type variable in the notifier.rb file, but if you do that, email reader that don't support html will not show your email correctly.

So how have the best of both worlds with as little effort as possible? Fear not my friends, for RoR convention over configuration policy has come to the rescue yet again!

All that you need to do is to create two files in your notifier views, one with the name whatever_you_want.text.html.erb and another with the name whatever_you_want.text.plain.erb and rails ActiveMailer will take care of the rest for you. Sweet!

PS: This is for rails 2.x, in rails 3.x the names would be whatever_you_want.text.erb and whatever_you_want.html.erb

Saturday, October 1, 2011

Properly show errors with Paperclip and Formtastic

Paperclip has for while now decided that each of its files should have 5 arrays of errors, one for each field it stores in the database (file_name, file_size, content_type and updated_at) and one for the actual file object.

If you are using it alongside with formtastic (or even if you are not), this can be the cause of some problems when trying to show those errors to the client. Therefore, I created a little method to concatenate all these arrays into one.

def properly_show_errors(record)
  if @record.errors.any?
    flash[:error] = []

    @record.errors.each do |attribute,msg|
      if attribute =~ /.+_content_type/ || attribute =~ /.+_content_file_size/
        proper_attribute = attribute.split('_')[0]
        @record.errors.delete_all_at proper_attribute
        @record.errors.add proper_attribute,msg

This takes a record and merges the content_type and content_file_size errors into its own error array. The message can be internationalized in the model to whom the file concerns, as such:

validates_attachment_size :image, :less_than => 1.megabytes, :message => I18n::t('flash.image_size_1mb')

The record is passed on as an instance variable of the caller class. In my use case this caller class is an action in the controller, for instance when creating a page:

flash.now[:error] = t("flash.page_not_updated", :name => page.title) 

This will render the page creation form with the error on the flash div, and the record instance variable with page and its errors. The two things of note in this piece of code are the way of using helpers in a controller with the @template variable, and the flash.now that will make the flash message last only one redirect.

Note: This 'bug' has been fixed in formtastic version 1.2.0 and above, but this is still pertinent for those using a prior version

Sunday, September 18, 2011

Dynamic HTML container size with CSS + JS

Have you ever tried to make a container (let's say a span) have the size of the text dynamically, without you having to har code it? Here's how I've done it using JavaScript (actually JQuery) and some CSS.

First let's define the markup:

<span id="ruler"></span>
<div class="wrapper">
    <span class="name">Hello World</span>
    <span class="name">I am a very very very very very big string.......................</span>
    <span class="name">I am a normal string</span>

The only thing of notice here is the span with the id ruler, this span is empty and is what is going to help us measure the string size in pixels.

Now for the javascript:

String.prototype.visualLength = function() {
    var width = $("#ruler").width();
    return width;

$("span.name").each(function() {
    $(this).css("width", $(this).text().visualLength());

This defines a new function for Strings called visualLength that puts the string in the ruler span, gets the width in pixels and cleans it. Then there is an iterator that sets the width for each of the spans we've defined to the one returned by the function.

And that is it. Now we just need some CSS, to make use of this:

    display: block;
    border: 3px solid #FF0000; 

    width: 500px;
    border: 3px solid #000;  

    visibility: hidden;

This code makes the ruler invisible and impedes the text from wrapping. The rest is just an example of how to use this feature to center your text in an outer container. Here is a demo.

Note: The javascript code was based on a blog somewhere, but I cannot seem to find it. If someone knows the link, I'll be happy to refer it.

Saturday, August 27, 2011

Integrating git and rvm with prompt

Here's a quick hack to your prompt, that I find helpful when using git and rvm.

Add this to you .bash_profile, .bashrc, or whatever file you use to configure your shell:

export PROMPT_COMMAND='PS1="\[\033[0;33m\][\!] \h\`
if [[ \$? = "0" ]]; then echo "\\[\\033[32m\\]";
else echo "\\[\\033[31m\\]"; fi
\` \`
if [[ `pwd|wc -c|tr -d " "` > 60 ]]; then echo ":..$(expr "$PWD" : ".*\(/.*.\{40\}\)")";
else echo ${PWD/\/Users\/$(whoami)/\~}; fi
\`\[\] $(parse_git_branch)\[\]\[\033[0m\]$(rvm_version.sh)\[\033[0m\]: ";
echo -ne "\033]0;`hostname -s`:`pwd`\007"'

Now you need the parse_git_branch and rvm_version.sh.

Parse Git Branch

parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/[\1]/'

RVM Version

ruby_version=$(/usr/local/rvm/bin/rvm current)
if [ -f "Gemfile" ] # If it is a rails project
  if [ -e "app/assets" ] # If rails version >= 3.1
    if [[ $ruby_version != *1.9* ]] # If not using correct rvm version
      echo -n "\\[\\033[31m\\]"
      echo -n "\\[\\033[32m\\]"
  else # If rails version >= 3.1
    if [[ $ruby_version != *1.8* ]]
      echo -n "\\[\\033[31m\\]"
      echo -n "\\[\\033[32m\\]"
  echo -n [$(/usr/local/rvm/bin/rvm current)]
  echo -n "\\[\\033[32m\\]"

Put them somewhere in some directory that's in your PATH, and it should work. What it does, as far as git and rvm go, is tell what branch your on, and if your using the correct rvm for your rails project (turns red if your not).

I'll probably work a little more on the rvm_version, that is the only thing that I can actually get credit for, but for now it works.

Monday, July 18, 2011

Project Euler

Project Euler is a website that proposes various problems, related to programming and/or math. You can solve the problem anyway you like, as it only asks for the result. If you get it right, you can then check out how others have done it or, in some cases, have an explanation from the guys at project euler.

It is very addictive and fun, I highly recommend it!

I've been solving the problems entirely in Ruby, and committing my code to github. Check out my solutions, and don't hesitate to let me know if you find a better one, or even a bug. ;)

Tuesday, May 31, 2011

Bridging the gap between SQL ao NoSQL: A state of the art

Here is a state of the art report I wrote on SQL and NoSQL, and a way to bring them closer. This is actually the theme of my master thesis, so you should probably get some more posts on this topic in the future.

Hasta. ;)


Monday, May 9, 2011

Running a Cassandra cluster with only one machine

I've noticed that if you want to run a cassandra cluster on your own pc, for the purpose of small tests, there is no guide in the wiki to do just that.

Therefore, here is how I've done it.

First of you'll need to create an alias for you network interface:

Mac OS
ifconfig en0 alias

ifconfig eth0:0

Here I've chosen the en0 (or eth0) interface, but you can choose the one you like, and also the IP address you like.

The first file you'll have to edit is the conf/cassandra.yaml:

- Change the commit_log, data and saved_caches directories, so it doesn't conflict with the ones from the previous "node";
- Change the rpc_port (used for Thrift or Avro) to one that is free;
- Change the listen_address to the IP of your "fake" interface.

Next open the conf/cassandra-env.sh file and change the JMX_PORT.

The last file to edit is the bin/cassandra.in.sh where you'll need to change all the occurences of $CASSANDRA_HOME to the path of the "node". For example, if you're bin directory is in /XXX/YYY/node2/bin, the path is /XXX/YYY/node2.

You can do this to create as many nodes as you want, and then just run them as usual, with bin/cassandra -f