Firstly, let me say that your approach is not that wrong imho. Introducing an extra method which is just an alias for Page.all
is not really needed, or not really an improvement.
But there are definitely better approaches.
I would fix this as follows: in ApplicationController
I would add the method
def get_all_pages
@pages ||= get_all_pages
end
This will make sure that any controller knows that method.
Then, if you are sure, you need it on every page, you can just a before_filter
in your ApplicationController
, but generally, I prefer to write it in the controller itself.
E.g.
class IdeasController < ApplicationController
before_action :get_all_pages
... the rest of your controller ...
end
Also, I would extract your list of pages into a partial, store in under app/views/shared/_pages_list.html.erb
or app/views/pages/_pages_list.html.erb
and then in your application.html.erb
just call to render the partial instead.
The method we called sets the instance variable @pages
, it will be available in the view, so your partial would like:
<ul>
<% @pages.each do |page| %>
<li><%= link_to page.name, page_path(page) %></li>
<% end %>
</ul>
Lastly, for completeness, let me answer how you can make a controller-method available in the view. In a controller write
def get_pages
# ..do something
end
helper_method :get_pages
This will make the method get_pages
available in the view, but only for a controller that was responsible for loading/rendering that view. So if you want it for all views, define this in ApplicationController
. E.g. this is what we generally do when defining current_user
method.
Further improvements/alternatives
if you start to get some more code, extract the code related to the page-list-fetching-and-rendering into a separate module, and include that into your ApplicationController
. This makes your ApplicationController
more readable.
- Note: this is exactly what
concerns
were introduced for, so you can use that, if you are on rails 4
a Page
is its own resource, so you could always create a separate PagesController
and make sure it is responsible for rendering the list, and use ajax to fetch on the pages where it is needed. This is a really nice solution, but also a bit more work (overkill?). But very nicely structured.
- This problem, where you have different areas on a page, which each should have their own Controller-Model-View, is exactly what the cells gem gem solves in a very clean way. There is a very good example of rendering a shopping-cart on the page I linked, so you could always check that out.