Combining show_for and stonewall

I'd been doing some thinking about simplifying the display of records in Rails applications and fortunately came across show_for.

show_for is a formtastic-like approach to displaying details about database records. It helps you DRY up your views and can even reflect on associations with code like this:

<% show_for @user do |u| %>
  <%= u.attribute :name %>
  <%= u.attribute :nickname, :in => :profile %>
  <%= u.attribute :confirmed? %>
  <%= u.attribute :created_at, :format => :short %>
  <%= u.attribute :last_sign_in_at, :if_blank => "User did not access yet",
                  :wrapper_html => { :id => "sign_in_timestamp" } %>

  <% u.attribute :photo do %>
    <%= image_tag(@user.photo_url) %>
  <% end %>

  <%= u.association :company %>
  <%= u.association :tags, :to_sentence => true %>
<% end %>

But since I'm working on an application which uses stonewall (which allows you to limit the display of a record's details), I needed the 2 of them to work together.

stonewall allows you to guard the display of your data from your models:

stonewall do |s|
  s.varies_on :aasm_state

  s.guard_attribute :secret_cultivation_details

  # ... role details here
end

It provides a allowed? method which you can use to ask an object if the current user is allowed to see the content.

So I quickly put together show_for_stonewall which will limit the display of certain fields if stonewall prevents it. It was as simple as using alias_method_chain to check that an attribute is not allowed

!allowed?(@object, current_user, attribute_name)

You can edit your show_for translation yaml and add a redacted key for the content to display if a field is not allowed for the current user.