= sinatra_more == Introduction Note: This library is still experimental and may not be ready for production just yet. That being said, work is being put into reaching solid test coverage and the gem is being actively used on a number of sinatra projects. This notice will be removed once sufficient testing has been done. This will be a plugin which expands sinatra's capabilities in a variety of ways. Note that as much as possible, all helpers have been created to work with haml, erb, and erubis. This gem is intended to be template-agnostic in providing helpers as much as possible. Let me expand briefly on what I want to accomplish with this gem. I love sinatra but if I want to use it for any non-trivial application I very quickly miss a lot of the extra tools provided by rails. Now the obvious question is "Why not just use rails then?" Well, in many cases that might be the right decision. Still, at least until version 3 comes along, Rails is quite a large framework with a 'take it or leave it' attitude. Personally, I have come to love the spirit of sinatra which acts as a thin wrapper on top of rack often allowing middleware to do most of the work and pulling in additional complexity only as required. My goal with this extension is to match the spirit of Sinatra and at the same time create a standard library of tools, helpers and components that will make Sinatra suitable for more complex applications. Here is a small list of what sinatra_more contains: * Generic view and tag helpers (tag, content_tag, input_tag, ...) * Asset helpers (link_to, image_tag, javascript_include_tag, ...) * Form helpers and builder support (form_tag, form_for, field_set_tag, text_field, ...) * Plug and play setup for the excellent Warden authentication system * Code generators for creating a new sinatra application Keep in mind, the user will be able to pull in these components seperately and leave out those that are not required. Please help me brainstorm and fork the project if you have any ideas to contribute. == Installation This gem has very few runtime dependencies. The 'sinatra' gem needs to be installed and also 'activesupport'. If you want to use the WardenPlugin component, then the 'warden' gem is also required. To install sinatra_more, simply grab the latest version from gemcutter: $ sudo gem install sinatra_more --source http://gemcutter.org Now you are ready to use this gem in your sinatra project. == Usage This extension can be easily registered into any existing sinatra application. You can require different components based on which pieces are useful for your particular application. # app.rb require 'sinatra/base' require 'sinatra_more' class Application < Sinatra::Base register SinatraMore::MarkupPlugin register SinatraMore::RenderPlugin register SinatraMore::WardenPlugin end This will then allow you to use the components that have been registered. A breakdown of components is below: === MarkupPlugin This component provides a great deal of view helpers related to html markup generation. There are helpers for generating tags, forms, links, images, and more. Most of the basic methods should be very familiar to anyone who has used rails view helpers. ==== Output Helpers * capture_html(*args, &block) * Captures the html from a block of template code for erb or haml * capture_html(&block) => "...html..." * concat_content(text="") * Outputs the given text to the templates buffer directly in erb or haml * concat_content("This will be output to the template buffer in erb or haml") ==== Tag Helpers * tag(name, options={}) * Creates an html tag with the given name and options * tag(:br, :style => 'clear:both') =>
* tag(:p, :content => "demo", :class => 'large') =>

demo

* content_tag(name, content, options={}) * Creates an html tag with given name, content and options * content_tag(:p, "demo", :class => 'light') =>

demo

* content_tag(:p, :class => 'dark') { ...content... } =>

...content...

