Search code examples
rubyif-statementhamlmiddlemantext-database

HAML If defined? statement evaluating whether entry exists in Middleman data file


I have a Middleman data file data/testimonials.yaml:

tom:
  short: Tom short
  alt: Tom alt (this should be shown)
  name: Thomas

jeff:
  short: Jeff short
  alt: Jeff alt (this should be shown)
  name: Jeffrey

joel:
  short: Joel short (he doesn't have alt)
  name: Joel

It can have either default "short" text or an alternative text. For some testimonials, I want to use alternative text for some pages, while using "short" text for others.

In my test.haml I am trying to write HAML statement that checks whether alternative text exists. If it does, it should be inserted; if it doesn't, the standard text should be used instead.

Following example shows that data.testimonials[person].alt properly refers to information from data, because it can be inserted manually. However, when I use the same variable in if defined? statement, it never returns true.

Not-working 'if' way, because 'if defined?' never evaluates to true:
- ['tom','jeff','joel'].each do |person|
    %blockquote
        - if defined? data.testimonials[person].alt
            = data.testimonials[person].alt
        - else
            = data.testimonials[person].short

Manual way (code above should return exactly this):
- ['tom','jeff'].each do |person|
    %blockquote
        = data.testimonials[person].alt

- ['joel'].each do |person|
    %blockquote
        = data.testimonials[person].short

The result is this:

What am I doing wrong? Is there any way to use a conditional statement that checks whether data exists?


Solution

  • defined? does not really do what you want. You can just just leave it away, the if will just evaluate to false because the value will be nil for alt.

    So just put

    - ['tom','jeff','joel'].each do |person|
        %blockquote
            - if data.testimonials[person].alt
                = data.testimonials[person].alt
            - else
                = data.testimonials[person].short
    

    Or you could actually write it much shorter:

    - ['tom','jeff','joel'].each do |person|
        %blockquote
            = data.testimonials[person].alt || data.testimonials[person].short
    

    I don't really know for sure, why defined? does not work, but generally you don't need the method to check for it, because undefined values will just give you a nil in middleman.