RuHL (Ruby Hypertext Language) **gem available on gemcutter: http://gemcutter.org/gems/ruhl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: What? :: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RuHL parses HTML (using Nokogiri) and by using a data-ruhl attribute, makes the contents dynamic! Let's say you have the following HTML in a file called ('hello_world.ruhl')

And you have the following method available to self: def say_hello "Hello World" end If you call RuHL::Engine.new(File.read('hello_world.ruhl')).render(self) It will return:

Hello World

Notice that it removes the data-ruhl attribute. You can pass an options hash to RuHL: RuHL::Engine.new(File.read('hello_world.ruhl'), options).render(self) Right now, RuHL knows the following options: :layout => This is the file name of the layout :layout_source => If the framework (like Rails) has already read the file, pass the contents through so RuHL doesn't have to reread the file. If you don't pass :layout_source, RuHL must be able to find/read :layout :local_object => If you are rendering a show page for @person, pass the @person object into RuHL. RuHL will first try to call the methods against the local_object then try the scope. For example:
  • RuHL will first try @person.first_name. There are some special methods defined by RuHL (examples follow): _render_ - This is used in your layout and lets rule know where to inject the rendered sub content. _partial - Path to a partial file. RuHL must be able to find/read this file. _if - If the method returns true, processing will continue. If the method returns a value other than true, the inner_html of the tag will be set to that value. If the method returns false or nil, processing will halt and the tag will not be included on output. _unless - If the method returns true, processing will halt and the tag will not included on output. If the method returns false, processing will continue. _collection - RuHL expects the method reference to return an array of objects. RuHL will iteratate over the collection and render the contents of the tag agains the collection item. (example below) _use - The object returned is used within the scope of the tag. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Rails :: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In your config/environment.rb : config.gem 'ruhl', :lib => 'ruhl/rails' Your filenames should end in .ruhl ('show.html.ruhl') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Sinatra :: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ require 'ruhl/sinatra' You can then do: get '/' do ruhl(:index, :layout => path_to_layout) end ******************************************************************************* * * EXAMPLES * ******************************************************************************* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Replacing attribute values :: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ content: meta_description is telling the parser to replace attribute 'content' with results from meta_description method. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Don't use iterators in views :: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    John Doe john@doe.com
    The above will call the :user_list method and iterate over the results. For each result it will duplicate the tag and it's contents. For the above example this means: John Doe john@doe.com is duplicated for each user in user_list. If user_list return an array of User objects like: [ User.create(:name => 'Rupert Boy', :email => 'rupert@stonean.com'), User.create(:name => 'Kaylee Girl', :email => 'kaylee@stonean.com'), User.create(:name => 'Monty Man', :email => 'monty@stonean.com')]
    Rupert Boy rupert@stonean.com
    Kaylee Girl kaylee@stonean.com
    Monty Man monty@stonean.com
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Using a Layout :: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Layout: This is a title template
    Fragment:

    I am a templated headline

    Lorem ipsum dolor sit amet

    To use: RuHL::Engine.new(File.read(fragment), :layout => path_to_layout).render(self) Returns the expected result of parsed Layout w/ parsed Fragment. Note the use of the _render_ method. This is a 'special' method that RuHL uses to inject the results of the parsed fragment into the layout. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Using a Partial :: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Main: This is a title template

    My main content

    Text designers would put here to test their layout

    Sidebar:

    Real Sidebarlinks

    To use: RuHL::Engine.new(File.read(path_to_main)).render(self) Returns the expected result of parsed Main with sidebar div contents replaced with parsed sidebar partial contents. Note the use of the _partial key. This is a 'special' key that RuHL uses to inject the results of the parsed partial into the contents of the calling node. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Conditional display of block (_if):: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is a title template

    This is the header template

    First Name Last Name Email
    Andrew Stone andy@stonean.com
    if users? returns false then the div (including it's contents) are not shown on output. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Conditional display of tag (_if):: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is a title template

    This is the header template

    First Name Last Name Email
    Andrew Stone andy@stonean.com
    if email.nil? then the td is not shown. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Conditional display of tag (_unless):: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is a title template

    This is the header template

    First Name Last Name Email
    Andrew Stone andy@stonean.com

    No Users were found.

    if users? == false then the "No Users were found" message appears. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Scope object to tag block (_use):: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ My Account

    Editing

    First Name Last Name Email
    Andrew Stone andy@stonean.com
    The table row information will be replace with the current_user details. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: Notes :: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * No eval (I don't think eval is evil, it's just not the way this works) * The data-ruhl attribute is always removed from the output. * Since it's just HTML, syntax highlighting is built-in. For vim, just add this to your ~/.vimrc: au BufNewFile,BufRead *.ruhl set filetype=html ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: TODO :: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1) Test more scenarios