Every show action in my app has the same template for every model (it is an Admin-portal type interface). I have a view show.html.erb that all of these models inherit.
The controllers all use InheritedResources, so I have access to some helper variables such as resource, which I use to display the attributes for the model being shown through resource.attributes in my parent view.
What I would like to be able to do is whitelist which attributes are being shown in each model. I have thought of two ways to do this… the first is to define some method in a class my model’s inherit from, say it is called attr_visible and define each attribute in the model. The reason I don’t like this approach is that it puts too much of the view logic in the models. I would rather provide my views with the model, and let the view determine what is displayed.
The second approach is what this question is about. I want to have a file /app/views/users/show.html.erb, and set which attributes for a User I would like to be shown, say something like:
@attributes = [:name, :email, :etc]
And then pass them to the parent view which I described in the beginning of this question. That view would then be able to loop through @attributes and display the attributes necessary.
Is it possible to use a “super“-type method from views? Everything I have read about view inheritance suggests the view is loaded based on where it is located in the directory structure, and then after that you’re out of luck.
edit: I have sort of done what I want. I defined a partial _show.html.erb in the /app/views/users directory that looks like:
<% @attributes = ['name', ...] %>
And then in the parent view I call <%= render "show" %> before looping through @attributes. This works, but feels clunky since I am not actually rendering anything when I call render. Is there a better way?
You can use a presenter for this. Adding “view” logic to a model is better done through this type of object. Take a look at draper.
Once the resource is decorated, you can just call
visible_attributesor whatever. Of course, you would need to implement that method for each resource.Views inheritance works when looking for a view, not when rendering it. Take a look at the original plugin implementation.
Other way would be to make the
showparent view to callrenderonresourceand create several partials for the classes.For a better understanding on Rails Views, I recommend The Rails View: Create a Beautiful and Maintainable User Experience