Tom Clowers
Tom Clowers

Reputation: 141

Control Structure in Rails Partial

I'm building a Rails app up from the Sample App featured in Michael Hartl's book. In order to display error messages on user signup, I'm using a partial in the shared directory - app/views/shared/_error_messages.html.erb:

<%if @fact %>
  <% @data = @fact %>
<% elsif @user %>
  <% @data = @user %>
<% end %>

<% if @data.errors.any? %>
  <div id="error_explanation">
    <div class="alert alert-error">
      The form contains <%= pluralize(@data.errors.count, "error") %>.
    </div>
    <ul>
    <% @data.errors.full_messages.each do |msg| %>
      <li>* <%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>

Originally, this partial just started with something like:

<% if @user.errors.any? %>

However, since I've decided to re-use this partial to show errors on other pages, I'm having to use different objects (@user, @fact) depending on which page I'm using it on. This is easily solved by adding that IF statement at the top,

<%if @fact %>
  <% @data = @fact %>
<% elsif @user %>
  <% @data = @user %>
<% end %>

-but this feels icky. Is there a controller somewhere I should be putting this kind of logic for shared partials?

Upvotes: 1

Views: 115

Answers (3)

Akash
Akash

Reputation: 5221

Marek's answer is probably the best. However, here is an alternative which though not scalable, is closer to what you have done.

Just replace:

<%if @fact %>
  <% @data = @fact %>
<% elsif @user %>
  <% @data = @user %>
<% end %>

with:

<% @data = @fact||@user %>

Upvotes: 0

mecharaptors
mecharaptors

Reputation: 21

You could use render to point to the partial from your controllers for users and fact. Check out the API documentation on rendering partials.

Upvotes: -1

Marek Lipka
Marek Lipka

Reputation: 51151

You can pass local variables to partial instead:

<% if object.errors.any? %>
  <div id="error_explanation">
    <div class="alert alert-error">
      The form contains <%= pluralize(object.errors.count, "error") %>.
    </div>
    <ul>
    <% object.errors.full_messages.each do |msg| %>
      <li>* <%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>

And in your template, for example:

<%= render 'shared/error_messages', object: @user %>

Upvotes: 3

Related Questions