Fork me on GitHub

Use Zena in own Rails-App

An article by Gaspard Bucher

Sometimes you may want to add Zena on an existing Rails application. This can work but there are currently a number of limitations due to the way login (visitor) is managed in Zena.

pre-requisites

login

You need to use Zena’s login (or at least figure out how it works and mimic it) in order to have:

  • the visitor in the current Thread
  • a visitor that is a User (so that you can ask if it’s an admin, anonymous, get the groups, remember caching context, etc).

model names

You also need to make sure you do not have models that clash with Zena’s (list of models). This until we move the models into “Zena” namespace.

rails version

Your rails version should match the version used by Zena (switch tags in github to see which version corresponds to the release you are using).

utc

You should use config.time_zone = 'UTC' inside your environment file or you might get unexpected results.

setup

You can simply run the “zena” command on your rails application (make a backup first!). Or configure things step by step:

config.gem ‘zena’

In the environment.rb file, you need to add a line such as:

config.gem 'zena', :version => '1.0'

rake tasks

You need to add a file with the following content in your “lib/tasks” folder:

# sync zena tasks to gem version
env = File.read(File.join(File.dirname(__FILE__), '..', '..', 'config', 'environment.rb'))
if env =~ /^\s*(#|).*config.gem.*zena.*version.*'(.*?)'/
  if $1 == '#'
    # commented out
  else
    gem 'zena', "= #{$2}"
  end
end
require 'zena'
require 'tasks/zena'

routes

Add zena roots with “map.zen_routes” inside the routing block:

ActionController::Routing::Routes.draw do |map|
  map.zen_routes
end

view caching

You should disable view caching (keep file stat live) so that you can use Zafu. Add the following line to all environments (test, development, production):

config.action_view.cache_template_loading = false

ApplicationController

Load Zena’s helpers, zafu compiler and such with:

class ApplicationController < ActionController::Base
  include Zena::App
end

bridge

Now that you managed to include Zena inside your application, you need some ways to show the content from your application inside Zafu templates.

To do this you have to either write subclasses of Zena models and declare safe methods. For example if you use Zena for an inline store, your users will probably have some Cart object. You should therefore create a sub-class of User:

class Buyer < User
  safe_method :cart => 'Cart'
end

And then your cart method should include RubyLess and declare safe methods:

class Cart < ActiveRecord::Base
  include RubyLess

  safe_method :items => {:class => ['CartItem'], :method => 'cart_items'}
end

And now, you do the same for CartItem & Product:

class Cart < ActiveRecord::Base
  include RubyLess

  safe_method :count => Number
  safe_method :price => Number
  safe_context :product => 'Product'
end

And the Product should be some sub-class of Zena’s Node (or a sub-class such as Page) so that you can easily edit, add pictures, create related products, categories, etc:

class Product < Page
  properties do |p|
    p.string :brand, :index => true
  end
end

Then you can write zafu such as:

<r:visitor do='cart'>
  <h3 do='t'>Your Cart</h3>
  <ul do='items'>
    <li do='each'>
      <span class='product' do='product'>
        <b do='title'/> (<span class='brand' do='brand'/>)
      </span>
      <span class='count' do='count'/>
      <span class='price' do='price' format='%.2 USD'/>
    </li>
  </ul>
</r:visitor>

Documentation: