Skip to content

Instantly share code, notes, and snippets.

@coderhs
Last active June 10, 2018 13:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coderhs/39b4606123c0e0450ac8c3294d11644d to your computer and use it in GitHub Desktop.
Save coderhs/39b4606123c0e0450ac8c3294d11644d to your computer and use it in GitHub Desktop.

Instructions

Setup the new rails project

  1. rails new docVault
  2. cd docValue
  3. bundle
  4. git add .
  5. git commit -m "Initial Commit"

run bundle exec rails s in another tab and keep it running

Setup User Management

  1. bundle exec rails g controller Home index
  2. Add devise gem to Gemfile. gem 'devise'
  3. bundle
  4. bundle exec rails generate devise:install
  5. Follow the post install instruction
  6. rails generate devise User
  7. bundle exec rails db:migrate
  8. bundle exec rails g devise:views
  9. To make all pages not accessible unles a user logs in place before_action :authenticate_user! in the application_controller.rb

Add Bootstrap for better layout

  1. Add CDN from https://getbootstrap.com/docs/4.1/getting-started/introduction/ to the app/views/layouts/application.html.erb
  2. In application.html.erb move the JS code toward the end of the file for better performance.
  3. Replace the layout with this basic starter layout: https://getbootstrap.com/docs/4.1/examples/starter-template/
  4. Add logout user to this page
    1. Find the route to sign out by visiting http://localhost:3000/rails/info/routes
    2. place in the top nav the following code <%= link_to "Log Out", destroy_user_session_path, method: :delete, class: 'nav-link' %>

Document Model

  1. bundle exec rails g model Document
  2. Set the following details in migration file with reference to the user field
class CreateDocuments < ActiveRecord::Migration[5.2]
  def change
    create_table :documents do |t|
      t.string :title
      t.string :content
      t.integer :user_id

      t.timestamps
    end
  end
end
  1. bundle exec rails db:migrate
  2. Set the relationship between user and document
# user.rb
  has_many :documents, dependent: :destroy
  
# document.rb
  belongs_to :user
  1. Set valiation. Ensure content and title exists on create but doesn't on update
# document.rb
  validates :title, presence: true
  validates :content, presence: true, on: :create

Frontent Index, forms, etc

  1. bundle exec rails g controller Documents index new edit
  2. Add to routes.rb, resources :documents
  3. Integrate TinyMCE, by adding the following code to the bottom of application.html.erb
      <script src="https://cloud.tinymce.com/stable/tinymce.min.js"></script>
      <script>tinymce.init({ selector:'textarea' });</script>
    
  4. Add the files as below
    1. documents_controller.rb
    class DocumentsController < ApplicationController
      def index
        @documents = current_user.documents.order("updated_at desc")
      end
    
      def new
        @document = current_user.documents.new
      end
    
      def create
        document = DocumentSaveService.new(document_params, current_user)
        if document.save
          redirect_to documents_path, notice: 'Created Successfully'
        else
          @document = document.object
          flash[:alert] = @document.errors.full_messages.to_sentence
          render 'new'
        end
      end
    
      def edit
        @document = current_user.documents.find(params[:id])
      end
    
      def update
        @document = current_user.documents.find(params[:id])
        if @document.update(document_params)
          redirect_to edit_document_path(@document), notice: 'Updated'
        else
          flash[:alert] = @document.errors.full_messages.to_sentence
          render 'new'
        end
      end
    
      private
    
      def document_params
        params.require(:document).permit(:title, :content)
      end
    end
    1. app/services/document_save_service.rb (this folder is not there in rails you have to make it, also since its a new folder we have to restart the rails server).
    class DocumentSaveService
      def initialize(params, user)
        @params = params
        @user = user
        @object = @user.documents.new(params)
      end
    
      def save
        @object.title = "Untitled" if @object.title.blank?
        @object.save
      end
    
      def object
        @object
      end
    end
    1. app/views/documents/index.html.erb
    <table class="table">
      <thead class="thead-dark">
        <tr>
          <th scope="col" style="width: 55%">Title</th>
          <th scope="col">Created at</th>
          <th scope="col">Updated at</th>
        </tr>
      </thead>
      <tbody>
        <% @documents.each do |document| %>
          <tr>
            <td><center><%= link_to document.title, edit_document_path(document) %></center></td>
            <td><%= document.updated_at.strftime("%-l:%M %p %b #{document.updated_at.day.ordinalize}, %Y") %></td>
            <td><%= document.created_at.strftime("%-l:%M %p %b #{document.created_at.day.ordinalize}, %Y") %></td>
          </tr>
        <% end %>
      </tbody>
    </table>
    1. edit.html.erb
       <h1> Edit Note </h1>
    
       <%= render 'form' %>
    1. new.html.erb
       <h1> Add Note </h1>
    
       <%= render 'form' %>
    1. _form.html.erb
       <%= form_for @document do |f| %>
         <div class="form-group">
           <%= f.label :title %>
           <%= f.text_field :title, class: 'form-control' %>
           <small id="emailHelp" class="form-text text-muted">What best defines your note.</small>
         </div>
    
         <div class="form-group">
           <%= f.text_area :content, class: 'form-control' %>
         </div>
    
         <%= f.submit 'Save', class: 'btn btn-success' %>
       <% end %>
  5. finally make your home redirect to documents#index by setting root to documnets#index in routes.rb
      root to: 'documents#index'
  6. To make the alert and notice banner looks nice, change the notice and alerts lines in your application.html.erb into this:
        <% if notice %>
         <p class="alert alert-success"><%= notice %></p>
        <% end %>
        <% if alert %>
         <p class="alert alert-danger"><%= alert %></p>
        <% end %>

