Archive for the ‘Tutorials’ Category

How to use a non-singleton version of Configatron

Thursday, November 20th, 2008

Since Configatron has come out it’s become a pretty popular library, and because of that I’ve received several feature requests. Nothing wrong with that. I actually welcome that, because, let’s be honest, that’s how configatron will become even better.

The biggest request I’ve received is from people who want to use Configatron, but they want their own instance of it, and not the global singleton instance of it. Although, I personally don’t see why you would need that, I’m a big enough man to understand that just because I don’t need it, doesn’t mean others don’t.

Last night I was reviewing the code, because I was asked this question again, and in doing so I realized that power has been there all along. It’s actually very simple. When you make a call on Kernel#configatron it returns a singleton of the Configatron class, but after that all it does is return an instance of the Configatron::Store class. So if you want your own instance of Configatron, what you really want is an instance of the Configatron::Store class, which you can do like so:

 

Well, there you go, I hope that helps. Enjoy.

Preview (0.7.0): Building Distributed Application w/ Mack (Screencast!)

Monday, August 18th, 2008

On Monday, August 25th, Mack 0.7.0 will be released. This is an extremely important release for Mack. Why is that you ask? Good question. Well, this is release that finally brings the much talked about distributed feature set to Mack. Distributed routes have been around for quite some time, but distributed views/layouts and distributed objects (models) have been missing. Well, in less than a week, you’ll have them!

Now I know that you’re just as excited about what’s coming as I am, that’s why I’ve prepared the first ever Mack screencast to demostrate these features. The screencast is a little rough around the edges, but it gets the ideas across. 

As always I’ll post more about the 0.7.0 as the release date nears. In the meantime enjoy the screencast:

The Mack Distributed Demo Screencast

Here’s the source code.

Preview (0.5.5): Adding PDF::Writer Plugin Support Tutorial

Tuesday, May 20th, 2008

Ok, let’s take the new rendering system out for a spin, shall we? Let’s add the PDF::Writer library to our Obligatory Blog Demo application. If you haven’t followed this demo you should do that now.

Let’s start by requiring the gem in our system. Open up your gems.rb file found in config/initializers and let’s add the gem:

require_gems do |gem|
  gem.add "pdf-writer", :version => "1.1.8", :libs => "pdf/writer"
end

Great! We’ve told Mack we want to use the ‘pdf-writer’ gem, version ‘1.1.8′, and we want to automatically require the file ‘pdf/writer’. Now, let’s install the gem:

$ sudo rake gems:install

See how easy this is? We’ve installed the gem, required the libraries, now we’re ready to write our plugin.

$ rake generate:plugin name=render_pdf

That should generate a few files/folders in our vendor/plugins directory. Let’s open up vendor/plugins/render_pdf/lib/render_pdf.rb and let’s start coding.

What we want to do is create a new Mack::Rendering::Engine::Base class so that when we call render(:action) it will have a new engine to render the view file as a PDF.

We’ll examine each section in a minute, but for now, let’s type this into our render_pdf.rb file:

module Mack
  module Rendering
    module Engine
      class Pdf < Mack::Rendering::Engine::Base

        def render(io, binding)
          @_pdf = ::PDF::Writer.new
          self.view_template.instance_variable_set("@_pdf", @_pdf)
          eval(io, binding)
          @_pdf.render
        end

        def extension
          :pdfw
        end

        module ViewHelpers
          def pdf
            @_pdf
          end
        end

      end
    end
  end
end
Mack::Rendering::ViewTemplate.send(:include, Mack::Rendering::Engine::Pdf::ViewHelpers)
Mack::Rendering::Engine::Registry.register(:action, :pdf)

Ok, so on line #4 we extended Mack::Rendering::Engine::Base. This will give us access to a view methods, and will allow us to write to a very simple API. The only method you are absolutely required to implement is the render method. As we can see on line #6, we did just that.

First thing we do in the render method is instantiate a new PDF::Writer class and assign it to an instance variable. We then set that instance variable into the Mack::Rendering::ViewTemplate object we have. We do that because the way the PDF::Writer object works you need to constantly reference the instance of the writer to do your work. Example:

@_pdf.text "Hello World", :font_size => 24, :justification => :center

On line #9 we eval the io and the binding we’ve been given. The io will be contents of the view file we have disk, as a String, and the binding will be that of the Mack::Rendering::ViewTemplate object we’ve been given.

In the extension method we tell the system that are files are going to be found with the extension, pdfw. Another example of this would be the Erubis engine which declares its extension as erb.

The Mack::Rendering::Engine::Pdf::ViewHelpers module we’ve declared on line #17 is there to hide the @_pdf instance variable with a nicer pdf method. On line #27 we include this module into Mack::Rendering::ViewTemplate so it has access to it.

Finally, and most importantly, we need to register the new engine we’ve built with the system. We do that on line #28 with this bit of code:

Mack::Rendering::Engine::Registry.register(:action, :pdf)

That’s saying whenever someone calls render(:action), consider me as an engine to render that. The way the selection of which engine to use is done, is very simple. First come first serve. The engines are in an array, and the first one to have a file with its extension on disk wins. Plain and simple.

Now, let’s see all this in action. Let’s add PDF support for our ’show’ page.

Open up views/posts/show.html.erb and add the following line:

<%= link_to("pdf", posts_show_url(:id => @post, :format => :pdf)) %>

That will give us a link that looks like ‘/posts/:id.pdf’. This will, of course, go to our PostsController and the show action. This method does not need to be altered. That’s right, you heard me. It does not need to change. Mack will handle the appropriate content-type headers for you. Just another great feature in 0.5.5.

