Basic Concepts

Every piece of information displayed here is stored as a snip. Snips, within their contents, can also reference other snips.

For example, consider the snip tutorial-basic-snip-inclusion:

This is a snip, which includes another {link_to snip}: {tutorial-another-snip}

is rendered into:

This is a snip, which includes another snip: this is another snip!

Notice the use of curly brackets to reference one snip from inside another. Vanilla.rb finds these references to snips, then renders that snip and replaces it in the first snip. Neat!

Renderers

The way that a snip is rendered depends on whether or not it has a render_as attribute set. For instance, the render_as property of this snip (vanilla-rb) is "Markdown". This means that the content of this snip will be passed through Vanilla::Renderers::Markdown before it is then rendered to the page. There are several different renders provided by Vanilla.rb at the moment:

It's using this last renderer that a second concept of Vanilla is implemented - dynasnips.

Dynasnips

Because the curly braces simply cause a snip to be rendered, we can use this in conjunction with the Ruby renderer to run actual code. For instance, in the snip above:

This is a snip, which includes another {link_to snip}: {tutorial-another-snip}

we can see a reference to the link_to snip - {link_to snip}.

Lets look at the raw content of link_to:

LinkTo

As you can see, it simply refers to the Ruby class LinkTo, which is contained within the vanilla-rb codebase. When the Ruby renderer is called, expects the given code to evaulate to a Ruby class. It then instantiates the class, and calls a handle method on the instance, passing it any other arguments from the snip inclusion. So, in the case of {link_to snip}, the only argument is snip.

Vanilla.rb includes a number of dynasnips by default. Here are a couple:

While dynasnip classes can be provided as part of the vanilla codebase, it's envisioned that much of these will be created by end users in their own sites, either by refering to local classes, or defining the classes directly as the content. Here's an example of that, as the raw content of hello_world:

class HelloWorld
  # although the name doesn't need to match the snip name,
  # it's simple to follow that convention where appropriate

  def handle(name=nil)
    if name
      "Hey #{name} - Hello World!"
    else
      "Hello World!"
    end
  end

  # note that this code must evaluate to a class. One way of achieving that is by 
  # putting 'self' at the end of the class definition.
  self
end
# Another way is by referring to the class at the end of the content. Either works fine.
HelloWorld

which, when rendered, gives:

Hello World!

Note that the handle method can take one (optional) argument. Lets try including it with {hello_world Dave}:

Hey Dave - Hello World!

Anyway - that should be enough to get you started.