Admin Panel

We are using Active Admin gem to create the admin pannel https://activeadmin.info

  1. Add gem 'activeadmin' to the Gemfile
  2. bundle (After bundle you need to restart your rails server)
  3. bundle exec rails generate active_admin:install
  4. bundle exec rails db:seed (this is to load the default username and password of admin).
  5. You can now login through the URL: http://localhost:3000/admin
  6. To create a page to view users
    1. Create a file called users.rb under app/admin
    2. place the following code in the file
       ActiveAdmin.register User do
         permit_params :email, :password, :password_confirmation
    
         index do
           selectable_column
           id_column
           column :email
           column("No of Document") { |user| user.documents.count }
           column :current_sign_in_at
           column :sign_in_count
           column :created_at
           actions
         end
    
         filter :email
         filter :current_sign_in_at
         filter :sign_in_count
         filter :created_at
    
         form do |f|
           f.inputs do
             f.input :email
             f.input :password
             f.input :password_confirmation
           end
           f.actions
         end
       end
  7. Create a page in admin panel to manage Documents
    1. Create a file called documents.rb under app/admin
    2. place the following code in the file
       ActiveAdmin.register Document do
    
         index do
           selectable_column
           id_column
           column :title
           column("User Email") { |document| document.user.email }
           column :created_at
           column :updated_at
           actions
         end
       end

Pushing to production

  1. Create an account at Heroku.com
  2. Create an app at heroku with any name
  3. add gem 'pg' to the Gemfile
  4. backup the existing database.yml -> database.yml.sqlite3
  5. create a new database.yml file vim config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: localhost
  pool: 5
  timeout: 5000
  username: postgres
  password: postgres123

development:
  <<: *default
  database: doc_vault_development

test:
  <<: *default
  database: doc_vault_test

staging:
  <<: *default
  database: <%= ENV['STAGING_DB_NAME'] %>
  username: <%= ENV['STAGING_USERNAME'] %>
  password: <%= ENV['STAGING_PASSWORD'] %>
  host: <%= ENV['STAGING_HOSTNAME'] %>
  port: <%= ENV['STAGING_PORT'] %>

production:
  <<: *default
  database: <%= ENV['DB_NAME'] %>
  username: <%= ENV['USERNAME'] %>
  password: <%= ENV['PASSWORD'] %>
  host: <%= ENV['HOSTNAME'] %>
  port: <%= ENV['PORT'] %>
  1. Uncomment config.secret_key in config/initializers/devise.rb
  2. We need to add all the code to git
    1. git add .
    2. git commit -m 'Push to production'
  3. follow the instructions mention in heroku setup
  4. heroku run rails db:migrate
  5. To create an admin user in production
    1. run heroku run rails console
    2. AdminUser.create(email: '<email you want>', password: '<your password>', password_confirmation: '<your password>')

Your app should be live now :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment