Cheat Sheet for All Design Patterns Implemented in Ruby

Cheat sheet for all design patterns implemented in Ruby?

Design patterns are useful for organizing massive amounts of code. since you don't need to write as much code to do things in ruby as you do in #{verbose_algol_derivitive_language}, they don't have the same degree of importance.

What you will see used all the time is strategy and builder implemented with blocks (an example of builder would be form_for blocks in rails views, an example of strategy would be File.open) I can't really think of the last time I saw any others (gof patterns anyways)

EDIT: responding to

You mean with ruby we don't have to
think about design patterns in most
cases? Another question, if I'm using
Rails, do I actually have to think
about design patterns? Cause I don't
know where to use them. They don't
seem to fit in any component of the
MVC. Are design patterns only for
people that are building massive
libraries/frameworks eg. Rails,
DataMapper, MongoID etc and not for
others that only using these
frameworks/libraries?

For the most part, rails makes a lot of your decisions for you, and will until your app hits a fairly high level of complexity. Even if you are using something like sinatra though (which doesn't decide anything for you), you still won't really need to reach for those GoF patterns the same way as you would in a language like (for example) java.

This is because the whole point of design patterns is bottled ways to keep things flexible and maintainable. If that is built into the language, often they aren't even needed.

For example, a strategy pattern implemented in java looks sort of like this

//StrategyExample test application

class StrategyExample {

public static void main(String[] args) {

Context context;

// Three contexts following different strategies
context = new Context(new ConcreteStrategyAdd());
int resultA = context.executeStrategy(3,4);

context = new Context(new ConcreteStrategySubtract());
int resultB = context.executeStrategy(3,4);

context = new Context(new ConcreteStrategyMultiply());
int resultC = context.executeStrategy(3,4);

}

}

// The classes that implement a concrete strategy should implement this

// The context class uses this to call the concrete strategy
interface Strategy {

int execute(int a, int b);

}

// Implements the algorithm using the strategy interface
class ConcreteStrategyAdd implements Strategy {

public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyAdd's execute()");
return a + b; // Do an addition with a and b
}

}

class ConcreteStrategySubtract implements Strategy {

public int execute(int a, int b) {
System.out.println("Called ConcreteStrategySubtract's execute()");
return a - b; // Do a subtraction with a and b
}

}

class ConcreteStrategyMultiply implements Strategy {

public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyMultiply's execute()");
return a * b; // Do a multiplication with a and b
}

}

// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
class Context {

private Strategy strategy;

// Constructor
public Context(Strategy strategy) {
this.strategy = strategy;
}

public int executeStrategy(int a, int b) {
return strategy.execute(a, b);
}

}

It is a lot of work, but what you end up with is worth it a lot of the time, and can be the difference between a big ball of mud, and something that has a chance in hell of being maintained. Now lets do it in ruby

class Context
def initialize(&strategy)
@strategy = strategy
end

def execute
@strategy.call
end
end

a = Context.new { puts 'Doing the task the normal way' }
a.execute #=> Doing the task the normal way

b = Context.new { puts 'Doing the task alternatively' }
b.execute #=> Doing the task alternatively

c = Context.new { puts 'Doing the task even more alternatively' }
c.execute #=> Doing the task even more alternatively

its hard to even call that a pattern, you are just using blocks! When the language covers the needs that the pattern addresses, effectively using the language will mean you don't really need the pattern in most circumstances. It also means you can elegantly address that kind of problem when it would be horrible overkill to do a java style strategy.

Snippets/examples for practical rubyish design patterns?

AFAIK, there is the source code for Design Patterns in Ruby and the source code for Metaprogramming Ruby. Perhaps these snippets are not so useful or practical on their own, but they contain many design patterns, idioms, and "spells" in Ruby.

Of course, it would be great if someone could point us to a more practical set of ruby snippets, if such a set exists.

Where should I place code which generates Excel spreadsheet?

  1. Create an excel library in your lib folder in which you include your xls generation routine as well as a method that overrides ActionController's render method.
  2. In a model that should be rendered as xls implement a method called to_excel method which generates a hash that you can provide to your xls routine.
  3. Doing it this way, you'll get something really "Railsy". In your controller you'll just call

    render :xls => @model

Not able to style Excel with spreadsheet gem (Ruby)

Well, it was not possible to format the existing excel then write it as a new Excel. Formatting was lost in that.
To overcome I created a new excel (populated with my existing data read from the old excel) formatted it as I want then used

book.write "xxx.xls"

Why all the Active Record hate?

There's ActiveRecord the Design Pattern and ActiveRecord the Rails ORM Library, and there's also a ton of knock-offs for .NET, and other languages.

These are all different things. They mostly follow that design pattern, but extend and modify it in many different ways, so before anyone says "ActiveRecord Sucks" it needs to be qualified by saying "which ActiveRecord, there's heaps?"

I'm only familiar with Rails' ActiveRecord, I'll try address all the complaints which have been raised in context of using it.

@BlaM

The problem that I see with Active Records is, that it's always just about one table

Code:

class Person
belongs_to :company
end
people = Person.find(:all, :include => :company )

This generates SQL with LEFT JOIN companies on companies.id = person.company_id, and automatically generates associated Company objects so you can do people.first.company and it doesn't need to hit the database because the data is already present.

@pix0r

The inherent problem with Active Record is that database queries are automatically generated and executed to populate objects and modify database records

Code:

person = Person.find_by_sql("giant complicated sql query")

This is discouraged as it's ugly, but for the cases where you just plain and simply need to write raw SQL, it's easily done.

@Tim Sullivan

...and you select several instances of the model, you're basically doing a "select * from ..."

Code:

people = Person.find(:all, :select=>'name, id')

This will only select the name and ID columns from the database, all the other 'attributes' in the mapped objects will just be nil, unless you manually reload that object, and so on.

CSS applied to all pages but one - Ruby/Sinatra

I think this might resolve your issue, I think the link to your stylesheets might be broken.
If the page is not in the top-path, if it looks something like this:

http://localhost/namespace/ThisIsThePage

In your layout.erb-file, you are refering to the stylesheets using:

href="style.css"

In your CSS-imports, I'd recommend to refer to the stylesheets by using e.g:

href="/style.css"

Note the slash before the filename. The slash tells the browser that the resource will loaded from the root-path of your webserver. Without the slash, the browser will try to grab the style.css from the path below:

http://localhost/namespace/style.css



Related Topics



Leave a reply



Submit