Redefine layout block in child view with rails 3 - ruby-on-rails

I have my layout looking like this :
<!doctype html>
<!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
<!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]-->
<!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]-->
<!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"> <!--<![endif]-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:og="http://opengraphprotocol.org/schema/" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<meta charset="UTF-8">
<title>My title</title>
<%= stylesheet_link_tag "general" %>
<%= javascript_include_tag "libs/jquery-1.5.1.min" %>
<%= csrf_meta_tag %>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<meta name="description" content="">
<meta name="author" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico">
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<% if flash[:notice] %>
<% if flash[:notice].kind_of?(Array) %>
<% flash[:notice].each do |id, value| %>
<p><%= id =%> <%= value =%> </p>
<% end %>
<% else %>
<p><%= flash[:notice] =%></p>
<% end %>
<% end %>
<% if flash[:error] %>
<p class="error"><%= flash[:error] %></p>
<% end %>
<!-- more content -->
<div id="principal">
<%= render 'layouts/header' %>
<%= render 'layouts/banner' %>
<%= yield %>
<%= render 'layouts/footer' %>
</div>
</body>
</html>
My problem is this line :
<%= render 'layouts/banner' %>
I have a banner in the top of my website. And i want to change it on each page. How can i overwrite this render from my index.html.erb view of my controller for example?
Thank you for help

Have a look at content_for. For instance:
layout
<%= content_for :banner %>
view
<% content_for :banner do %>
<h1>Banner for ThisParticularView!</h1>
<% end %>

Like this:
In your layout:
<%= content_for?(:banner) ? yield(:banner) : render 'layouts/banner' %>
Then in your view:
<%= content_for :banner do %>
banner code...
<% end %>
is the way closest to what you have now. However, I recommend just passing a local to the banner partial and using that on every page, like so:
<%= render :partial => 'layouts/banner', :locals => { :image_path => 'images/banner1.png' } %>
And then your 'banner' partial (it should be a partial, _banner.html.erb):
<%= image_tag(image_path) %>
You can even make it into a helper to save you a few keystrokes:
def banner(image_path='images/banner1.png')
render :partial => 'layouts/banner', :locals => { :image_path => image_path }
end
And then:
<%= banner 'images/banner5.png' %>
This also makes it easier to provide a default value to eliminate the possibility of Nil errors from your view, should you somehow forget to provide an image path to the banner helper.

You can
1 Use custom logic within the layouts/banner view
2 utilize content_for
# Somewhere deep inside
<% content_for :banner do %>
<!-- banner code -->
<% end %>
# In layout
<%= content_for :banner %>
3 Render custom banner file
# In controller
#file = "some_banner_file
# In layout
render #file

Related

Rails app with Boostrap not mobile response

After adding the viewport meta tag, my app still is not mobile responsive. I am using bootstrap as well. Is there any fix?
application.html.erb
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>gustoHop</title>
<%= csrf_meta_tags %>
<%= action_cable_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%#= stylesheet_pack_tag 'application', media: 'all' %> <!-- Uncomment if you import CSS in app/javascript/packs/application.js -->
<!-- <style>
#import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght#400;600;700&display=swap');
</style> -->
<%= favicon_link_tag asset_path('gustoHop-favicon.png') %>
</head>
<body>
<%= render "shared/navbar" %>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
<%= render "shared/footer" %>
<%= javascript_pack_tag 'application' %>
</body>
</html>

Turbolinks causes JavaScript file to run several times

