Module: Ezamar::Morpher

Defined in:
lib/ezamar/morpher.rb

Constant Summary collapse

MORPHS =

Use this trait to define your custom morphs.

{
  'if'     => '<?r %morph %expression ?>%content<?r end ?>',
  'unless' => '<?r %morph %expression ?>%content<?r end ?>',
  'for'    => '<?r %morph %expression ?>%content<?r end ?>',
  'each'   => '<?r %expression.%morph do |_e| ?>%content<?r end ?>',
  'times'  => '<?r %expression.%morph do |_t| ?>%content<?r end ?>',
}

Class Method Summary collapse

Class Method Details

.transform(template) ⇒ Object

Since the functionality is best explained by examples, here they come.

Example:

if:

<div if="@name">#@name</div>

morphs to:

<?r if @name ?>
  <div>#@name</div>
<?r end ?>

unless:

<div unless="@name">No Name</div>

morphs to:

<?r unless @name ?>
  <div>No Name</div>
<?r end ?>

for:

<div for="name in @names">#{name}</div>

morphs to:

<?r for name in @names ?>
  <div>#{name}</div>
<?r end ?>

times:

<div times="3">#{_t}<div>

morphs to:

<?r 3.times do |_t| ?>
  <div>#{_t}</div>
<?r end ?>

each:

<div each="[1,2,3]">#{_e}</div>

morphs to:

<?r [1,2,3].each do |_e| ?>
  <div>#{_e}</div>
<?r end ?>

The latter two examples show you also one standard introduced by a limitation of the replacement-system.

When you yield a value, please name it by the first character(s) of the morphs name, with an underscore prefixed.

for each an _e, for times a _t.

This is by far not the best way to handle it and might lead to problems due to the lack of proper scoping in ruby (if you define an _e or _t before the block it will be overwritten).

So please be careful, I tried to come up with something that is both easy to write and doesn’t look outright awful while keeping an easy to remember mnemonic.

TODO:

- Add pure Ruby implementation as a fall-back.


113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/ezamar/morpher.rb', line 113

def self.transform(template)
  template = template.to_s
  hp = Hpricot(template)

  MORPHS.each do |morph, replacement|
    hp.search("[@#{morph}]") do |elem|
      expr = elem[morph]

      elem.remove_attribute(morph)

      repl = replacement.
        sub('%morph', morph).
        sub('%expression', expr).
        sub('%content', elem.to_html)

      elem.swap(repl)
    end
  end

  hp.to_html
end