How to Implement different HTML background images based on different controller methods? - ruby-on-rails

Using Rails (4.1.4) and Ruby (2.1.2), what would be the most DRY way to implement different background images based on different controller actions? Would I need to move HTML code tags out of /app/views/layouts/application and move them into the separate view pages or is there a better way to do it?

You could use the content_for method. described here
Essentially, in your layout you might have
<body class="<%= yield #body_class %>">
Then in your views you could do
<% content_for :body_class do 'class-name' end %>
<!-- regular view HTML -->

Just use different classes on your element based on your action name and then apply different background images on those classes
Rails has controller_name and action_name helpers to get your controller name and action name so you can do:
<div class="<%= 'class_name' if action_name == 'show' %>">
</div>
And if you want to use the same class name as your controllers action then you can do
<div class="<%= action_name %>">
</div>
If you are using same layout for different controllers then you can utilize rails controller_name with action_name to make a unique class, something like:
<div class="<%= controller_name action_name %>">
</div>
Then use css accordingly, lets say you have home controller and new and show action then you can do
.home.show{
background: image-url("pic1.png");
}
.home.new{
background: image-url("pic2.png");
}

You can add dynamic class name on the element (which should have bg img)
# your '.html.erb' template
<body class="<%=controller_name%>-<%=action_name%>">
...
</body>
# your css file
// for user_controller's 'new' action
body.user-new {
background-image: url(http://cdn.topshelfcomix.com/catalog/covers/any_empire_cover_sm_lg.jpg);
}
// for profiles_controller's 'show' action
body.profile-show {
background-image: url(http://mrzine.monthlyreview.org/2011/images/latuff_egypt_by_any_means_necessary_a.gif);
}
That's it.. Enjoy!!

Related

set a class dynamically in Rails application layout file

the problem is this:
I have my application layout file looks like this:
app/views/layouts/application.html.erb
...
<section>
<%= yield %>
</section>
...
Now what I would like to do is set the class of the section element dynamically, depending on what view I'm rendering
for instance, if I'm rendering a Dashboard view from:
/app/views/admin/news_items/index.html.erb
I would like the class of the section element dynamically be set to "dashboard":
<section class="dashboard">
<%= yield %>
</section>
Is this possible with Rails?
thanks for your help,
Anthony
As far as i can understand you want specific namespaces to have different layouts right?
You can achieve easily this by specifying different layout for different controllers/namespaces
# In DashboardController
layout 'dashboard'
The above will use the dashboard.html.erb under app/views/layouts for all the actions that are inside the DashboardController or inherit from it.
I hope that helps
Maybe you could do something like this?
<section class="<%= controller.controller_name %>-<%= controller.action_name %>">
This will add a class like so
<section class="dashboard-show">
Source: https://stackoverflow.com/a/16813823/3651372

personalize the view related to one action

Is there a way to personalize the view related to only one action?
For instance I have the action campaigns#index and I want index.html.erb only to have an image background, because all the csss are included in one file how can I work out this problem?
Have you tried something like
<% if (params[:action] == "index") %>
...your code here, setting class="special-background"
<% else %>
...alternate code here, not setting the class
<% end %>
Then all you need to so is set the css for that class to show your background.
You can use css selectors to specify a background for just the index page. For instance, if you wanted to have a background on just the content of the index page, you could have your view look something like:
<div id='campaigns-index'>
<!-- some content -->
</div>
And then in your css do something to the effect of:
div#campaigns-index {
background-image: ...
}
I suggest you read up on css selectors (particularly ids). Here's a link.

Ruby Layout Inheritance

I was wondering if there is any layout inheritance implementation in ruby.
In symfony, you can do this:
layoutmain.html
Give <head> and all that here
<body>
<h3>{{title}}</h3>
{{block view}}
<div class="row">
<div class="span3">
{{content}}
</div>
</div>
{{end block}}
</body>
layout2.html
{{inherits layoutman}}
{{block view}}
<div class="container">
Structure it differently
</div>
{{end block}}
So to speak, it let's you inherit the whole template and override parts for a different layout. So the scripts etc stay as they are in the main template, but you can change the view structure. So you can reuse bits of code in the first layout
I found some liquid inheritance project on github, but it looked outdated
I use the following approach to achieve "nesting" of layouts which is the form of layout inheritance that I've found to be most useful.
In the main application helper module app/helpers/application_helper.rb I define a helper method parent_layout:
module ApplicationHelper
def parent_layout(layout)
#view_flow.set(:layout, self.output_buffer)
self.output_buffer = render(:file => layout)
end
end
This helper is responsible for capturing the output of the current layout and then rendering the specified parent layout with the child layout inserted when the parent yields.
Then in my views I can set up the layout inheritance as follows. I start with my main application layout app/views/layouts/application.html.erb which is the child layout in this configuration:
<div class="content">
<h1><%= content_for?(:title) ? yield(:title) : 'Untitled' %></h1>
<div class="inner">
<%= yield %>
</div>
</div>
<%= parent_layout 'layouts/container' %>
The call to the helper method parent_layout specifies that application.html.erb is a child layout of container.html.erb. I then define the parent layout app/views/layouts/container.html.erb as follows:
<!DOCTYPE html>
<html>
<head>
<title>Sample</title>
</head>
<body>
<%= yield %>
</body>
</html>
The yield in container.html.erb yields to the "derived" (or child) layout application.html.erb, i.e. it inserts the output of rendering application.html.erb into the <body> of container.html.erb. Note that the parent_layout call needs to come at the end of the template since it captures the output of the layout up until the point at which it is invoked.
This is based on this article but updated to work in Rails 3.2 (and, hopefully, later). I haven't tried it in Rails 4, but you'll be able to get something similar working.
Ruby on Rails views have a feature called "partials". I partial is a view that generates a bit of html and can be included in other views. The partials can also accept arguments (local variables) that customize their behavior. The partials can include other partials.
This is probably a good place to start learning about that: http://guides.rubyonrails.org/layouts_and_rendering.html
I have never needed to do some kind of layout inheritance thing like you are describing but I could imagine doing it pretty easily with partials and passing around ruby variables that say which partial to use in which situation.

Rails: Rendering Multiple index.html.erb on a Single Page

I am using tabs and want to load multiple index pages into tabs. For instance:
class AnimalsController < ApplicationController
def index
#dogs = Dog.all
#cats = Cat.all
end
end
Then in my views/animals/index.html.erb
<ul class="tabs">
<li>Dogs</li>
<li>Cats</li>
</ul>
<div id="#dogs">
<%= render #dogs %>
</div>
<div id="#cats">
<%= render #cats %>
</div>
Is refactoring out into a partial the only way to achieve this?
I'd like to have them loaded statically at once and not have to resort to doing an Ajax.load() when the tab is clicked.
You have your answer in the question itself. Why don't you just use javascript to hide the two partials and call them when their respective tab is clicked? You don't need ajax for this at all :)
Since you did not mention the javascript library that you use, I will give a generic solution using jquery:
Also you need not add a # to your respective div's ids. Change it to this:
<ul class="tabs">
<li id="dogs">Dogs</li>
<li id="cats">Cats</li>
</ul>
<div id="dogs" class="subTabs">
<%= render #dogs %><hr />
</div>
<div id="cats" class="subTabs">
<%= render #cats %><hr />
</div>
$(document).ready(function() {
$('.subTabs').hide(); //Hide the subTabs as soon as the DOM is loaded.
$('li').live('click', function(e) {
$('.subTabs').hide(); //Calling this again so as to remove an already loaded
tab, if any. You can refactor this part to make it
even simpler.
$('body').find('.subTabs').attr('id',$(this).attr('id')).show();
//This finds the ".subTabs" whose id is the same as the "li" id that
was clicked and shows it. Ofcourse, even this can be made even more
compact had i known your entire DOM structure.
});
});
Edit:
You also have to make sure that you style it using CSS to make it look more like tabs if you haven't already. :)
Hope this helps. :)
You typically only want to use a partial if you are using the same or almost the same code in more than one place.
When you say "index page", do you really want to use the same code that is used in an index of another controller? If so, then a partial is the best strategy.
Don't use JavaScript to solve a layout / code organization problem.

