I am experimenting with implementing BEM helpers in my Rails 4 app to help me write views more pleasantly.
Let's assume we have the following Haml view:
= block :user_bar, unregistered: current_user.unregistered? do |b|
- if current_user.unregistered?
= b.element :inner do
You are not registered.
Assuming the block
and the fictional class BEMBlockBuilder
with a method #element
(of which an instance is passed as b
) are defined, and assuming that current_user.unregistered?
is true
, we should get the following HTML output:
<div class="user-bar user-bar--unregistered">
<div class="user-bar__inner">
You are not registered.
</div>
</div>
This technique should make it possible to set up blocks, elements and apply modifiers to them without having to repeat the block's name every time, and it would make it possible able to apply modifiers simply based on the value bound to them being truthy.
The technique itself is somewhat similar to what happens when you use the form_for
helper, in that it passes an instance of FormBuilder
to the block.
The primary difference between this technique and the form_for
helper is that you may end up using a multitude of nested blocks to render a view, of which the output might not be known.
Would this technique affect Rails's (or HAML's) ability to perform caching in a negative way, or would it damage rendering performance in general?
No, the implementation you are suggesting does not negatively impact caching - This includes page caching, action caching as well as Russian doll caching.
While the cases for page caching or action caching are fairly obvious, the reason Russian doll caching is also unaffected by custom view builders is because if the
cache_key
of model does not change - the block passed to thecache
helper does not get re-evaluated irrespective of the view builder that is getting invoked underneath.The above assumes that you avoid implicit state in your builder. Alex has already highlighted the importance of predictability in the comments.
Apart from that the only key issue is that streaming of templates will be tricky to handle. If that is not relevant to your use case, then you are good to go. In particular, if you are using HAML then you can not use streaming anyways. You may however consider exploring the thread for some interesting ideas on handling streaming templates.
If you want to avoid this issue, you may consider using small helper functions just to generate the class names according to BEM. Then you can use something like:
This is obviously more verbose, but also easily allows you to handle cases where multiple blocks are applied to same DOM element, which is valid in BEM.
Finally, here are some key takeaways from an extremely well written article by Justin Weiss on view rendering performance assessment: