Beast demo
Neat list of different features is good, but if you really want to know how does Malline differ from ERB, you have to see real life example.
Beast is a small, light-weight forum in Rails with a scary name. I use it as an example, and rewrite some of it's ERB templates to Malline. Now when the ERB templates are from well-known software, and are not written by me, the compare may be considered to be quite fair and truthful.
On this page
- Introduction
- new.rhtml » new.mn
- _contact_info.rhtml » _contact_info.mn
- edit.rhtml » edit.mn
- _form.rhtml » _form.mn
- index.rhtml » index.mn
- _settings.rhtml » _settings.mn
- show.rhtml » show.mn
- The end
Introduction
Examples are from the latest (at 2007-10-07) stable Beast, version 1.0. I have tested (quickly) that the outputs are identical from my Malline templates and original ERB templates (identical as in "It seems to look the same in Firefox" ;D). I converted all templates from app/views/user.
Just remember, I tried to keep the structure exactly the same, so it's easier to make the comparison. That is why that does also mean that these examples are not the best way to do things.
new.rhtml » new.mn
Let's start with the simplest file. As you can see, Beast uses Gibberish localization library, so that forces every string to be form "foo"[:bar].
form_for has it's own magical ERB-output features, so it's not a normal helper method and thus not prefixed with "_". Malline automatically emulates ERB and captures output correctly.
_render and _submit_tag both are just normal helper methods, so they are outputted by using the prefix. Nothing extraordinary exciting here.
1 2 3 4 5 6 7 8 |
<h1><%= 'Signup'[] %></h1> <%= error_messages_for :user %> <% form_for :user, :url => users_path do |f| -%> <%= render :partial => "form", :object => f %> <p><%= submit_tag 'Sign up!'[:signup_title] %></p> <% end -%> |
1 2 3 4 5 6 7 8 |
h1 'Signup'[] _error_messages_for :user form_for :user, :url => users_path do |f| _render :partial => "form", :object => f p { _submit_tag 'Sign up!'[:signup_title] } end |
_contact_info.rhtml » _contact_info.mn
This file is actually quite clean in ERB, and it's conversion is straightforward.
settings.foo-methods are rendered automatically. See configuration options for more info.
This is not the only file that uses this "p { label; br; settings.foo }" -pattern. Custom helper method for that could shorten and clean up template files, but since I'm trying to make everything equally to original design, I just get along without it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<h3><%= 'User Profile'[] %></h3> <p> <label for="display_name"><%= 'Display Name'[:display_name_title] %></label><br /> <%= settings.text_field :display_name %> </p> <p> <label for="user_identity_url"><%= 'Identity Url'[:identity_url_title] %></label><br /> <p class="help"><%= 'Enter your OpenID Identity Url if you know it'[:open_id_field ]%>.</p> <%= settings.text_field :identity_url %> </p> <p> <label for="user_website"><%= 'Website'[:website_title] %></label><br /> <%= settings.text_field :website %> <span class="entryhelp"> (<%= 'without http://'[:without_http] %>) </span> </p> <p> <label for="user_bio"><%= 'Bio'[:bio_title] %></label><br /> <%= settings.text_area :bio, :rows => 10, :style => "width:99%" %> </p> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
h3 'User Profile'[] p do label 'Display Name'[:display_name_title], :for => 'display_name'; br settings.text_field :display_name end p do label 'Identity Url'[:identity_url_title], :for => 'user_identity_url'; br p.help 'Enter your OpenID Identity Url if you know it.'[:open_id_field] settings.text_field :identity_url end p do label 'Website'[:website_title], :for => 'user_website'; br settings.text_field :website span.entryhelp '('+'without http://'[:without_http]+')' end p do label 'Bio'[:bio_title], :for => 'user_bio'; br settings.text_area :bio, :rows => 10, :style => 'width:99%' end |
edit.rhtml » edit.mn
Sorry about long lines in .rhtml, but I didn't want to modify the original files. This file is so much cleaner in Malline, because most of the ERB file is also just Ruby.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<% content_for :right do %> <h5><%= 'Avatars'[:avatars_title] %></h5> <p><%= 'To have your very own avatar displayed on this forum visit {gravatar} and sign up for a free gravatar.'[:gravatar_notice, %(<a href="http://www.gravatar.com/">gravatar.com</a>)] %></p> <% end %> <h1><%= 'Settings'[:settings_title] %></h1> <p class="subtitle"><%= 'for {user}'[:for_user, @user.display_name] %> <% if @user.login!=@user.display_name %> (<%= @user.login %>) <% end %> </p> <%= error_messages_for :user %> <% form_for :user, :url => user_path(@user), :html => { :method => :put } do |f| -%> <%= render :partial => "settings", :object => f %> <p><%= submit_tag 'Change e-mail or password'[:change_email_or_password], :or => link_to( "cancel"[], "/") %></p> <% end -%> <br /> <% form_for :user, :url => user_path(@user), :html => { :method => :put } do |f| -%> <%= render :partial => "contact_info", :locals => { :settings => f } %> <p><%= submit_tag 'Update Profile'[], :or => link_to( "cancel"[], "/") %></p> <% end -%> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
content_for :right do h5 'Avatars'[:avatars_title] p 'To have your very own avatar displayed on this forum visit {gravatar} and sign up for a free gravatar.'[:gravatar_notice, %(<a href="http://www.gravatar.com/">gravatar.com</a>)] end h1 'Settings'[:settings_title] p.subtitle 'for {user}'[:for_user, @user.display_name] do _" (#{@user.login})" if @user.login != @user.display_name end _error_messages_for :user form_for :user, :url => user_path(@user), :html => { :method => :put } do |f| _render :partial => "settings", :object => f p { _submit_tag 'Change e-mail or password'[:change_email_or_password], :or => link_to( "cancel"[], "/") } end br form_for :user, :url => user_path(@user), :html => { :method => :put } do |f| _render :partial => "contact_info", :locals => { :settings => f } p { _submit_tag 'Update Profile'[], :or => link_to( "cancel"[], "/") } end |
_form.rhtml » _form.mn
This file is similar to _contact_info.mn, as it's conversion is very simple.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<p class="help"><%= 'Logins should start with least 2 characters and may consist of letters, numbers, or the underscore.'[:login_field] %></p> <p> <label for="user_login"><%= 'Login'[:login_title] %></label><br /> <%= form.text_field :login, :onkeypress => 'LoginForm.checkLogin(this)' %> </p> <p> <label for="user_email"><%= 'Email'[:email_title] %></label><br /> <%= form.text_field :email %> </p> <p> <p class="help"> <%= 'Enter your OpenID Identity Url if you know it. If your Identity Url supports the {sreg} extension, you can {login_link} and create your account automatically'[:open_id_field_extended, %(<acronym title="Simple Registration">sreg</acronym>), link_to('login'[], login_path)] %> </p> <label for="user_identity_url"><%= 'Identity Url'[:identity_url_title] %></label><br /> <%= form.text_field :identity_url %> </p> <p> <label for="display_name"><%= 'Display Name (optional)'[:display_name_title] %></label><br /> <%= form.text_field :display_name %> </p> <div id="password_fields"> <label for="user_password"><%= 'Password'[:password_title] %></label><br /> <p class="help"><%= 'Enter your desired password twice. It must be at least 5 characters.'[:password_field] %></span></p> <%= form.password_field :password %> <span class="entryhelp">(<%= 'once'[] %>)</span><br /> <%= form.password_field :password_confirmation %> <span class="entryhelp">(<%= 'and then again'[] %>)</span> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
p.help 'Logins should start with least 2 characters and may consist of letters, numbers, or the underscore.'[:login_field] p do label 'Login'[:login_title], :for => 'user_login'; br form.text_field :login, :onkeypress => 'LoginForm.checkLogin(this)' end p do label 'Email'[:email_title], :for => 'user_email'; br form.text_field :email end p do p.help 'Enter your OpenID Identity Url if you know it. If your Identity Url supports the {sreg} extension, you can {login_link} and create your account automatically'[:open_id_field_extended, %(<acronym title="Simple Registration">sreg</acronym>), link_to('login'[], login_path)] label 'Identity Url'[:identity_url_title], :for => "user_identity_url"; br form.text_field :identity_url end p do label 'Display Name (optional)'[:display_name_title], :for => 'display_name'; br form.text_field :display_name end div.password_fields! do label 'Password'[:password_title], :for => 'user_password'; br p.help 'Enter your desired password twice. It must be at least 5 characters.'[:password_field] form.password_field :password span.entryhelp ' (' + 'once'[] + ')'; br form.password_field :password_confirmation span.entryhelp ' (' + 'and then again'[] + ')'; br end |
index.rhtml » index.mn
As the ERB files are getting longer, they also become more and more messy. Malline version of index is much cleaner and easier to maintain.
On lines 14 to 18 in index.mn there is need for :whitespace -modifier, that adds a space between each element. We don't want space before commas, so they are concatted manually.
On lines 22, 34, 48 and 52 we can use Rubys statement modifiers to conditionally render a tag. That eliminates need for additional "if end" -block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
<% content_for :right do %> <h5><%= 'Find a User'[] %></h5> <% form_tag users_path, :method => 'get' do -%> <p> <label><%= 'Display name or login'[] %></label> <%= text_field_tag :q, params[:q] %> <%= submit_tag "Search"[:search_title] %></p> <% end -%> <% end -%> <h1 style="margin-top:0;"><%= 'Users'[:users_title] %></h1> <p class="subtitle"> <%= number_with_delimiter(@user_count) %> <%= 'users'[] %>, <%= @active %> <%= 'active'[] %>, <%= @user_count-@active %> <%= 'lurking'[] %> </p> <% if @user_pages.page_count > 1 -%> <p class="pages"><%= 'Pages'[:pages_title] %>: <strong><%= pagination_links @user_pages, :window_size => 10 %></strong></p> <% end -%> <table border="0" cellspacing="0" cellpadding="0" class="wide forums"> <tr> <th class="la" width="88%"><%= 'Name / Login'[:name_or_login] %></th> <th><%= 'Website'[:website_title] %></th> <th width="1%"><%= 'Posts'[:posts_title] %></th> </tr> <% @users.each do |user|-%> <tr> <td><%= link_to h(user.display_name), user_path(user), :class => (user.admin? ?< |
