Ruby on Rails content_tag options hash - setting a boolean html attribute?
Asked Answered
A

2

8

Boolean attributes, as defined in the html 5 draft specification:

http://dev.w3.org/html5/spec/Overview.html#boolean-attributes

The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.

If the attribute is present, its value must either be the empty string or a value that is an ASCII case-insensitive match for the attribute's canonical name, with no leading or trailing whitespace.

My page is using the html5 DTD. I'm attempting to use the content_tag view helper in a helper of my own, but am having issues with passing boolean attributes to it.

Specifically this is my helper:

def itemscope(type, options = {}, &block)
  content_tag(
    :div, {
      :itemscope => true,
      :itemtype => data_definition_url(type)
    }.merge(options),
    true,
    &block
  )
end

def data_definition_url(type)
  "http://data-vocabulary.org/#{type}"
end

in my view, let's say I call it like this (I'm using haml):

= itemscope("Organization") do
  %h1 Here's some content

This is what I would want it to render:

<div itemscope itemtype='http://data-vocabulary.org/Organization'>
  <h1>Here's some content</h1>
</div>

But this is what I'm actually getting:

<div itemscope='true' itemtype='http://data-vocabulary.org/Organization'>
  <h1>Here's some content</h1>
</div>

Which is invalid markup according to the w3 specification. Legal values for boolean attributes are either the name of the attribute itself, or no value at all.

It's annoying because I can change the :itemscope => true to :checked => true and it will correctly render the attribute as checked='checked' in the attribute list of the div element.

I'd prefer it to render the minimized version of just itemscope...but I'm not sure how to do that using the content_tag options. I could very easily send :itemscope => 'itemscope' but it's difficult to say if that will be correctly interpreted by google since all of their examples and specifications show the minimized versions. See here: http://www.google.com/support/webmasters/bin/answer.py?answer=146861 to see what these properties are and why I'm using them (Microdata format)

Anyone know how I can effectively get any attribute sent a true or false (ruby boolean) value in content_tag to render without any value instead of trying to stringify the boolean value? Thanks :)

Ageless answered 10/3, 2011 at 0:37 Comment(2)
Sounds like a great idea for a patch :) Though the patch would be for HAML in this case, not Rails.Arad
No, the problem lies with Rails' content_tag helper and related functions, not HAML.Jolty
J
3

Put the following content into an initializer called config/initializers/boolean_attributes.rb

# add any other boolean attributes to the %w() below to make them work like checked.
BOOLEAN_ATTRIBUTES = %w(itemscope).to_set
BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|attribute| attribute.to_sym })
ActionView::Helpers::TagHelper::BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES)

Et Voila! Restart Rails and you should be good to go. I don't know how to make the thing just add a blank attribute, just how to make it work like checked, disabled, readonly, etc...

Jolty answered 10/3, 2011 at 2:20 Comment(3)
I'll give this a shot - but it would be nice if it were smart enough to see the value 'true' and just know what you wanted =pAgeless
indeed, we get so used to "rails magic" when it doesn't do what we expect its disappointing. but I think it does this for a reason, since setting custom attributes (think "data-is_active") to true we would expect in javascript, for instance, to see a true or false value on that attribute rather than "data-is_active" == "data-is_active"Jolty
I agree with @nzifnab, it should be smart enough to treat it as a compliant boolean HTML attribute if you provide a boolean Ruby value (true or false). If you want the literal string 'true' or 'false', then supply the Ruby values 'true' or 'false'!Thorlay
S
3

the hacky but easy way: content_tag('div itemscope', ...)

Stadler answered 15/3, 2016 at 21:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.