One of the useful things about Pancake is that you can inherit your full application. This includes routes, bootloaders, configuration, paths and a few other things I won’t expound heavily on here.
What I want to go through is how to use it. Before we get started, make sure you have at least pancake 0.1.20
Since my initial post, Jack Dempsey has written a small test blog for Pancake. It’s not going to upset wordpress at this point (maybe one day), but it will serve to demonstrate inheriting and mounting gem’d stacks. The test blog stack is at http://github.com/jackdempsey/pancake-blog
Install Pancake-Blog
$ git clone git://github.com/jackdempsey/pancake-blog.git
$ cd pancake-blog
$ gem build blog.gemspec
$ gem install blog-x.x.x.gem
Once we’ve got the blog gem installed in the system, lets do the bare minimum to get it running in a container app. Move to another directory:
$ pancake-gen micro blog_container
$ cd blog_container
In pancake, you can progressively add directories of a larger app and they will just work. Lets setup a config.rb file and include an AR connection.
$ mkdir config
touch config/config.rb
Here’s an example of what you can put in there to get the connection setup.
require 'activerecord'
require 'blog'
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:username => "root",
:password => "",
:host => "localhost",
:database => "pancake_blog_development",
:encoding => "utf8"
)
You’ll notice here that we’ve also included the blog gem. Next lets mount the blog in the application. Lets get the blog_container.rb
file looking like this:
class BlogContainer < Pancake::Stacks::Short
add_root(__FILE__)
initialize_stack
router.mount(Blog, "/blog")
end
Initializing the stack will load the config file and mount applications etc. That’s almost it. Before we actually fire it up though, we need to create the database.
$ rake -T
$ rake blog:bootstrap
Pancake will load the rake files from the gem and make them available to you once we’ve mounted the Blog in the router. Now we can start the application 🙂
$ unicorn -p 5000
Head over to http://localhost:5000/blog and you should see a shiny new blog. Enter a few posts and you can see it’s a very very simple app.
Inheriting Stacks
It’s kinda cool that we can mount an app and stuff. But inheriting full apps could be a bit cooler. Lets get that happening. Lets get the blog_container.rb file looking like this:
class BlogContainer < Pancake::Stacks::Short
add_root(__FILE__)
initialize_stack
get "/" do
render :root
end
end
class WagyuBlog < Blog; end
class VegetableBlog < Blog; end
BlogContainer.router do |r|
r.mount(WagyuBlog, "/wagyu")
r.mount(VegetableBlog, "/veggies")
end
We’ll also need to add this to the bottom of the config/config.rb file.
Blog.initialize_stack
This makes sure all the models in Blog are loaded before we inherit.
Ok, so lets start up the app again (with unicorn) and head over to http://localhost:5000/wagyu Aaaannnddd… The posts from before have disappeared… That’s actually intentional. It’s done that way in pancake-blog so you can mount multiple blogs in the one process without clashing the posts.
The model Blog::BlogEntry (the post) is inherited along with Blog so we end up with WagyuBlog::BlogEntry and VegetableBlog::BlogEntry. By doing this we’re segregating the data via STI.
Try it… Go to http://localhost:5000/wagyu and make some posts. Now scoot on over to http://localhost:5000/veggies and put in some posts there. Flip about a bit and you’ll see it’s actually separate.
That’s kinda cool, but we can do better. It’s not much good to have them all behaving the same all the time, and having all the stuff in the blog_container.rb file isn’t the most awesome. Lets mount them through the mounts directory. Create a “mounts” directory and a sub-directory for each blog:
$ mkdir -p mounts/wagyu-blog
$ mkdir -p mounts/vegetable-blog
Now, lets make the blog_container.rb file look like this by removing the inherit calls:
class BlogContainer < Pancake::Stacks::Short
add_root(__FILE__)
initialize_stack
router do |r|
r.mount(WagyuBlog, "/wagyu")
r.mount(VegetableBlog, "/veggies")
end
get "/" do
render :root
end
end
Now, lets create a pancake_init.rb file in each of the sub-directories in “mounts” In them, we’ll put
# mounts/wagyu-blog/pancake_init.rb
class WagyuBlog < Blog
add_root(__FILE__)
end
# mounts/vegetable-blog/pancake_init.rb
class VegetableBlog < Blog
add_root(__FILE__)
end
Start the applciation again. You’ll see that the behavior is the same as doing it the other way. So, what exactly did that buy us? We’ve added a root to each of the blogs. That means we can start tweaking the views and add models / other files etc. We’ll just do one, but it will work for either, or both.
If you look at the pancake-blog source. You’ll see that the view inherits_from :base. Lets replace the base of the wagyu blog. Make a views directory in mounts/wagyu-blog/views
and create a base.html.haml
file. erb and erubis works just as well. Create your template, remember that you need to create a content block for at least :content
(because of the child template in pancake-blog) That means you’ll need something like:
# snip template stuffs
- content_block :content do
%p
No Posts Found
# snip
When you’re playing with templates, it’s a good idea to restart the app with shotgun so that the templates are re-compiled on each request.
shotgun -s thin -p 5000
I’ve made my mounts/waygu-blog/views/base.html.haml
look like this:
!!!
%html
%title A blog about Wagyu
%body
%h1 A Blog about Wagyu
- content_block :content do
%p
No Posts Found
%hr/
.footer
Here's My Footer
Not a very dramatic template I know, but you can see that it’s different when you render it. The VegetablesBlog at http://localhost:5000/veggies and see that it’s still the same as it was before we modified the templates for the WagyuBlog.
You can change any and all of the templates as you see fit for each inherited mount individually. You can even add a common root to both of them (or the parent class) and tweak there to have it affect both of them.