Caius Theory

Now with even more cowbell…

Use datamapper sessions with merb & datamapper

Issue

Can't use merb sessions with datamapper & mysql, get back an error about needing an id on the text column or something (I had the error a couple of days ago.)

Solution

I suggest grabbing merb_datamapper svn source to fix this in. To do so make sure you have subversion installed on your machine (I'm assuming a Unix based machine here.)

  1. Checkout the source

     svn co http://svn.devjavu.com/merb/plugins/merb_datamapper
    
  2. Open up the affected file in your favourite editor (I use TextMate)

     cd merb_datamapper
     mate lib/merb/sessions/data_mapper_session.rb
    
  3. Find line 25 that contains

     `property :session_id, :text, :lazy => false, :key => true`
    

    and remove :text, :lazy => false to replace it with :string

     `property :session_id, :string, :key => true`
    

    Save and close the file, thats the editing done. Now to install the gem.

  4. Build the gem

     rake gem
    
  5. Install the gem

     sudo gem install pkg/merb_datamapper-0.5.gem
    

And you're away with the fix installed. Now just run merb to create your sessions table in the db. Hope this helped!

Refactoring code logically

And now an example of how I write my ruby code and get it down to the bare, readable, minimum code needed. This is real life code taken from a website I'm building, but I've changed the objects to a blog post because more people will relate to that easier.

The show object has an id passed in using the params Hash, I want to check if that post exists in the database first. If it does, then render the page, and if it doesn't return a 404 error page.

So I start off by writing this in longhand ruby, I'm using the merb framework with DataMapper ORM by the way.

def show
  @post = Post.first(params[:id])
  if @post
    render
  else
    raise "404 - Not found"
  end
end

Now whilst theres nothing wrong with this code, it just doesn't look right to me. There is a big if/else statement in there whilst I'm sure there doesn't need to be.

Now I know if I return at any point in a ruby method, it exits the method at that point. So the first thing to is to refactor the if test to remove a line of code. I shall assign @post to the result of the DB as the actual if statement's test.

def show
  if (@post = Post.first(params[:id]))
    render
  else
    raise "404 - Not found"
  end
end

So thats reading slightly better, and also is a line less of code. Now I wonder if I can use a return true in there to stop me having to explicitly state an else clause.

def show
  if (@post = post.first(params[:id]))
    render
    return true
  end
  raise "404 - Not found"
end

Now the eagerest amongst you will be wondering what the advantage of that code is. It doesn't appear any more readable (slightly less in fact as you have to figure out its an implicit else) and is exactly the same amount of lines as the previous example. But what if we change the if to an if ! and flip the code logic around?

def show
  if ! (@post = Post.first(params[:id]))
    raise "404 - not found"
  end
  render
end

Now a raise will stop the code executing, and in the real application you would in fact just redirect to your 404 error page. The problem now is the if ! looks ugly and isn't easily readable.

All unless does is if !, that is, if the inverse of the result of the test statement is true, then invoke the block given to it. A quick example for you:

# without unless
if !@user.logged_in?
  puts "Please login."
end
    
# using unless
unless @user.logged_in?
  puts "Please login."
end

Now whilst if ! doesn't seem that bad compared to unless, the readablility of the code increases. It reads more as a flow of logic, and is quicker for the human brain to walk through (my brain anyway!)

So using unless we get 4 lines of code that is easily readable.

def show
  unless (@post = Post.first(params[:id]))
    raise "404 - Not found"
  end
  render
end

Now what if we go one step further and use the unless shorthand way of testing and exectuting one line of code?

def show
  raise "404 - Not found" unless (@post = Post.first(params[:id]))
  render
end

And that is generally how I write my code logically. Of course for something simple like this I'd probably jump in at the last block having refactored it in my head first, but for more complex things I tend to write them exlicitly and then refactor them down whilst maintaining readability of my code.

Command line tricks: Scripting Languages

To search your php.ini file quickly and easily with the option to use regular expressions, I tend to drop back to the cli. The reason for this is I can easily parse the output of phpinfo() with grep, and can do various things with the output, could even pass it to a script if I really wanted to.

Here is the line I use to search phpinfo()

echo "<?php phpinfo() ?>" | php | grep -i $search_string

It passes the string through the php interpreter and then searches through it with grep.

You can also do other nifty things with the shell & php + ruby especially (though I imagine python & perl work in the same way.) For instance I wanted to see if the following ruby would return the number of seconds since the epoch till now.

puts Time.now.to_i

Now I could fire up a PHP page and do something like the following

<?php
  echo "php: " . time() . "\n";
  echo "ruby: " . `ruby -e 'print Time.now.to_i'` . "\n";
?>

But what if I've not got a web server with PHP running on the machine I'm using? Well then I could drop back to the shell and run it through php using cat as a way to insert multiple lines, and it would look like the following

cat <<PHP | php
<?php
  echo "php: " . time() . "\n";
  echo "ruby: " . `ruby -e 'print Time.now.to_i'` . "\n";
PHP

php: 1203004463
ruby: 1203004463

Now this works, but why do I want to remember all that php, and seeing as I have to drop back to the shell to access the ruby statement, why not just let the shell do all the work? So after a few seconds thinking, I came up with this

ruby -e 'puts "ruby: #{Time.now.to_i}"' && \
  echo '<?php echo "PHP: " . time() . "\n" ?>' | php

This runs the ruby code through ruby and the php code through php without dropping back to the shell from within a language interpreter :)

Update:

Fangel pointed out php -r is the equivilent of ruby -e so the final commands could just be:

ruby -e 'puts "ruby: #{Time.now.to_i}"' && \
php -r 'echo "PHP: ".time()."\n";'