Create a file called views/posts/show.pdf.pdfw. I know this might look a little weird, what with ‘pdf.pdfw’, but here’s the reason why. That’s break the file name down into its three parts. ’show’ is the name of the action. ‘pdf’ is the format of the request, think also html, xml, etc… ‘pdfw’ is the engine we want to use. If we hated ourselves we could do this all in erb with a file called show.pdf.erb, but why would we want to do that?

Anyway, let’s dump this nice block of code into our show.pdf.pdfw file:

pdf.select_font "Times-Roman"
pdf.fill_color(Color::RGB::Red)
pdf.text @post.title, :font_size => 24, :justification => :center
pdf.fill_color(Color::RGB::Black)
pdf.text "by #{@post.email}", :font_size => 12, :justification => :center
pdf.with_options(:font_size => 10, :justification => :left) do |p|
  p.text "\n\n"
  p.text @post.body
  p.text "\n\n"
  p.text "Created at: #{@post.created_at}"
  p.text "Updated at: #{@post.updated_at}"
end

Since this is not a tutorial on this particular gem, I’m not going to go into what all that does. Instead, let’s just have a look at it in action.

Fire up your server:

$ rake server

And go to: http://localhost:3000. If you don’t already have a post created, create one. Now click on the show link. You should have a link on your page that says ‘pdf’ click on that link. Voila! You should be seeing a wonderfully formatted PDF right now!

Congrats! You’ve built a plugin and a new rendering engine for Mack. Now, go crazy!

The source for all this can be found at: http://github.com/markbates/mack_blog_demo/tree/master

0.4.6: The Obligatory ‘Blog’ Demo – Take 2

Friday, April 18th, 2008

This post has moved to the wiki @ http://wiki.mackframework.com/index.php/Blog%20Tutorial

0.3.0: Adding RSS/xml feeds to our Blog demo

Wednesday, March 19th, 2008

Ok, as you remember a while back we created a simple blog using mack, http://www.mackframework.com/2008/03/04/the-obligatory-blog-demo/. Well now it’s time to add the all important RSS/xml feed to it.

Mack 0.3.0 introduces xml rendering support natively, so this shouldn’t be so hard. First things first, let’s fire up the app, shall we:

$ rake server

Now let’s head over to http://localhost:3000/posts. We should see our beautiful posts index page. Now let’s try to go to http://localhost:3000/posts.xml you should see something that looks like this:

XML blog demo 1

Clearly, that’s not what we want, is it? I didn’t think so. The error is telling us that it’s looking for a file called index.xml.erb in the app/views/posts directory of our blog project. Obviously that file doesn’t exist.

Let’s take a second and talk about why Mack was looking for index.xml.erb. We haven’t changed anything in our controller. Our index method still looks something like this:

def index
  @posts = Post.find(:all)
end

No where in there does it mention xml. The only place xml is mentioned is on the the url itself, remember? We looked for /posts.xml. By adding .xml you’re telling Mack that you want to render, well… xml. So it goes looking for that. That’s also new in 0.3.0. The default is html, but if you append a format (.js, .xml, etc…), it will go looking for app/views/<controller_name>/<action_name>.<format>.erb and render it.

Ok, now that we understand why we’re looking for an xml file, let’s fire up our trusty text editor and create a new file called: app/views/posts/index.xml.erb. Let’s edit the file to look like this:

xml.instruct! :x ml, :version=>"1.0"
xml.rss(:version => "2.0") do
  xml.channel do
    xml.title("My Mack Blog")
    xml.link(posts_index_full_url)
    xml.description("Find out about all the cool stuff happening on my blog!")
    xml.language("en-us")
    xml.copyright("Copyright Me")
    xml.pubDate(CGI.rfc1123_date(Time.now))
    xml.lastBuildDate(CGI.rfc1123_date(Time.now))
    @posts.each do |post|
      xml.entry do
        xml.title(post.title)
        xml.link(posts_show_full_url(:id => post.id))
        xml.description(post.body)
        xml.pubDate(post.created_at.strftime("%a, %d %b %Y %H:%M:%S"))
      end
    end
  end
end

Mack uses the standard builder gem library. I’m not going to go into explaining how that works, there are plenty of other tutorials and documentation that will show you that. I’m also not going to explain all the necessary pieces of an RSS feed. Instead I’ll point out in that code you’ll see we’re using the @posts instance variable that we set in the index action of our PostsController. Just like regular *.html.erb files we have access to all the instance variables from the controller, as well, helpers, etc…

So now if we go to http://localhost:3000/posts.xml we should see our RSS feed. If we did a view source we should see something that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
 <channel>
  <title>My Mack Blog</title>
  <link>http://localhost:3000/posts</link>
  <description>Find out about all the cool stuff happening on my blog!</description>
  <language>en-us</language>
  <copyright>Copyright Me</copyright>
  <pubDate>Tue, 18 Mar 2008 17:18:05 GMT</pubDate>
  <lastBuildDate>Tue, 18 Mar 2008 17:18:05 GMT</lastBuildDate>
  <entry>
   <title>My New Post</title>
   <link>http://localhost:3000/posts/1</link>
   <description>This is my first post in my cool Mack blog!</description>
   <pubDate>Tue, 18 Mar 2008 11:58:30</pubDate>
  </entry>
 </channel>
</rss>

Awesome! All that’s really left is create one of those fancy RSS tags in the location field of our browsers that people can click and go straight to the RSS feed. Let’s do that now.

At the top of your app/views/posts/index.html.erb file add the following:

<%= rss_tag(posts_index_url(:format => :x ml)) %>

Now, refresh the page in your browser, and there you go, you should now see the little RSS button in the location bar of your browser. If you click that you should be taken to your feed.

That’s all there is to adding not only xml, but an RSS feed to your new blog.

The code for this demo can be found here.