RenderAction needs to behave different depending on containing page

I use RenderAction to render a partial that is used all over my site.
It is a partial where the user can search for an entity. It depends on the Controller / Action that rendered the parent main view what is done once the entity is found.
Lets say I have the controllers:
HireController, FireController with
Action ActOnPerson and
PeopleController with Action FindPerson which renders the partial
FindPerson
The Views are Hire/SearchPerson.aspx and Fire/SearchPerson.aspx
Each View contains the helper:
<%Html.RenderAction("FindPerson ", "People"); %>
The form that posts to HireController/FireController is contained in the partial.
It needs to be this way, because there are actually a couple of steps (form posts) involved in finding a person.
Is there a way to decide inside the partial FindPerson if the form needs to be posted to FireController or HireController? I guess I am looking for something like public properties of WebControls but for RenderAction.
Just add parameter ("PostTo" or "Next") to People.FindPerson Action:
<% Html.RenderAction("FindPerson ", "People", new { next = Url.Action("ActOnPerson", "HireController") }); %>
<!-- or -->
<% Html.RenderAction("FindPerson ", "People", new { nextaction = "ActOnPerson", nextcontroller = "HireController" }); %>
In FindPerson PartialView:
<form method="post" action="<%= ViewData["next"].ToString() %>">
<!-- or -->
<% using (Html.BeginForm(
ViewData["nextaction"].ToString(), ViewData["nextcontroller"].ToString() ) { %>

Resources