Smart Tech for a better Web

Ruby and Jekyll: First steps

von

I have to admit, I was looking long time at Ruby. I even started to script a few lines and liked it, but I never tried to get really into it. Today I changed mind, as I have a new project upcoming and the collegs are using Ruby. With an other project in mind, I installed Jekyll and started to create a few static pages with it. Installation was easy and straightforward, I was impressed. But soon I found out I need a plugin. And as Jekyll is a Ruby program, I needed to code in Ruby.

Basically my first "serious" lines of code was plugin, which would take a list of known Jekyll pages and returns it if it would match the first tokens of a String. In other terms, I want a list of pages which are in the same subfolder.

For example:

/book/hello.html
/book/conclusion.html
/other/other.html
/index.html

The Jekyll tag toc which I planned to create should return all the URLs matching a specific portion, in my case "book".

The tag should look like:

&#123% toc /book %}

Whenever I write this into my template, the table of content should appear. Thanks to the easy Jekyll plugin architecture and it's docs I got easily into it. This is my plugin:

class String
  def starts_with?(prefix)
    self[0, prefix.length - 1] == prefix.strip
  end
end

module Jekyll
  class TableOfContentTag < Liquid::Tag
    def initialize(tag_name, folder, tokens)
      @folder = folder
    end

   def pageHtml(site)
      html = "<ul>"
      site.pages.each do |p|
         if (p.url.starts_with?(@folder) )
            html = html + "<li>#{p.url}</li>"     
         end
      end
      html + "</ul>"
   end

    def render(context)
      pageHtml(context.registers[:site])
    end
  end
end

Liquid::Template.register_tag('toc', Jekyll::TableOfContentTag)

I had several lessions to learn. First, I did not succeed with the String.startswith method. It is <a href="http://ruby-doc.org/core-1.8.7/String.html#method-i-startwith-3F" target="_blank">documented, but whenever I called it, it said there is no such method. Not sure why. But lucky me, I found out that I could extend the String class very easy with Ruby. Look at the first portions of my code, where I "redefine" the String and add a method. I am not sure if I actually like this, because you can extend classes wherever you want. Doesn't this lead to pretty hard to understand code? On the other hand, JavaScript does it similar. I need more to learn about class extensions in Ruby.

Then I create a class within the module Jekyll. I learned about instance variables, prefixed with @. And of course that the return keyword is in some cases optional (the last statement is returned by default, cool stuff). Within the initialize method I get the String I want to use as a folder. Please take care: white spaces and line endings included. Therefore I need my custom starts_with method, which does call the "strip" method on my String, which removes the crap. It took me a while to find that out, until I learned about:

prefix.class.name #=> returns the name of a class
prefix.bytes.as_a #=> returns the bytes of the prefix var

The first line showed me I had the correct types to compare (String). But the second line showed me there was an invisible character: whitespace. It drove me nuts, until I found out. But actually it is pretty easy so far, but of course you need to learn about it first.

Another confusing thing is that Rubyists use ? and ! in their method names. I was pretty confused, because I thought they have a special meaning. It seems it has not.

Well, it took me a good while to code, but I like Ruby so far. Glad I have invested some time now and will look into my future project with a smile. And yes, I think Jekyll is a fantastic tool: I learned it so quickly, that I even don't bother to write much about it now :-)

Now I need to improve my plugin to return page names as link, but this is easy going.

Tags: #Jekyll #Open Source #Ruby

Newsletter

ABMELDEN

BLOG-POST TEILEN

When you load these comments, you'll be connected to Disqus. Privacy Statement.