4

This seems extremely basic, but I've read a lot of related questions and haven't found a proper answer.

Using Ruby on Rails or other similar MVC framework, how am I supposed to load data that is displayed in sidebars on multiple pages?

Options I know of, with the problems I see:

  • Load it in every controller method that needs it: causes duplication of code;
  • Load it in a method on the ApplicationController, which is executed by all controllers: would cause data to be loaded even when not needed;
  • Load it directly from the model in the view: not MVC?

I've asked this elsewhere and some people told me to "look into [insert another pattern here]" or "use Ajax calls to get the data". Although those might also work, I'm looking for an answer regarding MVC frameworks on the server.

3

Typically, I think the duplication is best handled by pushing the shared code up into a superclass (either in ApplicationController or some other superclass your controller inherits from) as a private method. I think nowadays DHH wants you to put your shared code in modules (erm, i mean concerns), and include those in your controllers, as opposed to shoving everything in ApplicationController.

Depending on your situation you'd either run the code in a before_filter on each controller action where you have your sidebar, or put the before_filter up in a superclass and call skip_before_filter when you dont want the code run before a specific controller action.

Also, its certainly possible to use ajax to accomplish this but unless you have a really good reason, I would avoid doing it that way.

There are also times when I think calling class methods on a model directly from a view is perfectly OK. Like getting simple counts, for example.

  • Thanks, excellent answer (sorry I can't upvote yet). From what I've read so far concerns is a great option. – Schrute Oct 21 '14 at 6:05
  • I upvoted on your behalf, @Schrute. – codenheim Oct 21 '14 at 6:13
2

You may be having trouble if you are thinking of all MVC as a 1 to 1 relationship of View to Controller and a View per Page. A view is not necessarily a page and a page is not necessarily a single view. Commonly they are 1 to 1, but often there is more to it. You might have pages made up of a handful of views, though there will usually be one master view that correlates to the current controller.

Rather than make it part of multiple controllers, you can dedicate a new controller to the sidebar and call it SideBarController. It has its own view.

In ASP.NET MVC land, I'd call it a partial view. Basically a fragment of markup that is included in a master page or set of pages. A master page is often a template page with header, footer, left nav, and main content. In RoR land, I think its done using explicit render

Example, my ProductsController returns a view, the Products index page renders, and inside that template page there is a markup tag that calls SideBar.

Not touched Rails in years, but I think:

render template: "sidebar/show"

Or simply:

render "sidebar/show"

Is enough since it Rails knows its a different controller with the embedded slash.

http://guides.rubyonrails.org/layouts_and_rendering.html

  • AFAIK the embedded slash thing only works when calling render from the controller. When using it to render partials in a template file, the slash just designates a different file path. It would be great to have the view calling a different controller to get data, but I don't think Rails supports it. Thanks. – Schrute Oct 21 '14 at 2:12
  • 'Partial' views are common in Node.js and Jade, at least in my experience. I find this to be the most useful practice: compose partial views (sidebars, navbars, modals that are re-used, etc.) and then compose 'master views' which combine several 'partial views'. – Chris Cirefice Oct 21 '14 at 2:54
  • @ChrisCirefice yes, but what I don't understand is how to provide data to these partials. At least in Rails or CakePHP, for example, I don't see a way to do this without the problems I mentioned in my question. – Schrute Oct 21 '14 at 5:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.