I'm using Rails 5.1.4, I'm new on the platform and I have problems with turboblinks, I have a file containing jquery code that has to run once the page loads, but Whenever the page loads the file runs several times but when I disable the turboblinks there it works as I want it. So I would like to know if there is one less to fix it without turning off the turboblinks. Thank you in advance..
So there is my layout file.// app/views/layouts/application.html.erb
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Rails web app</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-
track' => true %>
<%= csrf_meta_tags %>
</head>
<body class="<%= controller_name %> <%= action_name %>">
<%= render 'layouts/header' %>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<div class="container">
<%= yield %>
</div>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true
%>
</body>
</html>
About my js file as you will see i try to load automatically a bootstrap modal with an animation when the page loaded, actually the problem happens when i clik to any link on this page which takes me to another page and i try to come back to the initial page where the js file is loaded, then the problem happens. i see the page refresh many times and the js file as well.
So there is my js file with jquery code. //app/assets/javascripts/file.js
$(document).ready(function(){
$('#myModal').on('hide.bs.modal', function (e) {
$('.modal .modal-dialog').attr('class', 'modal-dialog animated rollOut');
});
$('#myModal').on('show.bs.modal', function (e) {
$('.modal .modal-dialog').attr('class', 'modal-dialog fadeIn
animated');
});
$('#myModal').modal('toggle');
});
Turbolinks replaces the body so put this line in your head tag :
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
Like this :
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Rails web app</title>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= csrf_meta_tags %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
</head>
<body class="<%= controller_name %> <%= action_name %>">
<%= render 'layouts/header' %>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<div class="container">
<%= yield %>
</div>
</body>
</html>
or add data-turbolinks-eval=false to the script tag that includes turbolinks.
Also you need use the turbolinks:load event :
$(document).on('turbolinks:load', function() {
$('#myModal').on('hide.bs.modal', function (e) {
$('.modal .modal-dialog').attr('class', 'modal-dialog animated rollOut');
});
$('#myModal').on('show.bs.modal', function (e) {
$('.modal .modal-dialog').attr('class', 'modal-dialog fadeIn
animated');
});
$('#myModal').modal('toggle');
});

How write this code in HAML

How write this ERB code in HAML:
<head>
<meta charset="utf-8">
<title><%= title %></title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<%== meta_data_tags %>
<%= favicon_link_tag image_path('favicon.ico') %>
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="72x72" href="apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="114x114" href="apple-touch-icon-114x114.png">
<%= stylesheet_link_tag 'store/all', :media => 'screen' %>
<%= csrf_meta_tags %>
<%= javascript_include_tag 'store/all' %>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6/html5shiv.min.js"></script>
<![endif]-->
<%= render "spree/shared/routes" %>
<%= yield :head %>
</head>
particularly interested in this
<%== meta_data_tags %>
code snippet.
I found answer for my question:
= raw(meta_data_tags)
<%== %> is the same as <%= raw() %>. It's just a fast helper to achieve same result.
Thank you all for help. =)
In Erubis (whch Rails uses) the <%== ... %> syntax escapes the result of the expression. Haml has a similar feature using &=.
So a Haml version of <%== meta_data_tags %> might look something like:
&= meta_data_tags

Capybara ambiguous match - should have_content

I'm using Capybara and Rspec in a Rails app, and I keep failing some of my tests with this message :
Failure/Error: it { should have_content('error') }
Capybara::Ambiguous:
Ambiguous match, found 2 elements matching xpath "/html"
And that's kind of logical, because in my test, my app should render two messages with the 'error' content.
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
<%= t('the_form_contains') %>
<%= pluralize(object.errors.count, t('error')) %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
And here my application layout :
<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<div class="row-fluid">
<div class="offset2 span8 offset2">
<% flash.each do |key,value| %>
<div class="alert alert-<%= key %>"><%= value %></div>
<% end %>
</div>
</div>
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
</body>
</html>
Do you know a way (like an option), to make it pass ?
EDIT
I used save_and_open_page and I didn't found any additional html tag, neither error messages outside the page. But when I remove <!DOCTYPE html> then it works. Must I really have <!DOCTYPE html> and an opening <html> tag ? Can I delete <!DOCTYPE html> without consequences ?
<!DOCTYPE html>
<html>
<head>
<title>Le Troquet</title>
<link data-turbolinks-track="true" href="/assets/application.css" media="all" rel="stylesheet" />
<script data-turbolinks-track="true" src="/assets/application.js"></script>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
.
.
.
.
.
<!-- There is no html tag here -->
.
.
.
.
</body>
</html>
It looks like the problem is that you either:
have two <html> tags in your page, or possibly
the "error" text appears outside the <html></html> tags.
See this discussion: Ambiguous match, found 2 elements matching xpath "/html".
Check for elements outside of the closing </html> tag. In my case (HAML), I had a javascript tag that was improperly indented
%html
...
:javascript
FIX
%html
...
:javascript
...
Indenting the :javascript so it was contained within the html tag solved the issue.
OK, I understand the problem. When I use should have_content, Capybara search in the whole layout the content. But it finds two html tags, that make it fails, because it doesn't know which is the right one. And why is there two html tags ? Because Capybara doesn't ignore the <!DOCTYPE html>.
I solved my problem, but it's more of a bypass. Instead of searching a content, I made Capybara search for the 'error' div, that contains the 'error' messages. Thereby, it doesn't have to search the whole application layout, and it doesn't get stucked with the two html tags.
So I just had to replace it { should have_content('error') } by it { should have_selector('div', text: 'error') }, and it worked.

gmaps4rails on jQueryMobile map not showing when redirecting

I am using gmap4rails on jQueryMobile but the map is not showing when I'm doing a redirecting to the page showing the map. The map shows normally when I refresh the map page, but not when I redirect to the page showing the page. Does anyone have an idea why? Thanks! Below is the code
/app/views/items/map.html.erb
<div data-role="header">
<h1>Market</h1>
<%= link_to 'Sell/Buy', new_item_path, "data-icon" => "plus", "class" => "ui-btn-right" %>
<%= link_to 'Back', root_path, "class" => "ui-btn-left" %>
</div>
<div class="center-wrapper">
<div data-role="controlgroup" data-type="horizontal">
List
Map
</div>
</div>
<div data-role="content">
<%= gmaps4rails(#json) %>
</div>
/app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Project</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<link rel="stylesheet"
href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" />
<%= javascript_include_tag "application" %>
<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<%= csrf_meta_tag %>
</head>
<body>
<div data-role="page">
<%= yield %>
<%= yield :scripts %>
</div>
</body>
</html>
/config/routes.rb
ProjectZ::Application.routes.draw do
...
match '/map', to: 'items#map'
end

Resources