* input_tag(type, options = {}) * Creates an html input field with given type and options * input_tag :text, :class => "demo" * input_tag :password, :value => "secret", :class => "demo" ==== Asset Helpers * flash_tag(kind, options={}) * Creates a div to display the flash of given type if it exists * flash_tag(:notice, :class => 'flash', :id => 'flash-notice') * link_to(*args, &block) * Creates a link element with given name, url and options * link_to 'click me', '/dashboard', :class => 'linky' * link_to('/dashboard', :class => 'blocky') { ...content... } * image_tag(url, options={}) * Creates an image element with given url and options * image_tag('icons/avatar.png') * stylesheet_link_tag(*sources) * Returns a stylesheet link tag for the sources specified as arguments * stylesheet_link_tag 'style', 'application', 'layout' * javascript_include_tag(*sources) * Returns an html script tag for each of the sources provided. * javascript_include_tag 'application', 'special' ==== Form Helpers * form_tag(url, options={}, &block) * Constructs a form without object based on options * form_tag('/register', :class => 'example') { ... } * field_set_tag(*args, &block) * Constructs a field_set to group fields with given options * field_set_tag(:class => 'office-set') { } * field_set_tag("Office", :class => 'office-set') { } * error_messages_for(record, options={}) * Constructs list html for the errors for a given object * error_messages_for @user * label_tag(name, options={}, &block) * Constructs a label tag from the given options * label_tag :username, :class => 'long-label' * label_tag(:username, :class => 'blocked-label') { ... } * text_field_tag(name, options={}) * Constructs a text field input from the given options * text_field_tag :username, :class => 'long' * text_area_tag(name, options={}) * Constructs a text area input from the given options * text_area_tag :username, :class => 'long' * password_field_tag(name, options={}) * Constructs a password field input from the given options * password_field_tag :password, :class => 'long' * file_field_tag(name, options={}) * Constructs a file field input from the given options * file_field_tag :photo, :class => 'long' * submit_tag(caption, options={}) * Constructs a submit button from the given options * submit_tag "Create", :class => 'success' A form_tag might look like: - form_tag '/login', :class => 'login-form' do = flash_tag(:notice) - field_set_tag do %p = label_tag :username, :class => 'first' = text_field_tag :username, :value => params[:username] %p = label_tag :password, :class => 'first' = password_field_tag :password, :value => params[:password] - field_set_tag(:class => 'buttons') do = submit_tag "Login" ==== FormBuilders * form_for(object, url, settings={}, &block) * Constructs a form using given or default form_builder * form_for(@user, '/register', :id => 'register') { |f| ...field-elements... } The following are fields provided by AbstractFormBuilder that can be used within a form_for: * error_messages(options={}) * Displays list html for the errors on form object * f.errors_messages * label(field, options={}) * f.label :name, :class => 'long' * text_field(field, options={}) * f.text_field :username, :class => 'long' * text_area(field, options={}) * f.text_area :summary, :class => 'long' * password_field(field, options={}) * f.password_field :secret, :class => 'long' * file_field(field, options={}) * f.file_field :photo, :class => 'long' * submit(caption, options={}) * f.submit "Update", :class => 'long' A form_for using these basic fields might look like: - form_for @user, '/register', :id => 'register' do |f| = f.error_messages %p = f.label :username, :caption => "Nickname" = f.text_field :username %p = f.label :email = f.text_field :email %p = f.label :password = f.password_field :password %p = f.submit "Create", :class => 'button' There is also a StandardFormBuilder which builds on the abstract fields that can be used within a form_for: * text_field_block(field, options={}, label_options={}) * text_field_block(:nickname, :class => 'big', :caption => "Username") * text_area_block(field, options={}, label_options={}) * text_area_block(:about, :class => 'big') * password_field_block(field, options={}, label_options={}) * password_field_block(:code, :class => 'big') * file_field_block(field, options={}, label_options={}) * file_field_block(:photo, :class => 'big') * submit_block(caption, options={}) * submit_block(:username, :class => 'big') A form_for using these standard fields might look like: - form_for @user, '/register', :id => 'register' do |f| = f.error_messages = f.text_field_block :name, :caption => "Full name" = f.text_field_block :email = f.password_field_block :password = f.submit_block "Create", :class => 'button' and would generate this html:

...omitted...

==== Format Helpers * relative_time_ago(date) * Returns relative time in words referencing the given date * relative_time_ago(2.days.ago) => "2 days ago" * escape_javascript(html_content) * Escapes html to allow passing information to javascript. Used for passing data inside an ajax .js.erb template * escape_javascript("

Hey

") === RenderPlugin This component provides a number of rendering helpers for sinatra, making the process of displaying templates far smoother. This plugin also has support for useful additions such as partials (with support for :collection) into the templating system. * erb_template(template_path, options={}) * Renders a erb template based on the given path * erb_template 'users/new' * haml_template(template_path, options={}) * Renders a haml template based on the given path * haml_template 'users/new' * render_template(template_path, options={}) * Renders the first detected template based on the given path * render_template 'users/new' * render_template 'users/index', :template_engine => 'haml' * partial(template, *args) * Renders the html related to the partial template for object or collection * partial 'photo/_item', :object => @photo, :locals => { :foo => 'bar' } * partial 'photo/_item', :collection => @photos === WardenPlugin This component provides out-of-the-box support for Warden authentication. With this plugin registered, warden will be automatically required, configured and helpers will be provided to make interacting with warden dead simple. * current_user * Returns the current authenticated user * authenticate_user! * Login the user through the default warden strategies * logout_user! * Signs out the user from the session * logged_in? * Returns true if the user has been authenticated * authenticated?(&block) * If a block is given, only yields the content if the user is authenticated * authenticated? { puts "I am authenticated!" } * must_be_authorized!(failure_path=nil) * Forces a user to return to a fail path unless they are authorized * Used to require a user be authenticated before routing to an action * must_be_authorized!('/login') == Acknowledgements * Thanks to keldredd for the sinatra_helpers code that helped me to create erb capture and concat methods. * Thanks to sbfaulkner for the sinatra-helpers code that I looked while starting this library. == Contributors * Nathan Esquenazi - Project creator and code maintainer * Arthur Chiu - Forming the idea and various code contributions == Known Issues * Tag helper methods that accept blocks work unreliably in ERB. == Note on Patches/Pull Requests * Fork the project. * Make your feature addition or bug fix. * Add tests for it. This is important so I don't break it in a future version unintentionally. * Commit, do not mess with rakefile, version, or history. * Send me a pull request. Bonus points for topic branches. == Copyright Copyright (c) 2009 Nathan Esquenazi. See LICENSE for details.