Pierre
Pierre

Reputation: 1114

Where to put code thats used on many views

Currently I have this piece of code in my _header.html.erb partial which is used by application.html.erb.

<% current_user.achievements.each do |achievement| %>
  <li><%= link_to achievement.header_string, polymorphic_path(achievement.achievementable) %></li>
<% end %>

current_user.achievements seems more appropriete to put in a controller instead? But im not sure where to put it, this is similar to the achievements in the header here on Stack Overflow. This code will be used in all views if the user is logged in.

Upvotes: 2

Views: 61

Answers (3)

Peter Sorowka
Peter Sorowka

Reputation: 1036

TL;DR leave it as it is

Actually your question could be answered in two ways:

  1. If you are referring to the view code (i.e. build the list), then this is what partials are meant for. And by placing it in the _header partial you do the right thing.

  2. If you are referring to the call of current_user.achievements and you feel that the view would be the wrong place for triggering a database call I would say: yes and no. This is the point where the strict MVC logic is a bit less strict. I would never clutter my controllers with filter methods or instance variables for such a case. To my mind it is perfectly fine to let the views decide which properties of objects and potentially which related objects the need to display. A controller involvement in that story could cover something like access control on a field level (by setting achievements to [] in not-auhorized case). I also think that your version is nice, readable and explicit code.

Upvotes: 1

Mandeep
Mandeep

Reputation: 9173

I don't see anything wrong using current_user.achievements in your views as it will call up current users achievements once and then rails caches that query result for you.

If you really want to put it somewhere then application controller is the place to be

def achievements
  @acheivements = current_user.achievements
end

then use before filter on whatever action you want it to set

before_filter :achievements, only: [:your_methods]

Upvotes: 1

ruby_newbie
ruby_newbie

Reputation: 3275

I would put it in the application controller with a helper method.

helper_method :achievements

def acheivements(current_user)
  current_user.achievements.each do |achievement| 
   <do stuff>
end

you can then call it from anywhere because all of your controllers inherit from application controller.

Upvotes: 1

Related Questions