Monday, July 17, 2017

Experiment: To Include Bootstrap Gem in My Ruby on Rails Project

* Currently, my Ruby on Rails project myapp2 did not equipped with the Bootstrap Gem.

* I created a new branch called: adding-bootstrap-attempt.
$ cd myapp2
$ git checkout -b adding-bootstrap-attempt

* I added the Bootstrap Gem into Gemfile.
myapp2/Gemfile
# Use Bookstrap
gem 'bootstrap-sass', '3.3.6'

* Then, I ran bundle install
$ bundle install
$ bundle show bootstrap-sass
/home/jimmyc/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/bootstrap-sass-3.3.6

* I created a new file called: custom.scss and copied the format for .user class
myapp2/app/assets/stylesheets/custom.scss
/* Users index */

.users {
  list-style: none;
  margin: 0;
  li {
    overflow: auto;
    padding: 10px 0;
    border-bottom: 1px solid;
  }
}

* I tried to copy all codes in custom.scss in Michael Hartl's sample_app to myapp2.

* It seemed that I could not copy everything in custom.scss. So I had to copy selectively. So, I deleted the typography (h1, h2, ..., h6, and p)  section. Then, I delete the header section (#logo) as well as footer section.

* In, Application Layout file, I changed CSS file for the stylesheet_link_tag.
myapp2/app/views/layout/application.html.erb
<%= stylesheet_link_tag 'templatemo-style.css' %>

* I pre-defined the asset file in assets.rb
myapp2/config/initializers/assets/rb
Rails.application.config.assets.precompile += %w( templatemo-style.css )

* I re-loaded Firefox, but the page seemed a little bit weird.

* I added custom.scss before templatemo-style.css.
myapp2/app/views/layout/application.html.erb
<%= stylesheet_link_tag 'custom.scss' %>
<%= stylesheet_link_tag 'templatemo-style.css' %>

* After I had done some trial and errors, these were the latest version of the files that I edited.

* The Assets Initializers file.
myapp2/config/initailizers/assets.rb
Rails.application.config.assets.version = '1.0'
Rails.application.config.assets.precompile += %w( templatemo-style.css )
Rails.application.config.assets.precompile += %w( bootstrap.min.css )

*  The Application Layouts file
myapp2/app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= csrf_meta_tags %>
       
<%= stylesheet_link_tag    'application',
                            media: 'all',
                            'data-turbolinks-track': 'reload' %>     

      <%= stylesheet_link_tag 'bootstrap.min.css',
                            media: 'all',
                            'data-turbolinks-track': 'reload' %>

      <%= stylesheet_link_tag 'templatemo-style.css',
                            media: 'all',
                            'data-turbolinks-track': 'reload' %>     
     
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
  <body>
    <%= render 'layouts/header' %>     
    <div class="container">
      <% flash.each do |message_type, message| %>
        <div class="alert alert-<%= message_type %>"><%= message %></div>
      <% end %>       
    <%= yield %>
      <%= render 'layouts/footer' %>       
        <%= debug(params) if Rails.env.development? %>
    </div>
  </body>   
</html>

* The CSS stylesheet file.
myapp2/app/assets/stylesheets/tempaltemo-style.css
/*

Classic Template

http://www.templatemo.com/tm-488-classic

-----------------------------*/

body {
    color: #000000;
    font-family: 'Open Sans', Helvetica, Arial, sans-serif;
    font-size: 18px;
    font-weight: 300;
    overflow-x: hidden;
}

a, button { transition: all 0.3s ease; }
a:hover,
a:focus {
    text-decoration: none;
    outline: none;
}

h2 { font-size: 2.2rem; }
.tm-thin-font { font-weight: 300; }

.container-fluid {
    margin-left: auto;
    margin-right: auto;
    max-width: 1390px;
    overflow-x: hidden;
}

@media (max-width: 1390px) {
    .container-fluid {
        padding-left: 5%;
        padding-right: 5%;
    }
}

.tm-header-inner {
    display: -webkit-center;
    display: -ms-flexbox;
    display: flex;
    -webkit-align-items: top;
        -ms-flex-align: center;
            align-items: center;
    -webkit-justify-content: space-between;
        -ms-flex-pack: justify;
            justify-content: space-between;
    height: 175px;
}

.tm-site-name {
    color: #cc9900;
    display: block;
    font-size: 2.6rem;
    font-weight: 400;
}

.tm-main-nav { font-size: 1.2rem; }

.navbar-nav .nav-link {
    border-radius: 6px;
    color: black;
    padding: 10px 40px;
}

.nav-item.active .nav-link,
.nav-link:hover,
.nav-link:focus {
    color: white;
    background-color: #cc9900;

}

.tm-gold-text { color: #cc9900; }

.tm-section {
    padding-top: 80px;
    padding-bottom: 100px;
}

.tm-home-img-container {
/* old:    background-image: url('../img/tm-home-img.jpg'); */
    background-image: url('tm-home-img.jpg');
    background-size: auto;
    background-position: center;
    background-repeat: no-repeat;
    height: 500px;
}

.tm-about-img-container { background-image: url('tm-about-img.jpg');    }
.tm-blog-img-container { background-image: url('tm-blog-img.jpg'); }
.tm-contact-img-container { background-image: url('tm-contact-img.jpg'); }

.tm-about-img-container,
.tm-blog-img-container,
.tm-contact-img-container {
    background-size: auto 200px;
    background-position: center;
    background-repeat: no-repeat;
    height: 200px;
}

.tm-title {
    margin-bottom: 1rem;
    line-height: 1.4;
}

.tm-subtitle {
    font-size: 1.4rem;
    max-width: 800px;
    margin: 0 auto 80px;
}

.tm-content-box {
    max-width: 310px;
    margin: 0 auto;
}

h3 { font-size: 1.65rem; }
h4 {
    font-size: 1.4rem;
    line-height: 1.6;
}

.tm-btn {
    color: white;
    background-color: #cc9900;
    border: none;
    border-radius: 5px;
    display: inline-block;
    padding: 10px 30px;
}

.tm-btn:hover,
.tm-btn:focus {
    background-color: #906E09;
    color: white;
    outline: none;
}

.tm-btn-gray { background-color: #666666; }
.tm-btn-gray:hover,
.tm-btn-gray:focus {
    background-color: #515050;   
}

.tm-margin-b-15 { margin-bottom: 15px; }
.tm-margin-b-20 { margin-bottom: 20px; }
.tm-margin-b-30 { margin-bottom: 30px; }
.tm-margin-b-40 { margin-bottom: 40px; }
.tm-margin-t-big { margin-top: 90px; }
.tm-margin-t-mid { margin-top: 60px; }
.tm-margin-t-small { margin-top: 30px; }

.tm-text-link {
    color: #006699;
    line-height: 2.8;
    text-decoration: underline;
}
.tm-overflow-auto { overflow: auto; }
.tm-small-font { font-size: 1rem; }
.tm-related-post { margin-bottom: 40px; }
.tm-related-post:last-child { margin-bottom: 0; }
.media-left { padding-right: 25px; }
.media-body {
    border-bottom: 1px solid #ccc;
    padding-bottom: 25px;
}

.tm-media-description { margin-bottom: 0; }

.tm-2-col-right { padding-left: 20px; }

.tm-footer {
    color: #c6c6c6;
    background-color: #191919;
    background-image: url('../img/classic-pattern-bg.png');
    font-size: 1rem;
    padding-top: 40px;
    padding-bottom: 20px;
}

.tm-footer-links-container { padding-left: 10px; }

.tm-footer-link {
    color: #CCCC66;
    line-height: 2.8;
    text-decoration: underline;
}

.tm-footer-link:hover,
.tm-footer-link:focus {
    color: #CCCC66;
    text-decoration: none;
}
.tm-footer-thumbnail { margin-bottom: 5px; }

.tm-copyright-text {
    color: #999999;
    margin-bottom: 0;
}

hr { border-top: 1px solid #CCCCCC; }
p { line-height: 1.9; }

.tm-gray-bg {
    background-color: #CCCCCC;
    color: black;
    padding: 30px 20px 20px;
}
.tm-footer-content-box-title { margin-bottom: 30px; }

.tm-img-post { margin-bottom: 30px; }

.tm-aside-r { padding-left: 30px; }

.form-control {
    border-radius: 0;
    font-size: 1.1rem;
    padding: 0.75rem 1rem;
}

.form-control:focus { border-color: #CC9900; }

.tm-form-description { margin-top: 30px; }
.tm-contact-form { padding-top: 20px; }

#google-map {
    height: 333px;
    width: 100%;
    margin-top: 40px;
}

.tm-contact-right { padding-left: 30px; }
.tm-p-small { font-size: 1rem; }

@media (max-width: 1199px) {
    .tm-2-col-left { padding-right: 0; }
    .tm-2-col-right { padding-left: 0; }
    .tm-text-link {
        line-height: 2.2;
    }
    .container-fluid {
        padding-left: 4%;
        padding-right: 4%;
    }
}

@media (max-width: 991px){

    .tm-home-img-container {
        background:none;
        height: auto;
    }

    .tm-subtitle { margin-bottom: 40px; }
   
    #tmNavbar .navbar-nav .nav-link { padding: 10px 25px; }
    .media { max-width: 240px; }
    .media-left {
        display: block;
        margin-bottom: 20px;
    }

    .tm-content-box { margin-bottom: 50px; }
    .tm-text-link { line-height: 2.4; }

    .tm-section {
        padding-top: 50px;
        padding-bottom: 60px;
    }

    .tm-2-col-left, .tm-2-col-right {
        margin: 0 auto;
        max-width: 660px;
    }
   
    .tm-margin-t-big { margin-top: 30px; }
    .media { max-width: 100%; }
    .media-left {
        display: table-cell;
        margin-bottom: 0;
    }

    .tm-footer-content-box { margin-bottom: 40px; }

    .tm-2-rows-md-swap {
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
        -webkit-flex-direction: column;
            -ms-flex-direction: column;
                flex-direction: column;
    }

    .tm-2-rows-md-down-1 {
        -webkit-order: 1;
            -ms-flex-order: 1;
                order: 1;       
    }
    .tm-2-rows-md-down-2 {
        -webkit-order: 2;
            -ms-flex-order: 2;
                order: 2;
        margin-bottom: 0;
        margin-top: 30px;       
    }

    .tm-contact-right {
        padding-left: 15px;
        padding-top: 40px;
    }
}

@media (max-width: 897px) {
    .tm-btn {
        padding: 10px 15px;
        font-size: 1rem;
    }
}

@media (max-width: 767px) {
    .tm-main-nav {
        position: fixed;
        right: 0;
        top: 21px;
        z-index: 1000;
    }
    #tmNavbar .navbar-nav .nav-item { float: none; }
    #tmNavbar .navbar-nav .nav-link { padding: 10px 35px; }
    #tmNavbar {
        background: white;
        border-radius: 6px;
    }
    #tmNavbar .navbar-nav .nav-item+.nav-item { margin-left: 0; }
    .navbar-toggler {
        background: white;
        border-color: #cc9900;
        color: #cc9900;
        display: block;
        margin-left: auto;
        margin-right: 0;
    }
    .navbar-toggler:focus { outline: none; }
    .tm-content-box { margin-bottom: 50px; }
   
    .tm-2-col-left {
        padding-right: 0;
        max-width: 660px;
    }

    .tm-2-col-right { padding-left: 0; }
    .tm-margin-b-40 { margin-bottom: 25px; }
   
    .tm-copyright-text { padding-top: 0; }
    .tm-gray-bg { padding: 20px 20px 10px; }
    .tm-footer { padding-bottom: 15px; }

    .tm-2-rows-sm-swap {
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
        -webkit-flex-direction: column;
            -ms-flex-direction: column;
                flex-direction: column;
    }

    .tm-2-rows-sm-down-1 {
        -webkit-order: 1;
            -ms-flex-order: 1;
                order: 1;       
    }
    .tm-2-rows-sm-down-2 {
        -webkit-order: 2;
            -ms-flex-order: 2;
                order: 2;
        margin-bottom: 0;
        margin-top: 30px;       
    }

    .tm-sm-m-b { margin-bottom: 20px; }
    .tm-aside-r { padding-left: 15px; }
    .tm-aside-container {
        max-width: 310px;
        margin: 0 auto;
    }

    .tm-blog-post {    padding-bottom: 10px; }
    .tm-content-box-contact {
        margin-top: 40px;
        margin-bottom: 0;
    }

    .tm-contact-row-related-posts {    margin-top: 40px; }
}

@media (max-width: 543px) {
    .tm-footer-links-container { padding-left: 0; }
    .tm-xs-m-t { margin-top: 20px; }
    .tm-btn { padding: 10px 30px; }
}

@media(max-width: 510px) {
    .media { max-width: 240px; }
    .media-left {
        display: block;
        margin-bottom: 20px;
    }
       
    .tm-section {
        padding-top: 10%;
        padding-bottom: 10%;
    }

    .tm-subtitle { margin-bottom: 20px; }
    .tm-margin-b-40 { margin-bottom: 15px; }
    .tm-content-box { margin-bottom: 40px; }
    .tm-margin-t-mid { margin-top: 30px; }
    .tm-footer-content-box { margin-bottom: 40px; }
    .tm-footer-content-box-title { margin-bottom: 15px; }
    #google-map { margin-top: 25px; }
    .tm-map-section { margin-top: 50px; }

    .tm-contact-related-posts-container {
        max-width: 240px;
        margin-left: auto;
        margin-right: auto;
    }
}

* The Custom SCSS style file by Michael Hartl's
myapp2/app/assets/stylesheets/custom.scss
@import "bootstrap-sprockets";
@import "bootstrap";

/* mixins, variables, etc. */

$gray-medium-light: #eaeaea;

@mixin box_sizing {
  -moz-box-sizing:    border-box;
  -webkit-box-sizing: border-box;
  box-sizing:         border-box;
}

/* universal */

body {
  padding-top: 60px;
}

section {
  overflow: auto;
}

textarea {
  resize: vertical;
}

.center {
  text-align: center;
  h1 {
    margin-bottom: 10px;
  }
}

/* typography */

h1, h2, h3, h4, h5, h6 {
  line-height: 1;
}

h1 {
  font-size: 3em;
  letter-spacing: -2px;
  margin-bottom: 30px;
  text-align: center;
}

h2 {
  font-size: 1.2em;
  letter-spacing: -1px;
  margin-bottom: 30px;
  text-align: center;
  font-weight: normal;
  color: $gray-light;
}

p {
  font-size: 1.1em;
  line-height: 1.7em;
}


/* header */

#logo {
  float: left;
  margin-right: 10px;
  font-size: 1.7em;
  color: white;
  text-transform: uppercase;
  letter-spacing: -1px;
  padding-top: 9px;
  font-weight: bold;
  &:hover {
    color: white;
    text-decoration: none;
  }
}

/* footer */

footer {
  margin-top: 45px;
  padding-top: 5px;
  border-top: 1px solid $gray-medium-light;
  color: $gray-light;
  a {
    color: $gray;
    &:hover {
      color: $gray-darker;
    }
  }
  small {
    float: left;
  }
  ul {
    float: right;
    list-style: none;
    li {
      float: left;
      margin-left: 15px;
    }
  }
}

/* miscellaneous */

.debug_dump {
  clear: both;
  float: left;
  width: 100%;
  margin-top: 45px;
  @include box_sizing;
}

/* sidebar */

aside {
  section.user_info {
    margin-top: 20px;
  }
  section {
    padding: 10px 0;
    margin-top: 20px;
    &:first-child {
      border: 0;
      padding-top: 0;
    }
    span {
      display: block;
      margin-bottom: 3px;
      line-height: 1;
    }
    h1 {
      font-size: 1.4em;
      text-align: left;
      letter-spacing: -1px;
      margin-bottom: 3px;
      margin-top: 0px;
    }
  }
}

.gravatar {
  float: left;
  margin-right: 10px;
}

.gravatar_edit {
  margin-top: 15px;
}

/* forms */

input, textarea, select, .uneditable-input {
  border: 1px solid #bbb;
  width: 100%;
  margin-bottom: 15px;
  @include box_sizing;
}

input {
  height: auto !important;
}

#error_explanation {
  color: red;
  ul {
    color: red;
    margin: 0 0 30px 0;
  }
}

.field_with_errors {
  @extend .has-error;
  .form-control {
    color: $state-danger-text;
  }
}

.checkbox {
    margin-top: -10px;
    margin-bottom: 10px;
    span {
        margin-left: 20px;
        font-weight: normal;
    }
}

#session_remember_me {
    width: auto;
    margin-left: 0;
}


