Search code examples
ruby-on-railsindentationslim-lang

Indentation oops with "if condition then <a> else <span>" in slim


I have to render either an or a depending on a condition, however, slim's indentation and "no explicit end allowed" gets in the way.

In this simplified code, I'd like to wrap a product with three DIVs in either an A or a SPAN depending on whether the product is available or not.


- if available?
  a href=...
- else
  span class="unavailable"
.currency = @product.currency
.price = @product.price
.description = @product.description

The above obviously won't work since the product is not rendered within the A or SPAN but next to it.


- if available?
  a href=...
- else
  span class="unavailable"
  .currency = @product.currency
  .price = @product.price
  .description = @product.description

This case is even worse, because slim treats the product as part of the "else" case and renders the product next to the SPAN and not at all for the A.


- if available?
  a href=...
- else
  span class="unavailable"
    .currency = @product.currency
    .price = @product.price
    .description = @product.description

Here everything is fine for the SPAN but the A remains empty because the product is treated as part of the "else" case.


- if available?
  a href=...
- else
  span class="unavailable"
- end
  .currency = @product.currency
  .price = @product.price
  .description = @product.description

Now, this could be correct, but slim doesn't allow explicit "end" and therefore raises an exception.

Any idea how I can get this to work?

PS: Maybe slim should allow explicit "end" for edge cases like this one.


Solution

  • This is what I could come up with as a workaround:

    Using capturing to local variables you save your children in a local variable:

    = capture_to_local children=:children
      .currency = @product.currency
      .price = @product.price
      .description = @product.description
    

    And now you can run

    - if available?
      a href=...
        = children
    - else
      span class="unavailable"
        = children
    

    I don't have slim set up, just tried it with haml, but it should work just the same :)