Bootstrap 5 Navbar & Layout

Add a Bootstrap 5 navbar plus bunch of partials and helpers
Icons/chart bar
Used 123 times
Created by
D Dale Zak

Usage

Run this command in your Rails app directory in the terminal:

rails app:template LOCATION="https://railsbytes.com/script/zmnsEn"
Template Source

Review the code before running this template on your machine.

file 'app/views/layouts/application.html.erb', <<-CODE
<!DOCTYPE html>
<html lang="en">
  <head>
    <%= render 'partials/metatags' %>
  </head>
  <body class="<%= body_class(params) %>">
    <nav class="d-block">
      <%= render 'partials/navbar' %>
    </nav>
    <main role="main" class="main m-3">
      <div class="container-fluid">
        <%= render 'partials/messages' %>
        <%= yield %>
      </div>
    </main>
  </body>
</html>
CODE

file 'app/views/partials/_navbar.html.erb', <<-CODE
<nav id="navbar" class="navbar navbar-expand-lg navbar-light bg-light">
  <div class="container-fluid">
    <%= link_to current_site, root_path, title: current_site, class: 'navbar-brand' %>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarContent" aria-controls="navbarContent" aria-expanded="false" aria-label="Menu">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarContent">
      <ul class="navbar-nav me-auto">
        <%= link_to "Page", "#", class: "nav-link" %>
      </ul>
      <ul class="navbar-nav">
        <% if user_signed_in? %>
          <%= link_to "Logout", destroy_user_session_path, class: "nav-link" %>
        <% else %>
          <%= link_to "Login", new_user_session_path, class: "nav-link" %>
          <%= link_to "Signup", new_user_registration_path, class: "nav-link" %>
        <% end %>
      </ul>
    </div>
  </div>
</nav>
CODE

file 'app/views/partials/_messages.html.erb', <<-CODE
<% colors = { 
  info: "info",
  notice: "success",
  success: "success",
  warning: "warning",
  error: "danger"
}.freeze %>
<% flash.each do |name, msg| %>
  <% if msg.is_a?(String) %>
  <div class="alert alert-<%= colors[name.to_sym] || "info" %> alert-dismissible fade show" role="alert">
    <%= content_tag :div, msg %>
    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
  </div>
  <% end %>
<% end %>
CODE

file 'app/views/partials/_metatags.html.erb', <<-CODE
<title><%=h sanitize current_title %></title>
<link rel="canonical" href="<%=h current_url %>" />
<% if content_for?(:image) -%>
<link rel="image_src" href="<%= content_for(:image) %>">
<% end %>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="<%=h content_for_or(:robot, 'INDEX,FOLLOW') %>"/>
<meta name="description" content="<%=h content_for_or(:description, '') %>"/>
<meta name="keywords" content="<%=h content_for_or(:keywords, '') %>">
<meta name="theme-color" content="#777777">
<meta property="og:url" content="<%=h current_url %>" />
<meta property="og:site_name" content="<%= current_site %>" />
<meta property="og:type" content="<%=h content_for_or(:type, 'website') %>">
<meta property="og:title" content="<%=h current_title %>" />
<meta property="og:description" content="<%=h content_for_or(:description, '') %>" />
<% if content_for?(:image) -%>
<meta property="og:image" content="<%= content_for(:image) %>" />
<% end %>
<% if content_for?(:video) -%>
<meta property="og:video" content="<%= content_for(:video) %>" />
<% end %>
<meta name="twitter:card" content="summary" />
<% if ENV['APP_TWITTER'].present? %>
<meta name="twitter:site" content="<%= ENV['APP_TWITTER'] %>"/>
<meta name="twitter:creator" content="<%= ENV['APP_TWITTER'] %>"/>
<% end %>
<meta name="twitter:title" content="<%=h current_title %>"/>
<meta name="twitter:description" content="<%=h content_for_or(:description, '') %>"/>
<meta name="twitter:url" content="<%=h current_url %>"/>
<% if content_for?(:image) -%>
<meta name="twitter:image" content="<%= content_for(:image) %>"/>
<% end %>
<%= auto_discovery_link_tag(:rss, content_for(:rss), {title: "RSS Feed"}) if content_for?(:rss) %>
<%= auto_discovery_link_tag(:atom, content_for(:atom), {title: "Atom Feed"}) if content_for?(:atom) %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= action_cable_meta_tag %>
CODE

inject_into_file 'app/helpers/application_helper.rb', after: "module ApplicationHelper\n" do <<-CODE
  def current_url
    "\#{request.protocol}\#{request.host_with_port}\#{request.fullpath}"
  end

  def current_site
    Rails.application.class.module_parent.name
      .underscore
      .humanize
      .split
      .map(&:capitalize)
      .join(' ')
  end

  def current_title
    title = []
    title << current_site
    if content_for?(:title)
      title << content_for(:title)
    else
      title << params[:controller].split("/").last.titleize
    end
    title.uniq.join(" | ")
  end

  def title(elements=[])
    content_for :title, elements.to_a.compact.map{ |a| a.try(:name) || a.try(:title) || a.try(:id) || a.to_s.capitalize }.join(" | ")
  end

  def description(description="")
    content_for :description, description
  end

  def sanitize(content)
    ActionController::Base.helpers.sanitize(content)
  end

  def strip_tags_and_entities(string)
    if string.present?
      stripped = strip_tags(string)
      decoded = HTMLEntities.new.decode(stripped)
      decoded.squish.gsub(%r{/<\/?[^>]*>/}, "")
    end
  end

  def route_exists?(path)
    begin
      recognize_path = Rails.application.routes.recognize_path(path, method: :get)
      recognize_path.present? && recognize_path[:action] != "route_not_found"
    rescue StandardError
      false
    end
  end

  def content_for_or(name, default)
    if content_for?(name)
      content_for(name)
    else
      default
    end
  end

  def body_class(params)
    body = []
    return unless params[:controller]
    if params[:controller].include?("/")
      body << params[:controller].split("/").first
      body << params[:controller].gsub("/", "-")
    else
      body << params[:controller]
    end
    if params[:controller].include?("/")
      body << "\#{params[:controller].gsub('/', '-')}-\#{params[:action]}"
    else
      body << "\#{params[:controller]}-\#{params[:action]}"
    end
    if params.key?(:page)
      body << "\#{params[:controller]}-\#{params[:action]}-\#{params[:page]}"
    end
    body.join(" ")
  end
CODE
end
Comments

Sign up or Login to leave a comment.