Rails 3 multiple layout question - ruby-on-rails

Can i have more than one layout per action -
What i want is - "show.html.erb" template to be contained in "layouts/users.html.erb" and this to be contained in "layouts/application.html.erb"
Basically I want application to be the global layout container, but i also want to use intermediate layouts containers between the action template & the final application layout.
If yes, can you point me to some help topics, links.

See the "Nested Layouts" section of the "Layouts and Rendering" guide.

You can use the Nested-Layout plugin:
http://nested-layouts.rubyforge.org
You can follow the instructions in "Sorta Nested Layouts":
http://mattmccray.com/archive/2007/02/19/Sorta_Nested_Layouts/
But what I would recommend is using named yield and content_for statements:
http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts
This approach lets you specify content for specific parts of your page and generally results in much cleaner and more readable code.

Related

Multiple layouts vs css trickery vs partials in a rails app for dynamic page layout

I was wondering if anyone could comment on which way is better and WHY?
Here is a simplified version of what I have ( in HAML):
#header
#root
#content
= yield
#sidebar
= context_navigation
#footer
The problem:
I want #sidebar to display on some pages to show context menu, such as on the account page to show links to profile, password, order history. On the product page show links to product specifications, description, "send link", etc. But not on other pages - such as on the home page I need to use the whole width of #root for #content to show news or featured items.
Solution & Question:
I have several ideas on how to implement it, but I was looking for some input at to which one you think is better and please explain WHY? The main objective is maintainability of code.
Here are some ideas:
CSS \ SCSS trickery - make the sidebar a collapsible div if there context navigation is empty
Use an else/if to load different partials depending on which part of the site I'm in.
Create a separate layout (seems like an overkill - as I understand layouts are to be used mostly for different media such as screen vs. print vs. pdf vs. mobile - etc)
Any other ideas?
Thank you,
Nick
You could use nested layouts to get this working:
http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts
Different views might serve you well... you may need to rethink your controller also to make them more use case specific. Going along this route will make you app more dynamic, increase cohesion amongst all of the components and allow for greater extensibility.

What are the best practices to generate "widgetized" content in Rails

On my previous projects built with usage of Zend Framework I extensively used Zend_view's "Action View" helper. It basically allows to initiate a separate cycle of request->dispatch ti action->view_rendering from a view script.
Here is the link to an appropriate page of zend framework reference guide (search for "Action View Helper").
This helper is quite a convenient way to work with widgetized content for example on pages with portal layout where you can stuff a page with different widgets (like advertising blocks, currency informers etc).
Although such an approach negatively affects response time of the page as it involves a lot of additional routing/dispatching activity, it allows to organizes widget code and views scripts into a rational structure. One widget is just a controller action, with linked view script.
Unfortunatelly, I have not found any similar view helpers in Rails.
Is there any way to elegantly solve this task in Rails?
In Rails, the render method of ActionController takes a Hash as arguments and outputs a simple string. You can use this in your view like so:
<%= render :partial => "shared/widgets/_#{widget.widgettype.name}", :collection => #current_user.widgets %>
In this case Rails will iterate through the list of #current_user.widgets, find a widget partials in "app/views/shared/widgets/_widgettypename.html.erb", and call the partial for each attached widget.
For further reading on Rails partials, see the ActionView::Partials documentation.
It seems that I've found an answer to my questions myself. It is "render_component" rails plugin. There is also a fork which apparently supports Rails3.

What's the difference between Partial and Slot in Symfony?

The two concepts Partial and Slot seem the same for me. Both of these two features replace placeholders in template with actual markup.
When should I use Partial and when should I use Slot?
The major difference between slots and partials is that the rendering for a given slot resides within a certain template. In opposite, the partial is merely an include of a template into another template.
"Basically, a slot is a placeholder that you can put in any of the view elements (in the layout, a template, or a partial). Filling this placeholder is just like setting a variable. The filling code is stored globally in the response, so you can define it anywhere (in the layout, a template, or a partial). Just make sure to define a slot before including it, and remember that the layout is executed after the template (this is the decoration process), and the partials are executed when they are called in a template."
Examples of ways of using each are:
Title for your page - would probably be placed in a slot (or in the title helper), and you would then in your layout check whether the slot was defined and then show it.
Sidebar items - say you have 3 sidebar "slots", you would then have three slots, for example 'sidebar-1', 'sidebar-2' and 'sidebar-3'. In your template you would then define the slot, which could be rendered using a partial (or even a component) if you wanted.
I hope that clarified it a bit.
A partial comes from a file:
include_partial('thing', $params) will include _thing.php with $params in it's scope.
Slots are not files, but set somewhere else in the template/controller:
slot('title', 'Home Page');
echo '<title>'.slot('title').'</title>'
All you need to know is the Symfony cheat sheet View. Partials, components, slots and component slots (PDF, 45 KB).
You could think of a slot as an OO method definition. Your layout defines slots. The template extends the layout and fills those slots (by overwriting the methods). You can also have a default content for a slot, which is displayed when it's not overwritten.
Partials on the other hand would be like composition. They are a reusable component that templates can access. Roughly they are the equivalent of a simple include statement, but you pass in the variables it uses.
This page does a pretty good job at explaining the concepts: http://www.symfony-project.org/book/1_2/07-Inside-the-View-Layer

How can I use an application layout in rails for all controllers except a few?

I have an application layout in my rails app to give a default header/footer for my entire website. I have 1 controller that I dont want this to apply to (a checkout page), and an entire namespace that needs to have a separate default template (the admin interface, which has 10-15 different controllers). What is the easiest way to do this?
app/views/layouts/application.html.erb
Will set the default for the entire layout. To override for a specific model, just have
app/views/layouts/mymodel.html.erb
I believe that will work for namespaces also, so long as your layouts directory structure matches your models' directory structure.
http://apidock.com/rails/ActionController/Layout/ClassMethods/layout
Just create new layout file (ie: /app/views/layouts/new_layout.html.erb) and set it in the beginning of the controller:
layout 'new_layout'

Global action to generate layout variables

what is the best way to implement some action that should be executed each time a request is made?
My aim is to export some variables layout-wide, so the layout could render some fields like "You are logged in as ${userName}, Server time is ${serverTime}".
I know I can inline code in the gsp, but there should be some better way to execute some operations on each request.
Thanks in advance.
I've just found an answer here: Accessing the model from a layout view in Grails
Filters is the way to execute some global action.
You could use layouts and SiteMesh to do that automagically, but in my project, I've stopped using that, because it also has some drawbacks (like <body onload="foobar()"> no longer working...). I propose you create a template just for this info line and render it wherever appropriate.

Resources