OK, here's my problem:
I have a HomeController
with an action, say index
, that would render a landing page for my site. The site also has a bunch of other Controllers that implement actions for various other functionalities.
I want a dynamic navigation bar on my home page and what I'm looking for is that HomeController#index
goes to every other Controller in my app and calls a particular method that would return and object with link details, for example, HomeController#index
would go to ContactController
and call a method get_link
which would return something like:
{label: "Contact", url: "/contact"}
Similarly HomeController#index
would try calling get_link
on every other controller until it has collected an Array
of link objects which could then be passed to the View to render navigation.
I tried doing this through metaprogramming in Modules and using included
hook method (getting my references from a Sitepoint tutorial). But that didn't work. Then I read somewhere that I may have to use ActiveSupport::Concern
for ths kind of functionality, but I'm not sure how to go about it. I've worked on PHP CMS like Drupal and WordPress any they implement this using hooks, which is more-or-less what I'm looking for here. Any ideas?
In Rails flavor MVC controllers are not the dumping ground for a bunch of miscellaneous junk. In fact the only public methods of a controller are the the actions which correspond to a HTTP request:
class ThingsController
before_action :set_thing, except: [:new, :index]
# THIS IS THE "PUBLIC API" OF THE CONTROLLER:
# GET /things
def index
@things = Thing.all
end
# GET /things/:id
def show
end
# EVERYTHING ELSE IS PRIVATE!
private
def set_thing
@thing = Thing.find(params[:id])
end
end
In fact controllers should only be instantiated by the Rails router or your controller tests. While you can create class methods and call them on your controllers this is also a huge anti-pattern.
According to the single responsibility pattern the controllers job is to just to respond to HTTP requests when called by the routing layer.
So do you solve such a case:
How exactly to solve the issue depends on the use case - is the content static or are you building something CMS like?