Have you ever written the same template or helper twice? Do you have trouble sleeping at night because of code duplication? Then Fifty may right for you. It allows you to save keystrokes by leveraging:
- HAML as a markup language for the static part of your templates.
- Handlebars to render dynamic fields on the server or in the browser.
- Javascript to write helpers that run both client- and server-side.
Is it ready?
No. The proof of concept is there for you to see, but I need to work on this some more before I release it as a gem.
What does it do?
Hopefully this is self-explanatory:
1. Start with some model data
$data = {
posts: [
{ title: 'Hello, world!',
text: 'This is fu-man-chu!',
likes: 2,
comments: [
{ user: 'Louis',
text: 'Cool!' },
{ user: 'Justin',
text: 'What do you think?' }
] },
{ title: 'This is a post!',
text: 'With lots of love.',
likes: 1,
comments: [
{ user: 'Chris',
text: 'Nice!' }
] }
]
}
2. Include Fifty in our app.
require 'sinatra'
require 'fifty'
class MyApp < Sinatra::Base
helpers Fifty
# Share a copy of the data to the client.
# Made available as `window.client`
shared_data :client_data, $data.to_json
get '/posts?.format?' do |format|
if format == 'json'
$data.to_json
elsif format == 'html'
fifty :posts, $data
end
end
end
MyApp.run!
3. Define your views
@@ layout
%html
%head
%script{src: fifty_cdn(:handlebars)}
%script{src: fifty_cdn(:jquery)}
= fifty_partials
= fifty_scripts
%body
#posts
= yield
:javascript
// Reload from route /posts.json
$('#reload').click(function () {
$('#posts').getAndReplace('posts');
});
// Submit form and add post to feed.
$('#form').submit(function (event) {
event.preventDefault();
var data = $(this).serialize;
$('#posts').postAndAppend('post', data);
});
// Delete post and remove from feed.
$('.delete').click(function (e) {
$(this).postAndRemove('post/delete', {
id: $(this).closest('.post')
});
});
@@ posts
.container
.row
{{#each posts}}
{{> post}}
{{/each}}
%button#reload Reload
@@ post
.post{id: "{{id}}"}
%h3 {{title}}
%p {{text}}
%p
{{likes}}
{{t "like"}}
%hr
%p
{{#each comments}}
{{> comment}}
{{/each}}
%a.delete{href: '#'} Delete
@@ comment
.comment{id: "{{id}}"}
%b {{user}}:
%span {{text}}
@@ form
%form{method: 'post'}
Name:
%input#name{type: 'text'}
Message:
%textarea#message
Configuration Options
You can put these anywhere before you run your routes. For a Sinatra app, the canonical path is config/fifty.rb
.
Paths to Views and Locales
Set the path(s) to your views (shown is the default):
Fifty.views = ['./views/**/*.haml']
If using locales with I18n
, set the path to your files:
Fifty.locales = ['./config/locales/*.yml']
Shared Helpers and JSON data
# Share a copy of the data to the client.
#
# Made available as `window.client`
js_data :client_data, $data.to_json
# Define a shared helper function.
#
# Can be invoked within a HBS
# template in Ruby or Javascript.
hbs_helper :add, %t{
function (a, b) { return a + b; }
}