Intro to Functions
When you are just writing quick scripts, you can use Ruby all you want and be happy. However, there comes a point where you have to do the same thing in a bunch of places. Functions are a way to organize the logic in your code so that you can re-use it in more than one place. I’ll introduce how to do math at the beginning, but functions aren’t only for numbers as we will show later.
Doing Some Math
As long as you are working with numbers, you will have to remember some symbols. In your math text books you will see symbols that just don’t exist on keyboards and requires different key combination to make them show up. The good news is that the conventions for replacing mathematical symbols in code is pretty standard across languages. You only have to learn them once, which helps.
- + addition
- - subtraction
- * multiplication
- / division
- % modulus
- ^ exponent
- () group expressions
Math expressions are performed in algebraic order. In short, that means that expressions are evaluated in the reverse order from what I listed. Parentheses first, exponents next, then multiplication, division and modulus, finally addition and subtraction. Just to make it clear, look at the following code:
puts 4 + 5 * 6 # 34 puts (4 + 5) * 6 # 54 puts 4 + (5 * 6) # 34
It’s a good habit to use parentheses to make things clearer. There’s a few more symbols that allow you to do bit manipulation, but then I have to explain the math behind it. Let’s focus on this level of math for now. Let’s say we want to do a little trigonometry and calculate the area of a circle. The mathematical formula for the area of a circle is πr2. So how do we get a hold of the value of π? There is a Ruby module called Math that has the value of π and other more advanced functions.
Ok, so how does the expression look like in Ruby?
radius = 5 puts Math::PI * (radius ^ 2) # 15.707963267949
I added the parentheses to make it clearer that the exponent (raising to the power of two) comes first. So what if we wanted to reuse this function anywhere? We would have to create a function to do it. It’s pretty easy, and you will use the same construct in another post when we talk about creating our own methods. Let’s create our function:
def area radius
Math::PI * (radius ^ 2)
end
So what’s going on here? The word def is a Ruby keyword that tells Ruby that you are creating a function. After that, is the name of the function. Finally we have the list of parameters. A parameter is a name we give to a value that you pass to the function. Basically, the function is going to do something with that value—even though it doesn’t know what the value is first. The next line bears some explaining.
Functions can return a value, which is usually their whole point. However, we don’t see any words that say “return this”. It’s probably the most unintuitive thing you’ll run into with Ruby, but the last expression in a function is the value that’s returned. It’s a carryover from Smalltalk, and once you understand that it becomes a little more understandable. If we had one more line that just had the number 2 on it, then the function would always return the number 2—which is wrong for what we want. What some people do to make things a bit clearer is to use the keyword return . That keyword is designed for letting you leave a method early for some cases, but it works just as well. It’s probably not a bad habit as other languages require you to use it. The method would now look like this:
def area radius
return Math::PI * (radius ^ 2)
end
The keyword end is something we saw already when we were doing loops in the last lesson. This keyword is used to end any block, so you will use it a lot.
Not All Functions Are for Math
I introduced functions with math because that’s where the idea came from. But most problems don’t require the use of heavy math. Ruby isn’t designed to be a math engine anyway. Just for fun, let’s create a function that will turn a number into words—Japanese words to be exact. It’s only fitting as Ruby came from Japan after all. Just to save us some work, we’ll limit ourselves to the range from 0 to 99. To do that we need to use an if statement. The if statement let’s us do something if it is true, but skips the code inside if it is not true. We also want to raise an issue so that the calling code knows that they asked something we can’t deliver. The keyword is raise , which is rather convenient. You can “raise” any object, but we will just use a string. The code looks like this:
if not (0..99).include? number
raise "We can only translate numbers between 0 and 99"
end
I’ll include the solution below, and just expound on things in comments. Your job is to expand the method to do up to 999, or to change it to another language. I’m using Japanese partly because it’s easy to do with code. Other languages have more exceptions.
def to_japanese(number)
#
# Protect our method from trying to work on numbers
# it doesn't support
#
if not (0..99).include? number
raise "We can only translate numbers between 0 and 99"
end
#
# Keep it simple, use the variations of four and
# nine that work in the tens column as well as
# the ones column. These are the numbers from
# zero to nine.
#
numbers = ['rei', 'ichi', 'ni', 'san', 'yon', 'go',
'roku', 'nana', 'hachi', 'kyu']
#
# Modulus gives the remainder.
# 12 divided by 10 is 1 with a remainder of 2.
# It's a good way to get just the ones column.
# Then we use regular division to get just the tens column
#
ones = number % 10
tens = number / 10
case tens
# When we are doing 10 - 19
when 1
japanese = (0 == ones) ? 'ju' : 'ju ' + numbers[ones]
# When we are doing 20 - 99
when 2..9
japanese = numbers[tens] + ' ju'
if (ones > 0)
japanese = [japanese, numbers[ones]].join(' ')
end
# Otherwise we are doing 0-9
else
japanese = numbers[ones]
end
return japanese
end
So there are a couple things I need to explain above. First is the case, when, else construct. The case statement tells Ruby that we are going to use the following expression (in this example the expression is a variable) with a bunch of comparisons. It’s a little nicer than doing a bunch of if/else statements. The first match is what gets run. Each case that we are checking is marked with the when statement. To translate it to English, it’s like saying “when tens is 1 do this”, “when tens is in the range 2..9 do that”, “otherwise do this”.
The next thing I have to explain is the (something) ? true : false construct. It’s a shorthand for an if/else statement. Essentially, we are saying that if the ones column is 0, just return ‘ju’ otherwise return ‘ju ’ plus the translation of the ones column. Have fun!
Using Many Objects at Once
Last article was meant to introduce you to the terminology that is common to object oriented languages. You should have a clear idea of what an Object is and what a Method is. Today, we are going to learn about how to use more than one object at a time. We’ll start with simple variables, which are simply names for objects you are using so you can get to them again. Then we’ll talk about some special objects called containers, whose sole purpose is to organize a group of objects for you.
A container is an object that holds a bunch of other objects
Variables
So there’s a little more terminology here. We can assign objects to individual variables fairly easily just by giving a name, using the equals sign, and the value. For example:
my_variable = 12345
As long as the first character of the variable name starts with a letter or an underscore “” character, the rest of the characters can be letters, numbers, and underscores. Almost all languages have this requirement, so that the computer doesn’t get confused between what is supposed to be a number and what is supposed to be a variable. Just a little helpful advice from someone with experience here, use variable names that make sense. It is better to type a few extra keys than wonder whether _cntr meant counter or center later on. It’s also better to use names that reflect the variable’s purpose rather than what it is made of.
array = ['cero', 'uno', 'dos', 'tres'] ones_column = ['cero', 'uno', 'dos', 'tres']
The variable named ‘array’ is kind of silly. It describes what kind of object is assigned to the variable rather than what we are using the variable for. The variable named ‘ones_column’ describes the purpose for the variable better. We are using an array of names to write out the ones column of a number.
Variables let us hold on to objects with a user friendly name so we can use them later
Arrays
Since we already introduced how to create an array above, let’s talk about how they are used. Arrays hold a bunch of related values together so that we can use them in interesting ways. Using the ‘ones_column’ example above, we can use any single digit number to get the name of that number.
Arrays are lists of information
puts ones_column[2] # prints 'dos'
Remember in the last lesson, when we had a number do something using the times method? The number passed back to our code started at zero. The number inside the square brackets is an index number that starts at zero. So the first element in the array is always 0, not 1. That’s why we started the array with ‘cero’ (Spanish for zero) instead of ‘uno’ (Spanish for one).
An Array is a Collection, so like all collections it has an each method. The each method works just like the times method on the number objects. The method will pass back the elements (the objects) of the array one at a time in order. So, if we wanted to count in Spanish, we would use our ones_column array like this:
ones_column.each do |number| puts number end
Hash
A Hash allows you to map one object as a key and another object as the value. Other languages will call the Hash a Map or a Dictionary, essentially letting you look up one object (a definition) using another object (the word to look up). Think of the word key in the terms of a map key. A symbol represents a concept, so to speak.
Hash lets you associate key objects with value objects
In Ruby, Hashes are created using the curly braces, and the key/value pairs are marked with the phrase: key => value . They can be quite handy when you have a lot of information to pass from one place to the next. One variable would take all the name/value pairs. If it helps, think of it as a collection of variables. It is most common to see string names be the key, but in Ruby we also have something called a symbol. Strings are surrounded by quotes, and they can change. Symbols have a colon in front and they never change.
my_map = {'string' => 'surrounded by quotes',
:symbol => 'starts with colon',
:string => 'not the same as a string'}
puts my_map['string'] # shows 'surrounded by quotes'
puts my_map[:symbol] # shows 'starts with colon'
puts my_map[:string] # shows 'not the same as a string'
puts my_map[:string.to_s] # shows 'surrounded by quotes'
In the above code, we set up a map of keys to string values. Just so you know, the objects don’t have to be the same type. In fact you’ll see that we used one string and two symbols for keys. You’ll also see that the Hash object treats them differently. The last lookup call might cause a little confusion, so look at the method being called on the symbol. The to_s method is on every Ruby object, and it is a convenient way to get a string out of the object. For a symbol, the to_s returns the name of the symbol (everything except for the colon). Because that happens to be the same name as a string key that is already in the map, it returns the value that belongs to the string.
This brings up a very important point, particularly for newbies. Save yourself a lot of headaches, and only use keys of the same type until you know exactly what you are doing. If you ever use many types of objects for different keys make sure you document your code with your comments. You don’t want to run the chance of spending hours tracking down a bug only to find it is the same thing I showed here. Talk about your ‘Doh!’ moments.
Strings
Ok, the Array and Map are good enough to get you going—there are more collection types and more things you can do with these collections, but strings are pretty important in programming. The string is your best tool for communicating with the user. On web forms, your values are all strings, and when you add content onto a page, they are strings. There are three ways of working with strings in Ruby, depending on how much power you need. We will introduce them from the simplest to the most complex.
Strings hold text
simple_string = 'single quotes and no processing'
The above string is rather simple. The single quotes mean to take the text AS IS, no escaped characters, no single quotes, and no formatting. You’d be surprised by how much you can use this simple declaration. If we ever needed to stick two strings together, we can use the plus sign (’+’).
hello = 'Hello' world = 'World' puts hello + ' ' + world #shows 'Hello World'
Things can get messy when you have to show information your program has back to the user. The ’+’ concatenation only works for strings, so each object that is not a string needs to call the to_s method to be concatenated. Oh, and then you still have the problem of formatting the text to be pretty. There is a more powerful way to declare and use strings, and that is to use double quotes:
number = 4
puts "Number:\t#{number}"
In the string we sent directly to the puts method, we see a bunch of stuff that might look confusing at first. The first funny looking characters would be the ”\t”. The backslash (’\’) is an escape character, so you can access more special characters with it. You can embed double quotes by adding a backslash in front, or in this case you can embed a tab character. Essentially, we told the string to embed some white space. The next set of funny looking characters would be ”#{number}”, but when you realize that the number inside the curly braces is the same name as the variable we defined before, it suddenly becomes a little less confusing. Basically anything between the ’#{’ and ‘}’ will be treated like regular ruby. You can even do math in there if you really wanted. It’s best to keep it simple and only use it to display the value of variables in your string.
That’s all well and good, but what if I have a lot of text, I only need to embed a little bit of Ruby variables, and I want to do all the spacing and carriage returns myself? There is a way to define a big string by providing your own “terminator”. The terminator is just so that Ruby can know when the string is done and it can go back to normal Ruby processing.
really_big = <<-END This string will keep going and going on and on until I use the terminator to make it end. END puts really_big
You can embed variables just like before using the ’#{}’ construct, but there really isn’t a whole lot of need for escape characters and such. When you have a big message you want to give to the user, this is usually the best way to get it done. The important thing is that you choose the terminator so it will never be text in your block. The characters ‘<<-’ basically tell ruby to keep adding lines to the string until we reach X where X is the terminator. In my example, I chose the word END in all capital letters, but you could just as well use TERMINAR or BATTLE_FLAG or any other gibberish you want. The string will start on the following line and continue until it hits the terminator you set up. Just make sure it is clear what you are doing so that when you come back to the code later you aren’t thinking What in the world did I do?
Intro to Programming with Ruby
First of all, Ruby is a programming language that has become pretty popular with the advent of Ruby on Rails . That said, Ruby is a great first programming language to learn. I won’t bore you with it’s history, even though the language has been in existence for over a decade. For the summary about Ruby, check out http://www.ruby-lang.org/en/about/ and also look at the different tutorials. This tutorial is meant for people who don’t know squat about programming. If it’s confusing at all, let me know in the comments.
Before we delve into objects and things like that, let’s consider what happens when we have to use Ruby to help with other tasks. Those tasks can be deployment scripts, test support, etc. One of the most important things you will learn has nothing to do with actually making stuff work. It’s the comment. Basically you want to leave notes for yourself so that you can get back into the swing of things after you leave something alone for a while. To do that with Ruby, all you need is the ’#’ symbol. It marks the beginning of a comment, and the comment is over at the end of the line.
# # A block of comments looks like this, with a '#' symbol # at the beginning of every line. Comments are supposed # to help you remember things later on. #
Start with good commenting habits, and keep them up. Some things are pretty self explanatory so make sure you document the big things and not what every line is doing. Remember that these are clues you leave to yourself, or anyone else who will work with the code about what’s going on.
Now, Ruby is an object oriented language, but before I get into making objects let’s look at what they can do for you. In Ruby, everything is an object—your numbers, ranges, collections, etc. To help wrap your brain around objects, think of them as “things”.
Objects are things you can tell what to do.
Let’s say you need something to be done five times. The number five is an object, which means you can tell it to do something for you. Core Ruby Doc has all the standard objects that are part of the language, but it can be a little overwhelming at the beginning. First of all, the number five is an Integer (there are no decimal points so math people tell us that the correct name is an Integer). If you look up Integer in the Ruby docs, you’ll find that a list of things that it can do. There are two that look pretty interesting to us, but for now we just want to do something five times. Here’s how we do it:
5.times do |num|
puts 'Do something!'
end
Ok, what’s going on here? The number five is an object, and the ”.” symbol means “tell the object to do something”. The name after the ”.” is what we are telling it to do. So we are basically saying “Number 5, I want you to .times”. OK, so we are missing part of the picture. That part is the do block. Everything between the do and end is also being passed along with the message ”.times”. Let’s call the ”.times” message a method.
A method is something you can tell an object to do.
Continuing on, we have the do block followed by some pipe symbols ”|” and a name in the middle. This is how the number 5 passes something back into your do block so that you can use it. The name you give this something is called a variable. You can use it or ignore it, it’s up to you. We are ignoring it for now, but if we want to use it, we just have to use that name.
5.times do |count|
puts 'Do something on time ' + count
end
What you see will change based on the value of the variable “count” that the number 5 is giving us. The documentation tells us that the number will start at 0 and go to just under our number. So we will see five lines counting up from 0 to 4. A lot of programming languages do this, so it’s just something you have to get used to. Everything between the do and the end markers gets run each time. The important thing is that the variable you named inside the ”|” symbols is how you use that variable.
OK, we are taking some baby steps here, but I’ll stop for today. First of all, we learned that things are called Objects and we tell Objects what to do by calling Methods (some people call them messages, but other languages use the word Method so we are just being consistent). We also learned that you could pass in a whole block into a method and have that object run that block for us. We learned that when we pass in a block to an object’s message, it can pass something back into our block so that we can use it. I want to point out that the whole “pass a block of code” thing is something that not every language can do. For instance at the time I am writing this, Java, C#, and C++ can’t do that.
Lastly, I want to start you thinking about something. The best code is self documenting, but it will never read like a book. As long as the details are clear, all you have to worry about in your comments is why you are doing something five times. With the last snippet of code above, it almost reads like English. We are saying “five times do something using ‘count’”. The word “puts” is actually a method on the text console object. Ruby makes some assumptions to make the code a little more readable.
Judicious Use of Closures 9
After going back and reviewing some of my old articles, I got to thinking that my role based authorization system I outlined in this article still reflected my Java bias. I know some people approach new toys and technologies by diving in head first, and then backing off later. I personally try to think of what problems that approach can practically solve. As a result I may be a late bloomer, but the flowers are nicer.
The whole issue of why I thought it could be better is because it is still too Java/C++ based. I tried to make it more rubyesque but I stopped short. You see, in the Java/C++/C# world you think about having to query an object and then do something. This is in stark contrast to the Smalltalk and Ruby approach where you tell an object to do something for you. You can even pass in some extra steps so that you can be very happy. So what’s the difference, and does it really make a big deal? The difference is subtle, but so is elegance. Let’s consider the code I had you write to do work if a user had a particular role:
if @user.is_in_role? (:Admin) Article.find(params[:id]).destroy flash[:notice] = 'Article was successfully deleted.' end
The “is_in_role?” message is straight from Java’s HttpServletRequest interface. It does make sense from a certain point of view, but the control is inverted from what it should be. In short, we should tell the user to do something if they have a roll. Here’s how the same logic should look from the subtle shift in viewpoint:
@user.with_role :Admin do Article.find(params[:id]).destroy flash[:notice] = 'Article was successfully deleted.' end
So what’s the big deal? They both do the same thing, and they are both pretty readable. The big fat hairy deal is in perspective. The first version is interrogative, we are treating the user object like a little child and taking back control. We aren’t letting the user object do his part of the chores. The the second version is imperative, we are telling the user object what we need him to do. We trust him to make judgments like whether he can do it or not. The implementation of the method is just about the same under the covers, but the important thing to stress is who is doing what. We should provide general directions, and the objects should pull their own weight to make it happen.
Ruby is really great when it comes to closures. Every method implicitly handle closures. The trick is the yield keyword. If you want to pass a parameter to the closure, just add it on to the yield command. Here is how our implementation would look if we did the more rubyesque approach:
def with_role role
if roles.include? Role[role]
yield
end
end
That’s pretty slick when you think about it. You can make any method handle closures just by using the yield command. If we needed to pass parameters, we just tack them on after the yield command. There’s tons of applications for it, but it’s best to start off slow. After you add support for a closure to an object’s method, ask yourself if it makes life better. Is the code that matters more readable? Does it simplify life? The answers to those questions will help you walk the balance between elegant and gimmicky.
Contrast Ruby With Java
I’m cheating a little bit with referencing the current specification proposal for JSR for Closures in Java as it represents the closest thing to what you can expect here. First of all, if you use Ruby or Smalltalk you will be sorely disappointed. In a sense, Java closures still follow the same pattern in that the closure is an object—only you have to be explicit about it. Edit: Apparently I missed a very important, and good part of the new Java closure spec. I’m changing the code examples to reflect the preferred method.
First, let’s look at the Java way of solving the problem we solved with Ruby:
if ( user.isInRole("Admin") ) {
Article.find(id).destroy();
sendMessage( "Article was successfully deleted." );
}
It’s fairly readable, and it doesn’t look too bad. Again, we are treating the user object like a little child. We are asking the object about itself and assuming control. The approach has its roots in the procedural world that the C based languages came from. Now let’s look at what the new Java Closures will look like, and whether that will help things be more readable.
user.withRole("Admin") {
Article.find(id).destroy();
sendMessage( "Article was successfully deleted." );
}
There is an uglier way of declaring the closure, but since we want the code to be as elegant as possible I chose this form. Before I go into details of what is going on under the hood, we need to see the other half of the equation so we can better understand what’s going on. Here’s the implementation of the withRole method:
public void withRole(String role, {=>void} block) {
if ( roles.contains( role ) ) {
block.invoke();
}
}
Under the covers, the definition of the closure is the ugly {=>void} block. That’s telling the compiler to create an anonymous interface that has a method named invoke with no parameters and returns a void. Ok, time to take a breath. If we want to add parameters to the invoke method, we have to add them as a comma separated list in front of the => symbol. The void after the symbol is the return type. The implementation of this anonymous interface is assigned to the variable name block. There’s a bit more to it, and you can reference variables declared outside the block—but for the purposes of our conversation let’s keep it simple.
When we pass in our implementation, we use the same basic construct except we add variable names to the parameters and the implementation after the ugly symbol. We cheated in our example by not having any parameters. You might think that because the method tells what types the variables are you could skip the type declaration. You’d be dead wrong. Consider the example the spec provides (granted this is from the original specs:
// Define it
{int,int=>int} math;
// Assign it
math = {int x, int y =>
return x + y;
};
// Invoke it
assert 2 == math.invoke(1, 1);
Edit: I had to revise my initial reactions based on the input from commenters. The Java spec has come a long way. Although it’s not perfect (and what in life is?), it is a vast improvement over what we once had. The critical part of Java closures is that they are really closures. That means that you can reference variables declared outside the closure (you can’t do that with anonymous inner classes), and they enable more flexible, robust, and readable code. At least on the calling side of things. Java will never match the simplicity and elegance of Ruby, but this time it will be much improved.
The Languages Are Different, Play to Their Strengths
What I don’t want you to do is walk away with the impression that Ruby is great and Java sucks. I work with both technologies, one because I want to and the other because I’m paid to. They both have their strengths, design idioms, and code aesthetic. The important thing is to play up the strengths of the language you are using.
Just because a solution is elegant in one language doesn’t mean the same approach translates well to another. Sometimes it’s just plain impossible. Other times, the overall approach is fantastic, but the implementation will have to have subtle differences based on the language you are using. That’s OK too. My Java ActionPack is based on most of the design principles of Ruby’s action-pack (part of Rails), but they are done in a very Java way. They evolved differently, appealing to what is considered elegant and good code for the respective languages they are written for.
Edit: It appears that there are quite a few things I don’t quite get about the Java closure spec. Until we have something solid to play with, everything said is academics. Neal Grafter is the headmaster for the spec, and he should know better than I about what can and can’t be done with it.
Getting Typo 4.1.1 Installed on a Shared Host
Every shared host has their own procedures for getting a Rails app up and running. The instructions that TextDrive has for installing a Rails application does a great job for them. However there are a few gotchas that you need to be aware of. First and foremost the installed version of Rails at TextDrive does not match what Typo 4.1.1 needs. Not to mention that the quotas installed for users are pretty limiting for RAM usage. You can't run gem update or install because it exceeds the memory allowed for a user (you can run gem list --local, but that's about it). That means you can't use the preferred method for Typo installation! Such a pain, but all is not lost.
Preparing the Typo Package
Typo needs Rails version 1.2.2 to function properly. It needs at least 1.2.0, but I did find issues with 1.2.3 and I didn't have time to figure out what they where. So, how do we publish an application that needs a different version of Rails than our host provides? Thankfully the Rails folks already have a solution for that, which was designed to let you play with "EdgeRails" (or the latest trunk). First, let's make sure you have the appropriate version of Rails installed on your local machine:
gem uninstall rails gem install rails --version '= 1.2.2'
Now that the right version of rails is installed on your machine, we have to install it into the typo distribution. Download the tarball from the Typo website, and unpack it on your machine:
tar xzf typo-4.1.1.tgz
With the command line, navigate into the distribution directory. The following command is probably a good idea no matter where you are publishing--particularly on a shared host. You don't have control over when your ISP decides to upgrade or change things. We are going to "Freeze" the version of rails to the gems you just installed on your machine.
rake rails:freeze:gems
Now you can repack the tar file. Go ahead and delete the old tarball before you pack it. The Rails app will have paths that are too long for the "old" style tar so you can't use the 'o' option. The following worked well:
tar czf typo-4.1.1.tgz typo-4.1.1
All you have to do at this point is upload the tarball to your account on your ISP. Unpack the tarball
Setting up the Database
The next step is to get the database up and running. Do whatever you need with your ISP to create a database for typo, and run the appropriate SQL script provided in the typo/db directory to set up the database schema. Next you'll have to configure the database.yml. The Typo team was good enough to provide an example configuration file. You just need to edit it to connect to your ISP's database instance. Just for safe keeping, do change the database name to the same thing for the development, test, and production configurations.
As a way to test the database connection, and to ensure everything is configured properly, you'll need to run the migrate task.
RAILS_ENV=production rake db:migrate
There's just a couple things left to do now.
Configure The Application
We need to make things easier on ourselves, so whether your ISP lets you set environment variables for running tasks or not, you'll want to uncomment the line to force the rails environment to production in the config/environment.rb file:
ENV['RAILS_ENV'] = 'production'
Also, because shared hosting is usually pretty limiting on your memory allocations, you'll want to disable any plugins that generate thumbnails. Find the line where the config/environment.rb file specifies plugins and edit it to look like this:
config.plugins = [ 'localization',
'typo_textfilter_tmcode' ]
Finally, most ISP instructions include changing the public/dispatch.* files so that the hashbang line has an explicit reference to your ISP's ruby interpreter. There's no guarantee that the env will find the ruby interpreter, and it removes one thing the machine has to do to get the app running.
Assuming the rest of the instructions from your ISP worked to get the app visible to the world, you will be able to go into the blog, create your username/password and manage the blog. I highly recommend keeping the sidebar simple. Only use static text, archives, syndication, and tags (and categories if you want) plugins when you have to share your host. The Magnolia and Flickr plugins generate thumbnails which look nice, but you'll run out of memory quick and the fastcgi process will die.
