One place for hosting & domains

      How To Add and Delete Users on CentOS 8


      Introduction

      When you first start using a fresh Linux server, adding and removing users is often one of first things you’ll need to do. In this guide, we will cover how to create user accounts, assign sudo privileges, and delete users on a CentOS 8 server.

      Prerequisites

      This tutorial assumes you are logged into a CentOS 8 server with a non-root sudo-enabled user. If you are logged in as root instead, you can drop the sudo portion of all the following commands, but they will work either way.

      Adding Users

      Throughout this tutorial we will be working with the user sammy. Please susbtitute with the username of your choice.

      You can add a new user by typing:

      Next, you’ll need to give your user a password so that they can log in. To do so, use the passwd command:

      You will be prompted to type in the password twice to confirm it. Now your new user is set up and ready for use!

      Note: if your SSH server disallows password-based authentication, you will not yet be able to connect with your new username. Details on setting up key-based SSH authentication for the new user can be found in step 5 of Initial Server Setup with CentOS 8.

      Granting Sudo Privileges to a User

      If your new user should have the ability to execute commands with root (administrative) privileges, you will need to give them access to sudo.

      We can do this by adding the user to the wheel group (which gives sudo access to all of its members by default).

      Use the usermod command to add your user to the wheel group:

      • sudo usermod -aG wheel sammy wheel

      Now your new user is able to execute commands with administrative privileges. To do so, append sudo ahead of the command that you want to execute as an administrator:

      You will be prompted to enter the password of the your user account (not the root password). Once the correct password has been submitted, the command you entered will be executed with root privileges.

      Managing Users with Sudo Privileges

      While you can add and remove users from a group with usermod, the command doesn’t have a way to show which users are members of a group.

      To see which users are part of the wheel group (and thus have sudo privileges), you can use the lid command. lid is normally used to show which groups a user belongs to, but with the -g flag, you can reverse it and show which users belong in a group:

      Output

      centos(uid=1000) sammy(uid=1001)

      The output will show you the usernames and UIDs that are associated with the group. This is a good way of confirming that your previous commands were successful, and that the user has the privileges that they need.

      Deleting Users

      If you have a user account that you no longer need, it’s best to delete it.

      To delete the user without deleting any of their files, use the userdel command:

      If you want to delete the user’s home directory along with their account, add the -r flag to userdel:

      With either command, the user will automatically be removed from any groups that they were added to, including the wheel group if applicable. If you later add another user with the same name, they will have to be added to the wheel group again to gain sudo access.

      Conclusion

      You should now have a good grasp on how to add and remove users from your CentOS 8 server. Effective user management will allow you to separate users and give them only the access that is needed for them to do their job.

      You can now move on to configuring your CentOS 8 server for whatever software you need, such as a LAMP or LEMP web stack.



      Source link

      How To Add Sidekiq and Redis to a Ruby on Rails Application


      Introduction

      When developing a Ruby on Rails application, you may find you have application tasks that should be performed asynchronously. Processing data, sending batch emails, or interacting with external APIs are all examples of work that can be done asynchronously with background jobs. Using background jobs can improve your application’s performance by offloading potentially time-intensive tasks to a background processing queue, freeing up the original request/response cycle.

      Sidekiq is one of the more widely used background job frameworks that you can implement in a Rails application. It is backed by Redis, an in-memory key-value store known for its flexibility and performance. Sidekiq uses Redis as a job management store to process thousands of jobs per second.

      In this tutorial, you will add Redis and Sidekiq to an existing Rails application. You will create a set of Sidekiq worker classes and methods to handle:

      • A batch upload of endangered shark information to the application database from a CSV file in the project repository.
      • The removal of this data.

      When you are finished, you will have a demo application that uses workers and jobs to process tasks asynchronously. This will be a good foundation for you to add workers and jobs to your own application, using this tutorial as a jumping off point.

      Prerequisites

      To follow this tutorial, you will need:

      Step 1 — Cloning the Project and Installing Dependencies

      Our first step will be to clone the rails-bootstrap repository from the DigitalOcean Community GitHub account. This repository includes the code from the setup described in How To Add Bootstrap to a Ruby on Rails Application, which explains how to add Bootstrap to an existing Rails 5 project.

      Clone the repository into a directory called rails-sidekiq:

      • git clone https://github.com/do-community/rails-bootstrap.git rails-sidekiq

      Navigate to the rails-sidekiq directory:

      In order to work with the code, you will first need to install the project’s dependencies, which are listed in its Gemfile. You will also need to add the sidekiq gem to the project to work with Sidekiq and Redis.

      Open the project’s Gemfile for editing, using nano or your favorite editor:

      Add the gem anywhere in the main project dependencies (above development dependencies):

      ~/rails-sidekiq/Gemfile

      . . . 
      # Reduces boot times through caching; required in config/boot.rb
      gem 'bootsnap', '>= 1.1.0', require: false
      gem 'sidekiq', '~>6.0.0'
      
      group :development, :test do
      . . .
      

      Save and close the file when you are finished adding the gem.

      Use the following command to install the gems:

      You will see in the output that the redis gem is also installed as a requirement for sidekiq.

      Next, you will install your Yarn dependencies. Because this Rails 5 project has been modified to serve assets with webpack, its JavaScript dependencies are now managed by Yarn. This means that it’s necessary to install and verify the dependencies listed in the project’s package.json file.

      Run yarn install to install these dependencies:

      Next, run your database migrations:

      Once your migrations have finished, you can test the application to ensure that it is working as expected. Start your server in the context of your local bundle with the following command if you are working locally:

      If you are working on a development server, you can start the application with:

      • bundle exec rails s --binding=your_server_ip

      Navigate to localhost:3000 or http://your_server_ip:3000. You will see the following landing page:

      Application Landing Page

      To create a new shark, click on the Get Shark Info button, which will take you to the sharks/index route:

      Sharks Index Route

      To verify that the application is working, we can add some demo information to it. Click on New Shark. You will be prompted for a username (sammy) and password (shark), thanks to the project’s authentication settings.

      On the New Shark page, input “Great White” into the Name field and “Scary” into the Facts field:

      Shark Create

      Click on the Create Shark button to create the shark. Once you see that your shark has been created, you can kill the server with CTRL+C.

      You have now installed the necessary dependencies for your project and tested its functionality. Next, you can make a few changes to the Rails application to work with your endangered sharks resources.

      Step 2 — Generating a Controller for Endangered Shark Resources

      To work with our endangered shark resources, we will add a new model to the application and a controller that will control how information about endangered sharks is presented to users. Our ultimate goal is to make it possible for users to upload a large batch of information about endangered sharks without blocking our application’s overall functionality, and to delete that information when they no longer need it.

      First, let’s create an Endangered model for our endangered sharks. We’ll include a string field in our database table for the shark name, and another string field for the International Union for the Conservation of Nature (IUCN) categories that determine the degree to which each shark is at risk.

      Ultimately, our model structure will match the columns in the CSV file that we will use to create our batch upload. This file is located in the db directory, and you can check its contents with the following command:

      The file contains a list of 73 endangered sharks and their IUCN statuses - vu for vulnerable, en for endangered, and cr for critically endangered.

      Our Endangered model will correlate with this data, allowing us to create new Endangered instances from this CSV file. Create the model with the following command:

      • rails generate model Endangered name:string iucn:string

      Next, generate an Endangered controller with an index action:

      • rails generate controller endangered index

      This will give us a starting point to build out our application’s functionality, though we will also need to add custom methods to the controller file that Rails has generated for us.

      Open that file now:

      • nano app/controllers/endangered_controller.rb

      Rails has provided us with a skeletal outline that we can begin to fill in.

      First, we’ll need to determine what routes we require to work with our data. Thanks to the generate controller command, we have an index method to begin with. This will correlate to an index view, where we will present users with the option to upload endangered sharks.

      However, we will also want to deal with cases where users may have already uploaded the sharks; they will not need an upload option in this case. We will somehow need to assess how many instances of the Endangered class already exist, since more than one indicates that the batch upload has already occurred.

      Let’s start by creating a set_endangered private method that will grab each instance of our Endangered class from the database. Add the following code to the file:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      class EndangeredController < ApplicationController
        before_action :set_endangered, only: [:index, :data]
      
        def index
        end
      
        private
      
          def set_endangered
            @endangered = Endangered.all 
          end
      
      end
      

      Note that the before_action filter will ensure that the value of @endangered is only set for the index and data routes, which will be where we handle the endangered shark data.

      Next, add the following code to the index method to determine the correct path for users visiting this part of the application:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      class EndangeredController < ApplicationController
        before_action :set_endangered, only: [:index, :data]
      
        def index          
          if @endangered.length > 0
            redirect_to endangered_data_path
          else
            render 'index'
          end
        end
      . . . 
      

      If there are more than 0 instances of our Endangered class, we will redirect users to the data route, where they can view information about the sharks they’ve created. Otherwise, they will see the index view.

      Next, below the index method, add a data method, which will correlate to a data view:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      . . . 
        def index          
          if @endangered.length > 0
            redirect_to endangered_data_path
          else
            render 'index'
          end
        end
      
        def data 
        end
      . . .
      

      Next, we will add a method to handle the data upload itself. We’ll call this method upload, and it will call a Sidekiq worker class and method to perform the data upload from the CSV file. We will create the definition for this worker class, AddEndangeredWorker, in the next step.

      For now, add the following code to the file to call the Sidekiq worker to perform the upload:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      . . . 
        def data 
        end
      
        def upload
          csv_file = File.join Rails.root, 'db', 'sharks.csv'   
          AddEndangeredWorker.perform_async(csv_file)
          redirect_to endangered_data_path, notice: 'Endangered sharks have been uploaded!'
        end
      . . .
      

      By calling the perform_async method on the AddEndangeredWorker class, using the CSV file as an argument, this code ensures that the shark data and upload job get passed to Redis. The Sidekiq workers that we will set up monitor the job queue and will respond when new jobs arise.

      After calling perform_async, our upload method redirects to the data path, where users will be able to see the uploaded sharks.

      Next, we’ll add a destroy method to destroy the data. Add the following code below the upload method:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      . . . 
        def upload
          csv_file = File.join Rails.root, 'db', 'sharks.csv'   
          AddEndangeredWorker.perform_async(csv_file)
          redirect_to endangered_data_path, notice: 'Endangered sharks have been uploaded!'
        end
      
        def destroy
          RemoveEndangeredWorker.perform_async
          redirect_to root_path
        end
      . . . 
      

      Like our upload method, our destroy method includes a perform_async call on a RemoveEndangeredWorker class – the other Sidekiq worker that we will create. After calling this method, it redirects users to the root application path.

      The finished file will look like this:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      class EndangeredController < ApplicationController
        before_action :set_endangered, only: [:index, :data]
      
        def index          
          if @endangered.length > 0
            redirect_to endangered_data_path
          else
            render 'index'
          end
        end
      
        def data 
        end
      
        def upload
          csv_file = File.join Rails.root, 'db', 'sharks.csv'   
          AddEndangeredWorker.perform_async(csv_file)
          redirect_to endangered_data_path, notice: 'Endangered sharks have been uploaded!'
        end
      
        def destroy
          RemoveEndangeredWorker.perform_async
          redirect_to root_path
        end
      
        private
      
          def set_endangered
            @endangered = Endangered.all 
          end 
      
      end
      

      Save and close the file when you are finished editing.

      As a final step in solidifying our application’s routes, we will modify the code in config/routes.rb, the file where our route declarations live.

      Open that file now:

      The file currently looks like this:

      ~/rails-sidekiq/config/routes.rb

      Rails.application.routes.draw do
        get 'endangered/index'
        get 'home/index'
        resources :sharks do
                resources :posts
        end
        root 'home#index'
        # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
      end
      

      We will need to update the file to include the routes that we’ve defined in our controller: data, upload, and destroy. Our data route will match with a GET request to retrieve the shark data, while our upload and destroy routes will map to POST requests that upload and destroy that data.

      Add the following code to the file to define these routes:

      ~/rails-sidekiq/config/routes.rb

      Rails.application.routes.draw do
        get 'endangered/index'
        get 'endangered/data', to: 'endangered#data'
        post 'endangered/upload', to: 'endangered#upload'
        post 'endangered/destroy', to: 'endangered#destroy'
        get 'home/index'
        resources :sharks do
                resources :posts
        end
        root 'home#index'
        # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
      end
      

      Save and close the file when you are finished editing.

      With your Endangered model and controller in place, you can now move on to defining your Sidekiq worker classes.

      Step 3 — Defining Sidekiq Workers

      We have called perform_async methods on our Sidekiq workers in our controller, but we still need to create the workers themselves.

      First, create a workers directory for the workers:

      Open a file for the AddEndangeredWorker worker:

      • nano app/workers/add_endangered_worker.rb

      In this file, we will add code that will allow us to work with the data in our CSV file. First, add code to the file that will create the class, include the Ruby CSV library, and ensure that this class functions as a Sidekiq Worker:

      ~/rails-sidekiq/app/workers/add_endangered_worker.rb

      class AddEndangeredWorker
        require 'csv'
        include Sidekiq::Worker
        sidekiq_options retry: false
      
      end
      

      We’re also including the retry: false option to ensure that Sidekiq does not retry the upload in the case of failure.

      Next, add the code for the perform function:

      ~/rails-sidekiq/app/workers/add_endangered_worker.rb

      class AddEndangeredWorker
        require 'csv'
        include Sidekiq::Worker
        sidekiq_options retry: false
      
        def perform(csv_file)
          CSV.foreach(csv_file, headers: true) do |shark|
          Endangered.create(name: shark[0], iucn: shark[1])
        end
       end
      
      end
      

      The perform method receives arguments from the perform_async method defined in the controller, so it’s important that the argument values are aligned. Here, we pass in csv_file, the variable we defined in the controller, and we use the foreach method from the CSV library to read the values in the file. Setting headers: true for this loop ensures that the first row of the file is treated as a row of headers.

      The block then reads the values from the file into the columns we set for our Endangered model: name and iucn. Running this loop will create Endangered instances for each of the entries in our CSV file.

      Once you have finished editing, save and close the file.

      Next, we will create a worker to handle deleting this data. Open a file for the RemoveEndangeredWorker class:

      • nano app/workers/remove_endangered_worker.rb

      Add the code to define the class, and to ensure that it uses the CSV library and functions as a Sidekiq Worker:

      ~/rails-sidekiq/app/workers/remove_endangered_worker.rb

      class RemoveEndangeredWorker
        include Sidekiq::Worker
        sidekiq_options retry: false
      
      end
      

      Next, add a perform method to handle the destruction of the endangered shark data:

      ~/rails-sidekiq/app/workers/remove_endangered_worker.rb

      class RemoveEndangeredWorker
        include Sidekiq::Worker
        sidekiq_options retry: false
      
        def perform
          Endangered.destroy_all
        end
      
      end
      

      The perform method calls destroy_all on the Endangered class, which will remove all instances of the class from the database.

      Save and close the file when you are finished editing.

      With your workers in place, you can move on to creating a layout for your endangered views, and templates for your index and data views, so that users can upload and view endangered sharks.

      Step 4 — Adding Layouts and View Templates

      In order for users to enjoy their endangered shark information, we will need to address two things: the layout for the views defined in our endangered controller, and the view templates for the index and data views.

      Currently, our application makes use of an application-wide layout, located at app/views/layouts/application.html.erb, a navigation partial, and a layout for sharks views. The application layout checks for a content block, which allows us to load different layouts based on which part of the application our user is engaging with: for the home index page, they will see one layout, and for any views relating to individual sharks, they will see another.

      We can repurpose the sharks layout for our endangered views since this format will also work for presenting shark data in bulk.

      Copy the sharks layout file over to create an endangered layout:

      • cp app/views/layouts/sharks.html.erb app/views/layouts/endangered.html.erb

      Next, we’ll work on creating the view templates for our index and data views.

      Open the index template first:

      • nano app/views/endangered/index.html.erb

      Delete the boilerplate code and add the following code instead, which will give users some general information about the endangered categories and present them with the option to upload information about endangered sharks:

      ~/rails-sidekiq/app/views/endangered/index.html.erb

      <p id="notice"><%= notice %></p>
      
      <h1>Endangered Sharks</h1>
      
      <p>International Union for Conservation of Nature (ICUN) statuses: <b>vu:</b> Vulnerable, <b>en:</b> Endangered, <b>cr:</b> Critically Endangered </p>
      
      <br>
      
        <%= form_tag endangered_upload_path do %>
        <%= submit_tag "Import Endangered Sharks" %>
        <% end %>
      
        <br>
      
      <%= link_to 'New Shark', new_shark_path, :class => "btn btn-primary btn-sm" %> <%= link_to 'Home', home_index_path, :class => "btn btn-primary btn-sm" %>
      

      A form_tag makes the data upload possible by pointing a post action to the endangered_upload_path – the route we defined for our uploads. A submit button, created with the submit_tag, prompts users to "Import Endangered Sharks".

      In addition to this code, we’ve included some general information about ICUN codes, so that users can interpret the data they will see.

      Save and close the file when you are finished editing.

      Next, open a file for the data view:

      • nano app/views/endangered/data.html.erb

      Add the following code, which will add a table with the endangered shark data:

      ~/rails-sidekiq/app/views/endangered/data.html.erb

      <p id="notice"><%= notice %></p>
      
      <h1>Endangered Sharks</h1>
      
      <p>International Union for Conservation of Nature (ICUN) statuses: <b>vu:</b> Vulnerable, <b>en:</b> Endangered, <b>cr:</b> Critically Endangered </p>
      
      <div class="table-responsive">
      <table class="table table-striped table-dark">
        <thead>
          <tr>
            <th>Name</th>
            <th>IUCN Status</th>
            <th colspan="3"></th>
          </tr>
        </thead>
      
        <tbody>
          <% @endangered.each do |shark| %>
            <tr>
              <td><%= shark.name %></td>
              <td><%= shark.iucn %></td>
            </tr>
          <% end %>
        </tbody>
      </table>
      </div>
      
      <br>
      
        <%= form_tag endangered_destroy_path do %>
        <%= submit_tag "Delete Endangered Sharks" %>
        <% end %>
      
        <br>
      
      <%= link_to 'New Shark', new_shark_path, :class => "btn btn-primary btn-sm" %> <%= link_to 'Home', home_index_path, :class => "btn btn-primary btn-sm" %>
      

      This code includes the ICUN status codes once again, and a Bootstrap table for the outputted data. By looping through our @endangered variable, we output the name and ICUN status of each shark to the table.

      Below the table, we have another set of form_tags and submit_tags, which post to the destroy path by offering users the option to "Delete Endangered Sharks".

      Save and close the file when you are finished editing.

      The last modification we’ll make to our views will be in the index view associated with our home controller. You may recall that this view is set as the root of the application in config/routes.rb.

      Open this file for editing:

      • nano app/views/home/index.html.erb

      Find the column in the row that states Sharks are ancient:

      ~/rails-sidekiq/app/views/home/index.html.erb

      . . . 
              <div class="col-lg-6">
                  <h3>Sharks are ancient</h3>
                  <p>There is evidence to suggest that sharks lived up to 400 million years ago.
                  </p>
              </div>
          </div>
      </div>
      

      Add the following code to the file:

      ~/rails-sidekiq/app/views/home/index.html.erb

      . . . 
              <div class="col-lg-6">
                  <h3>Sharks are ancient and SOME are in danger</h3>
                  <p>There is evidence to suggest that sharks lived up to 400 million years ago. Without our help, some could disappear soon.</p>
                  <p><%= button_to 'Which Sharks Are in Danger?', endangered_index_path, :method => :get,  :class => "btn btn-primary btn-sm"%>
                  </p>
              </div>
          </div>
      </div>
      

      We’ve included a call to action for users to learn more about endangered sharks, by first sharing a strong message, and then adding a button_to helper that submits a GET request to our endangered index route, giving users access to that part of the application. From there, they will be able to upload and view endangered shark information.

      Save and close the file when you are finished editing.

      With your code in place, you are ready to start the application and upload some sharks!

      Step 5 — Starting Sidekiq and Testing the Application

      Before we start the application, we’ll need to run migrations on our database and start Sidekiq to enable our workers. Redis should already be running on the server, but we can check to be sure. With all of these things in place, we’ll be ready to test the application.

      First, check that Redis is running:

      You should see output like the following:

      Output

      ● redis-server.service - Advanced key-value store Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2019-11-12 20:37:13 UTC; 1 weeks 0 days ago

      Next, run your database migrations:

      You can now start Sidekiq in the context of your current project bundle by using the bundle exec sidekiq command:

      You will see output like this, indicating that Sidekiq is ready to process jobs:

      Output

      m, `$b .ss, $$: .,d$ `$$P,d$P' .,md$P"' ,$$$$$b/md$$$P^' .d$$$$$$/$$$P' $$^' `"/$$$' ____ _ _ _ _ $: ,$$: / ___|(_) __| | ___| | _(_) __ _ `b :$$ ___ | |/ _` |/ _ |/ / |/ _` | $$: ___) | | (_| | __/ <| | (_| | $$ |____/|_|__,_|___|_|__|__, | .d$$ |_| 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: Running in ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux] 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: See LICENSE and the LGPL-3.0 for licensing details. 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: Booting Sidekiq 6.0.3 with redis options {:id=>"Sidekiq-server-PID-17621", :url=>nil} 2019-11-19T21:43:00.543Z pid=17621 tid=gpiqiesdl INFO: Starting processing, hit Ctrl-C to stop

      Open a second terminal window, navigate to the rails-sidekiq directory, and start your application server.

      If you are running the application locally, use the following command:

      If you are working with a development server, run the following:

      • bundle exec rails s --binding=your_server_ip

      Navigate to localhost:3000 or http://your_server_ip:3000 in the browser. You will see the following landing page:

      Sidekiq App Home

      Click on the Which Sharks Are in Danger? button. Since you have not uploaded any endangered sharks, this will take you to the endangered index view:

      Endangered Index View

      Click on Import Endangered Sharks to import the sharks. You will see a status message telling you that the sharks have been imported:

      Begin Import

      You will also see the beginning of the import. Refresh your page to see the entire table:

      Refresh Table

      Thanks to Sidekiq, our large batch upload of endangered sharks has succeeded without locking up the browser or interfering with other application functionality.

      Click on the Home button at the bottom of the page, which will bring you back to the application main page:

      Sidekiq App Home

      From here, click on Which Sharks Are in Danger? again. This will now take you directly to the data view, since you already uploaded the sharks.

      To test the delete functionality, click on the Delete Endangered Sharks button below the table. You should be redirected to the home application page once again. Clicking on Which Sharks Are in Danger? one last time will take you back to the index view, where you will have the option to upload sharks again:

      Endangered Index View

      Your application is now running with Sidekiq workers in place, which are ready to process jobs and ensure that users have a good experience working with your application.

      Conclusion

      You now have a working Rails application with Sidekiq enabled, which will allow you to offload costly operations to a job queue managed by Sidekiq and backed by Redis. This will allow you to improve your site’s speed and functionality as you develop.

      If you would like to learn more about Sidekiq, the docs are a good place to start.

      To learn more about Redis, check out our library of Redis resources. You can also learn more about running a managed Redis cluster on DigitalOcean by looking at the product documentation.



      Source link

      How To Add Bootstrap to a Ruby on Rails Application


      Introduction

      If you are developing a Ruby on Rails application, you may be interested in adding styles to your project to facilitate user engagement. One way to do this is by adding Bootstrap, an HTML, CSS, and JavaScript framework designed to simplify the process of making web projects responsive and mobile ready. By implementing Bootstrap in a Rails project, you can integrate its layout conventions and components into your application to make user interactions with your site more engaging.

      In this tutorial, you will add Bootstrap to an existing Rails project that uses the webpack bundler to serve its JavaScript and CSS assets. The goal will be to create a visually appealing site that users can interact with to share information about sharks:

      Application Landing Page

      Prerequisites

      To follow this tutorial, you will need:

      Step 1 — Cloning the Project and Installing Dependencies

      Our first step will be to clone the rails-stimulus repository from the DigitalOcean Community GitHub account. This repository includes the code from the setup described in How To Add Stimulus to a Ruby on Rails Application, which described how to add Stimulus.js to an existing Rails 5 project.

      Clone the repository into a directory called rails-bootstrap:

      • git clone https://github.com/do-community/rails-stimulus.git rails-bootstrap

      Navigate to the rails-bootstrap directory:

      In order to work with the project code, you will first need to install the project’s dependencies, which are listed in its Gemfile. Use the following command to install the required gems:

      Next, you will install your Yarn dependencies. Because this Rails 5 project has been modified to serve assets with webpack, its JavaScript dependencies are now managed by Yarn. This means that it’s necessary to install and verify the dependencies listed in the project’s package.json file.

      Run the following command to install these dependencies:

      • yarn install --check-files

      The --check-files flag checks to make sure that any files already installed in the node_modules directory have not been removed.

      Next, run your database migrations:

      Once your migrations have finished, you can test the application to ensure that it is working as expected. Start your server with the following command if you are working locally:

      If you are working on a development server, you can start the application with:

      • rails s --binding=your_server_ip

      Navigate to localhost:3000 or http://your_server_ip:3000. You will see the following landing page:

      Application Landing Page

      To create a new shark, click on the New Shark link at the bottom of the page, which will take you to the sharks/new route. You will be prompted for a username (sammy) and password (shark), thanks to the project’s authentication settings. The new view looks like this:

      Create New Shark

      To verify that the application is working, we can add some demo information to it. Input “Great White” into the Name field and “Scary” into the Facts field:

      Add Great White Shark

      Click on the Create Shark button to create the shark:

      Show Shark

      You have now installed the necessary dependencies for your project and tested its functionality. Next, you can make a few changes to the Rails application so that users encounter a main landing page before navigating to the shark information application itself.

      Step 2 — Adding a Main Landing Page and Controller

      The current application sets the root view to the main shark information page, the index view for the sharks controller. While this works to get users to the main application, it may be less desirable if we decide to develop the application in the future and add other capabilities and features. We can reorganize the application to have the root view set to a home controller, which will include an index view. From there, we can link out to other parts of the application.

      To create the home controller, you can use the rails generate command with the controller generator. In this case, we will specify that we want an index view for our main landing page:

      • rails generate controller home index

      With the controller created, you’ll need to modify the root view in the project’s config/routes.rb file — the file that specifies the application’s route declarations — since the root view is currently set to the sharks index view.

      Open the file:

      Find the following line:

      ~/rails-bootstrap/config/routes.rb

      . . . 
      root 'sharks#index'
      . . .
      

      Change it to the following:

      ~/rails-bootstrap/config/routes.rb

      . . . 
      root 'home#index'
      . . .
      

      This will set the home controller’s index view as the root of the application, making it possible to branch off to other parts of the application from there.

      Save and close the file when you are finished editing.

      With these changes in place, you are ready to move on to adding Bootstrap to the application.

      Step 3 — Installing Bootstrap and Adding Custom Styles

      In this step, you will add Bootstrap to your project, along with the tool libraries that it requires to function properly. This will involve importing libraries and plugins into the application’s webpack entry point and environment files. It will also involve creating a custom style sheet in your application’s app/javascript directory, the directory where the project’s JavaScript assets live.

      First, use yarn to install Bootstrap and its required dependencies:

      • yarn add bootstrap jquery popper.js

      Many of Bootstrap’s components require JQuery and Popper.js, along with Bootstrap’s own custom plugins, so this command will ensure that you have the libraries you need.

      Next, open your main webpack configuration file, config/webpack/environment.js with nano or your favorite editor:

      • nano config/webpack/environment.js

      Inside the file, add the webpack library, along with a ProvidePlugin that tells Bootstrap how to interpret JQuery and Popper variables.

      Add the following code to the file:

      ~/rails-bootstrap/config/webpack/environment.js

      const { environment } = require('@rails/webpacker')
      const webpack = require("webpack") 
      
      environment.plugins.append("Provide", new webpack.ProvidePlugin({ 
        $: 'jquery',
        jQuery: 'jquery',
        Popper: ['popper.js', 'default']
      }))  
      
      module.exports = environment
      

      The ProvidePlugin helps us avoid the multiple import or require statements we would normally use when working with JQuery or Popper modules. With this plugin in place, webpack will automatically load the correct modules and point the named variables to each module’s loaded exports.

      Save and close the file when you are finished editing.

      Next, open your main webpack entry point file, app/javascript/packs/application.js:

      • nano app/javascript/packs/application.js

      Inside the file, add the following import statements to import Bootstrap and the custom scss styles file that you will create next:

      ~/rails-bootstrap/app/javascript/packs/application.js

      . . . 
      import { Application } from "stimulus"
      import { definitionsFromContext } from "stimulus/webpack-helpers"
      
      import "bootstrap"
      import "../stylesheets/application"
      . . . 
      

      Save and close the file when you are finished editing.

      Next, create a stylesheets directory for your application style sheet:

      • mkdir app/javascript/stylesheets

      Open the custom styles file:

      • nano app/javascript/stylesheets/application.scss

      This is an scss file, which uses Sass instead of CSS. Sass, or Syntactically Awesome Style Sheets, is a CSS extension language that lets developers integrate programming logic and conventions like shared variables into styling rules.

      In the file, add the following statements to import the custom Bootstrap scss styles and Google fonts for the project:

      ~/rails-bootstrap/app/javascript/stylesheets/application.scss

      @import "~bootstrap/scss/bootstrap";
      @import url('https://fonts.googleapis.com/css?family=Merriweather:400,700');
      

      Next, add the following custom variable definitions and styles for the application:

      ~/rails-bootstrap/app/javascript/stylesheets/application.scss

      . . .
      $white: white;
      $black: black;
      
      .navbar {
              margin-bottom: 0;
              background: $black;
      }
      body {
              background: $black;
              color: $white;
              font-family: 'Merriweather', sans-serif;
      }
      h1,
      h2 {
              font-weight: bold;
      }
      p {
              font-size: 16px;
              color: $white;
      }
      a:visited {
              color: $black;
      }
      .jumbotron {
              background: #0048CD;
              color: $white;
              text-align: center;
              p {
                      color: $white;
                      font-size: 26px;
              }
      }
      .link {
              color: $white;
      }
      .btn-primary {
              color: $white;
              border-color: $white;
              margin-bottom: 5px;
      }
      .btn-sm {
              background-color: $white;
              display: inline-block;
      }
      img,
      video,
      audio {
              margin-top: 20px;
              max-width: 80%;
      }
      caption {
      
              float: left;
              clear: both;
      
      }
      

      Save and close the file when you are finished editing.

      You have added Bootstrap to your project, along with some custom styles. Now you can move on to integrating Bootstrap layout conventions and components into your application files.

      Step 4 — Modifying the Application Layout

      Our first step in integrating Bootstrap conventions and components into the project will be adding them to the main application layout file. This file sets the elements that will be included with each rendered view template for the application. In this file, we’ll make sure our webpack entry point is defined, while also adding references to a shared navigation headers partial and some logic that will allow us to render a layout for the views associated with the shark application.

      First, open app/views/layouts/application.html.erb, your application’s main layout file:

      • nano app/views/layouts/application.html.erb

      Currently, the file looks like this:

      ~/rails-bootstrap/app/views/layouts/application.html.erb

      <!DOCTYPE html>
      <html>
        <head>
          <title>Sharkapp</title>
          <%= csrf_meta_tags %>
          <%= csp_meta_tag %>
      
          <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
          <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
        </head>
      
        <body>
          <%= yield %>
        </body>
      </html>
      

      The code renders things like cross-site request forgery protection parameters and tokens for dynamic forms, a csp-nonce for per-session nonces that allows in-line script tags, and the application’s style sheets and javascript assets. Note that rather than having a javascript_link_tag, our code includes a javascript_pack_tag, which tells Rails to load our main webpack entry point at app/javascript/packs/application.js.

      In the <body> of the page, a yield statement tells Rails to insert the content from a view. In this case, because our application root formerly mapped to the index shark view, this would have inserted the content from that view. Now, however, because we have changed the root view, this will insert content from the home controller’s index view.

      This raises a couple of questions: Do we want the home view for the application to be the same as what users see when they view the shark application? And if we want these views to be somewhat different, how do we implement that?

      The first step will be deciding what should be replicated across all application views. We can leave everything included under the <header> in place, since it is primarily tags and metadata that we want to be present on all application pages. Within this section, however, we can also add a few things that will customize all of our application views.

      First, add the viewport meta tag that Bootstrap recommends for responsive behaviors:

      ~/rails-bootstrap/app/views/layouts/application.html.erb

      <!DOCTYPE html>
      <html>
        <head>
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Sharkapp</title>
          <%= csrf_meta_tags %>
          <%= csp_meta_tag %>
      . . .
      

      Next, replace the existing title code with code that will render the application title in a more dynamic way:

      ~/rails-bootstrap/app/views/layouts/application.html.erb

      <!DOCTYPE html>
      <html>
        <head>
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title><%= content_for?(:title) ? yield(:title) : "About Sharks" %></title>
          <%= csrf_meta_tags %>
          <%= csp_meta_tag %>
      . . .
      

      Add a <meta> tag to include a description of the site:

      ~/rails-bootstrap/app/views/layouts/application.html.erb

      <!DOCTYPE html>
      <html>
        <head>
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title><%= content_for?(:title) ? yield(:title) : "About Sharks" %></title>
          <meta name="description" content="<%= content_for?(:description) ? yield(:description) : "About Sharks" %>">
          <%= csrf_meta_tags %>
          <%= csp_meta_tag %>
      . . .
      

      With this code in place, you can add a navigation partial to the layout. Ideally, each of our application’s pages should include a navbar component at the top of the page, so that users can easily navigate from one part of the site to another.

      Under the <body> tag, add a <header> tag and the following render statement:

      ~/rails-bootstrap/app/views/layouts/application.html.erb

        <body>
          <header>
            <%= render 'layouts/navigation' %>
          </header>
      
          <%= yield %>
      . . .
      

      This <header> tag allows you to organize your page content, separating the navbar from the main page contents.

      Finally, you can add a <main> element tag and some logic to control which view, and thus which layout, the application will render. This code uses the content_for method to reference a content identifier that we will associate with our sharks layout in the next step.

      Replace the existing yield statement with the following content:

      ~/rails-bootstrap/app/views/layouts/application.html.erb

      . . . 
        <body>
          <header>
            <%= render 'layouts/navigation' %>
          </header>
          <main role="main">
          <%= content_for?(:content) ? yield(:content) : yield %>
          </main>
        </body>
      </html>
      

      Now, if the :content block is set, the application will yield the associated layout. Otherwise, thanks to the ternary operator, it will do an implicit yield of the view associated with the home controller.

      Once you have made these changes, save and close the file.

      With the application-wide layout set, you can move on to creating the shared navbar partial and the sharks layout for your shark views.

      Step 5 — Creating the Shared Partial and Specific Layouts

      In addition to the changes you made to the application layout in the previous Step, you will want to create the shared navbar partial, the sharks layout that you referenced in app/views/layouts/application.html.erb, and a view for the application landing page. You can also add Bootstrap styles to your application’s current link_to elements in order to take advantage of built-in Bootstrap styles.

      First, open a file for the shared navbar partial:

      • nano app/views/layouts/_navigation.html.erb

      Add the following code to the file to create the navbar:

      ~/rails-bootstrap/app/views/layouts/_navigation.html.erb

      <nav class="navbar navbar-dark navbar-static-top navbar-expand-md">
          <div class="container">
              <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
              </button> <%= link_to "Everything Sharks", root_path, class: 'navbar-brand' %>
              <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                  <ul class="nav navbar-nav mr-auto">
                  <li class='nav-item'><%= link_to 'Home', home_index_path, class: 'nav-link' %></li>
                  <li class='nav-item'><%= link_to 'Sharks', sharks_path, class: 'nav-link' %></li>  
      
                      </li>
                  </ul>
              </div>
          </div>
      </nav>
      

      This navbar creates a link for the application root using the link_to method, which maps to the application root path. The navbar also includes two additional links: one to the Home path, which maps to the home controller’s index view, and another to the shark application path, which maps to the shark index view.

      Save and close the file when you are finished editing.

      Next, open a file in the layouts directory for the sharks layout:

      • nano app/views/layouts/sharks.html.erb

      Before adding layout features, we will need to ensure that the content of the layout is set as the :content block that we reference in the main application layout. Add the following lines to the file to create the block:

      ~/rails-bootstrap/app/views/layouts/sharks.html.erb

      <% content_for :content do %>
      <% end %>
      

      The code we’re about to write in this block will be rendered inside the :content block in the app/views/layouts/application.html.erb file whenever a sharks view is requested by a controller.

      Next, inside the block itself, add the following code to create a jumbotron component and two containers:

      ~/rails-bootstrap/app/views/layouts/sharks.html.erb

      <% content_for :content do %>
          <div class="jumbotron text-center">
              <h1>Shark Info</h1>
          </div>
          <div class="container">
              <div class="row">
                  <div class="col-lg-6">
                      <p>
                          <%= yield %>
                      </p>
                  </div>
                  <div class="col-lg-6">
                      <p>
      
                          <div class="caption">You can always count on some sharks to be friendly and welcoming!</div>
                          <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
                      </p>
      
                  </div>
              </div>
          </div>
          <% end %>
      

      The first container includes a yield statement that will insert the content from the shark controller’s views, while the second includes a reminder that certain sharks are always friendly and welcoming.

      Finally, at the bottom of the file, add the following render statement to render the application layout:

      ~/rails-bootstrap/app/views/layouts/sharks.html.erb

      . . . 
                  </div>
              </div>
          </div>
          <% end %>
              <%= render template: "layouts/application" %>
      

      This sharks layout will provide the content for the named :content block in the main application layout; it will then render the application layout itself to ensure that our rendered application pages have everything we want at the application-wide level.

      Save and close the file when you are finished editing.

      We now have our partials and layouts in place, but we haven’t yet created the view that users will see when they navigate to the application home page, the home controller’s index view.

      Open that file now:

      • nano app/views/home/index.html.erb

      The structure of this view will match the layout we defined for shark views, with a main jumbotron component and two containers. Replace the boilerplate code in the file with the following:

      ~/rails-bootstrap/app/views/home/index.html.erb

      <div class="jumbotron">
          <div class="container">
              <h1>Want to Learn About Sharks?</h1>
              <p>Are you ready to learn about sharks?</p>
              <br>
              <p>
                  <%= button_to 'Get Shark Info', sharks_path, :method => :get,  :class => "btn btn-primary btn-lg"%>
              </p>
          </div>
      </div>
      <div class="container">
          <div class="row">
              <div class="col-lg-6">
                  <h3>Not all sharks are alike</h3>
                  <p>Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.
                  </p>
              </div>
              <div class="col-lg-6">
                  <h3>Sharks are ancient</h3>
                  <p>There is evidence to suggest that sharks lived up to 400 million years ago.
                  </p>
              </div>
          </div>
      </div>
      

      Now, when landing on the home page of the application, users will have a clear way to navigate to the shark section of the application, by clicking on the Get Shark Info button. This button points to the shark_path — the helper that maps to the routes associated with the sharks controller.

      Save and close the file when you are finished editing.

      Our last task will be to transform some of the link_to methods in our application into buttons that we can style using Bootstrap. We will also add a way to navigate back to the home page from the sharks index view.

      Open the sharks index view to start:

      • nano app/views/sharks/index.html.erb

      At the bottom of the file, locate the link_to method that directs to the new shark view:

      ~/rails-bootstrap/app/views/sharks/index.html.erb

      . . .
      <%= link_to 'New Shark', new_shark_path %>
      

      Modify the code to turn this link into a button that uses Bootstrap’s "btn btn-primary btn-sm" class:

      ~/rails-bootstrap/app/views/sharks/index.html.erb

      . . .
      <%= link_to 'New Shark', new_shark_path, :class => "btn btn-primary btn-sm" %>
      

      Next, add a link to the application home page:

      ~/rails-bootstrap/app/views/sharks/index.html.erb

      . . .
      <%= link_to 'New Shark', new_shark_path, :class => "btn btn-primary btn-sm" %> <%= link_to 'Home', home_index_path, :class => "btn btn-primary btn-sm" %>
      

      Save and close the file when you are finished editing.

      Next, open the new view:

      • nano app/views/sharks/new.html.erb

      Add the button styles to the link_to method at the bottom of the file:

      ~/rails-bootstrap/app/views/sharks/new.html.erb

      . . . 
      <%= link_to 'Back', sharks_path, :class => "btn btn-primary btn-sm" %>
      

      Save and close the file.

      Open the edit view:

      • nano app/views/sharks/edit.html.erb

      Currently, the link_to methods are arranged like this:

      ~/rails-bootstrap/app/views/sharks/edit.html.erb

      . . . 
      <%= link_to 'Show', @shark %> |
      <%= link_to 'Back', sharks_path %>
      

      Change their arrangement on the page and add the button styles, so that the code looks like this:

      ~/rails-bootstrap/app/views/sharks/edit.html.erb

      . . . 
      <%= link_to 'Show', @shark, :class => "btn btn-primary btn-sm" %> <%= link_to 'Back', sharks_path, :class => "btn btn-primary btn-sm" %>
      

      Save and close the file.

      Finally, open the show view:

      • nano app/views/sharks/show.html.erb

      Find the following link_to methods:

      ~/rails-bootstrap/app/views/sharks/show.html.erb

      . . . 
      <%= link_to 'Edit', edit_shark_path(@shark) %> |
      <%= link_to 'Back', sharks_path %>
      . . . 
      

      Change them to look like this:

      ~/rails-bootstrap/app/views/sharks/show.html.erb

      . . . 
      <%= link_to 'Edit', edit_shark_path(@shark), :class => "btn btn-primary btn-sm" %> <%= link_to 'Back', sharks_path, :class => "btn btn-primary btn-sm" %>
      . . .
      

      Save and close the file.

      You are now ready to test the application.

      Start your server with the appropriate command:

      • rails s if you are working locally
      • rails s --binding=your_server_ip if you are working with a development server

      Navigate to localhost:3000 or http://your_server_ip:3000, depending on whether you are working locally or on a server. You will see the following landing page:

      Application Landing Page

      Click on Get Shark Info. You will see the following page:

      Sharks Index Page

      You can now edit your shark, or add facts and posts, using the methods described in How To Add Stimulus to a Ruby on Rails Application. You can also add new sharks to the conversation.

      As you navigate to other shark views, you will see that the shark layout is always included:

      Sharks Show Page

      You now have Bootstrap integrated into your Rails application. From here, you can move forward by adding new styles and components to your application to make it more appealing to users.

      Conclusion

      You now have Bootstrap integrated into your Rails application, which will allow you to create responsive and visually appealing styles to enhance your users’ experience of the project.

      To learn more about Bootstrap features and what they offer, please see the Bootstrap documentation. You can also look at the documentation for Sass, to get a sense of how you can use it to enhance and extend your CSS styles and logic.

      If you are interested in seeing how Bootstrap integrates with other frameworks, please see How To Build a Weather App with Angular, Bootstrap, and the APIXU API. You can also learn about how it integrates with Rails and React by reading How To Set Up a Ruby on Rails Project with a React Frontend.



      Source link