/* Users index */

.users {
  list-style: none;
  margin: 0;
  li {
    overflow: auto;
    padding: 10px 0;
    border-bottom: 1px solid $gray-lighter;
  }
}

* The Gemfile.
myapp2/Gemfile
source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.2'

# Use the minitest ver 5.10.1 for testing stability
gem "minitest", "5.10.1"

# bcrypt for password digest
gem 'bcrypt',         '3.1.11'

# faker for creating sample users for testing
gem 'faker',          '1.7.3'

# For pagination
gem 'will_paginate',           '3.1.5'
gem 'bootstrap-will_paginate', '1.0.0'

# Use Bookstrap
gem 'bootstrap-sass', '3.3.6'

# gem for controller testing
gem 'rails-controller-testing'

# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use Puma as the app server
gem 'puma', '~> 3.0'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri
end

group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 3.0.5'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

* And this was the screenshot of the improved version myapp2 with required SCSS and CSS stylesheet files. It was not perfect and it still needed some fine tuning. But, it is good enough for me to do the Ruby on Rails coding.

* Finally, I ran the test to make sure no failures.
$ rails test
Running via Spring preloader in process 4347
Run options: --seed 18815

# Running:

/home/jimmyc/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/will_paginate-3.1.5/lib/will_paginate/view_helpers/link_renderer.rb:27: warning: constant ::Fixnum is deprecated
/home/jimmyc/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/will_paginate-3.1.5/lib/will_paginate/view_helpers/link_renderer.rb:91: warning: constant ::Fixnum is deprecated
./home/jimmyc/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/will_paginate-3.1.5/lib/will_paginate/view_helpers/link_renderer.rb:27: warning: constant ::Fixnum is deprecated
/home/jimmyc/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/will_paginate-3.1.5/lib/will_paginate/view_helpers/link_renderer.rb:91: warning: constant ::Fixnum is deprecated
...........................................

Finished in 2.413957s, 18.2273 runs/s, 81.1945 assertions/s.

44 runs, 196 assertions, 0 failures, 0 errors, 0 skips

* And then, I added all untracked files, committed the changes, merged back to Master branch, and pushed it onto Github.
$ git add -A
$ git commit -m "Improved SCSS file for All User Listing"
$ git checkout master
$ git merge adding-bootstrap-attempt
$ git push

* The Github address for myapp2 project was https://github.com/jimmy2046/myapp2

* At this time, I planned to continue to Ch 11 of Michael Hartl's book using his original sample_app project.

1 comment:

How to kill an abandoned process in Linux/Unix

I remembered it, then I forgot, then I remembered it, and then I forgot again. In case of a Linux/Unit process hang, I have to figure out ...