项目作者: lkcbharath

项目描述 :
Complaint Management system as per the requirements stated in the README.
高级语言: Ruby
项目地址: git://github.com/lkcbharath/RoR-ComplaintManagement.git
创建时间: 2018-12-27T11:35:56Z
项目社区:https://github.com/lkcbharath/RoR-ComplaintManagement

开源协议:

下载


RoR-ComplaintManagement

  • After cloning, to run the application, type the following in a terminal opened at the root of it:

    1. bundle install
    2. rake db:create
    3. rake db:migrate
    4. rails s

    and you will be able to see the application in action.

Objectives:

The objectives of this project are:

  1. User authentication with 1 admin user.

  2. Accept complaints from all users.

  3. Allow admin (with special privileges) to update the status of complaint from pending, to processing and complete.

  4. The person who created the complaint should be finally able to close the complaint after resolution.

  5. Make 2 different dashboards for normal users and resolving authorities.

  6. Now add validations to check if complaint title is not empty. As told it should do frontend as well as model validation.

  7. Also modify the authentication to ask for name also while creating a account. You will have to add column in database and modify the controllers of devise also.

Creating the application:

  • Create the application with the name ComplaintManagement using the MySQL database with the command:

    rails create new ComplaintManagement -d mysql

  • Navigate to the folder and then generate a scaffold to generate the MVC for a resource with name as Complaint, and three fields being the Name, Title and Details using:

    rails g scaffold Complaint name:string title:string details:text

  • Change the default route of the application in config/routes.rb:

    1. root "complaints#index"
  • For authentication, add the gem ‘devise’ to the Gemfile.

  • Each time a gem is added, remember to execute

    bundle install

  • Install all necessary components needed for devise by:

    rails generate devise:install

  • Using devise, the resource and corresponding MVC for the user are first created by the command:

    rails generate devise User

  • IMPORTANT: In newer versions of devise, it abstracts some functionality of ORM. To fix it, allow the User model (app/models/user.rb) to extend the Models Class from Devise:

    1. class User < ApplicationRecord extend Devise::Models
  • Finally, perform the migrations, then generate views for the User resource:

    1. rake db:migrate
    2. rails generate devise:views
  • Using devise, the model & views for the user are created by:

  • To authenticate users on opening any page of the application, add this filter to the Complaints controller (controllers/complaint_controllers.rb)

    1. before_action :authenticate_user!
  • Add the gems ‘bootstrap-sass’ & ‘jquery-rails’ to the Gemfile to generate a list of routes for easier modification.

  • Modify the main HTML page, i.e. app/layouts/application.html.erb to display options for logging in and out, and account details:

    1. <!--...-->
    2. <body>
    3. <header class="navbar navbar-fixed-top navbar-inverse">
    4. <div class="container">
    5. <nav>
    6. <ul class="nav navbar-nav navbar-right">
    7. <li><%= link_to "Home", root_path , class: "btn "%></li>
    8. <% if user_signed_in? %>
    9. <li><%= link_to "Account", edit_user_registration_path, class: "btn " %></li>
    10. <li>
    11. <%= link_to('Logout', destroy_user_session_path, method: :delete) %>
    12. </li>
    13. <% else %>
    14. <li><%= link_to "Sign Up", new_user_registration_path, class: "btn " %></li>
    15. <li><%= link_to "Sign In", new_user_session_path, class: "btn " %></li>
    16. <% end %>
    17. </ul>
    18. </nav>
    19. </div>
    20. </header>
    21. <!--...-->
  • To uniquely identify each user, perform the migration

    rails generate migration add_column_user_id_to_complaints user_id:integer

  • To let a user associate with multiple complaints, modify the User model (app/model/user.rb) to include the line

    1. has_many :complaints
  • Each complaint is tied to a single user and is validated by adding these lines to the Complaint model:

    1. belongs_to :user
    2. validates_presence_of :user
  • Update the Complaint controller to show only the user’s complaints in his dashboard (the Index):

    1. def index
    2. @complaints = Complaint.where(:user_id => current_user.id)
    3. end
  • Associate each complaint with the user ID on creation in the Complaint controller method:

    1. def create
    2. @complaint = Complaint.new(complaint_params)
    3. @complaint.user_id = current_user.id
    4. respond_to do |format|
    5. #...
    6. end

Objective 1:

  • Add a boolean attribute ‘admin’ to every user by first:

    • Generating the migration:

      rails g migration add_column_admin_to_user admin:boolean

    • Before migrating, modify the migration to set the default value of the ‘admin’ attribute as False, then perform the migration:

      1. add_column :users, :admin, :boolean, default: false
    • Finally using the Rails console (rails c), set a particular user to be the Administrator (or Admin) by updating the attribute ‘admin’ to True:

      1. user = User.first (or any user of your choice)
      2. user.admin = True
      3. user.save

      If no user has been created already, do so and set it to be the Admin.

    • To test if a user is an admin, use the method

      1. current_user.try(:admin?)

Objective 2:

  • The objective is implicitly achieved i.e. all users can make a complaint by default.

Objective 3 & 4:

  • First generate a migration to add an attribute ‘status’ to every complaint:

    rails g migration add_column_status_to_complaint status:string

  • Modify the migration to set the default value of ‘status’ to “Pending”,

    1. add_column :complaints, :status, :string, default: 'Pending'

    then perform the migration.

  • To check for the value of status, add these methods to the Complaint model:

    1. def processing?
    2. status == "Processing"
    3. end
    4. def pending?
    5. status == "Pending"
    6. end
    7. def complete?
    8. status == "Complete"
    9. end
  • Define a new Complaint controller to update the status according to the specifications (using the PATCH method), and validate it against the user:

    1. def update_status
    2. new_status = @complaint.new_status(current_user)
    3. @complaint.update_attribute(:status, new_status)
    4. redirect_to @complaint, notice: "Marked as " + new_status
    5. end
  • Define a new function in the Complaint model to return the new status to update in the method above:

    1. def new_status(current_user)
    2. new_status = status
    3. if current_user.try(:admin?)
    4. if pending?
    5. new_status = 'Processing'
    6. elsif processing?
    7. new_status = 'Complete'
    8. end
    9. elsif id == current_user.id && complete?
    10. new_status = 'Resolved'
    11. end
    12. return new_status
    13. end
  • To use the updated model and controller (also to differentiate between the User and Admin dashboards), edit the Index view (index.html.erb) to the following:

    1. <!--...-->
    2. <td><%= link_to 'Delete', complaint, method: :delete, data: { confirm: 'Are you sure?' } %></td>>
    3. <!--...-->
    4. <% if current_user.try(:admin?) %>
    5. <% if complaint.pending? %>
    6. <td><%= link_to 'Mark as Processing', update_status_complaint_path(complaint), method: :patch %></td>
    7. <% elsif complaint.processing? %>
    8. <td><%= link_to 'Mark as Complete', update_status_complaint_path(complaint), method: :patch %></td>
    9. <% end %>
    10. <% else %>
    11. <% if complaint.pending? %>
    12. <td>Pending</td>
    13. <% elsif complaint.complete? %>
    14. <td><%= link_to 'Mark as Resolved', update_status_complaint_path(complaint), method: :patch %></td>
    15. <% end %>
    16. <% end %>
    17. <!--...-->
  • Add the corresponding method in the routes.rb file:

    1. #...
    2. resources :complaints do
    3. member do
    4. patch :update_status
    5. end
    6. end
    7. #...

Objective 5:

  • For different dashboards (i.e. identify users and the Admin seperately), modify the main application header (in application.html.erb) to match the following:

    1. <!--...-->
    2. <header class="navbar navbar-fixed-top navbar-inverse">
    3. <div class="container">
    4. <% if current_user.try(:admin?) %>
    5. ADMIN DASHBOARD
    6. <% elsif current_user %>
    7. <%= current_user.name %>'s dashboard
    8. <% end %>
    9. <nav>
    10. <!--...-->
  • The methods current_user.try(:admin?) and current_user can be used to check if the user is signed in and is an Admin or a regular user, for further UI improvements (check the modified Index & Show Views for an example).


Objective 6:

Disclaimer: This approach (specifically the JS function and HTML+ERB form) is not fully DRY due to issues I’ve run into with jQuery and Rails.

  • To validate the title from the server-side (Model validation), add this line to the Complaint model:

    1. validates :title, presence: true
  • For client-side validation (View validation), first update app/assets/javascripts/application.js to include these three lines (before //= require_tree .)

    1. //= require jquery
    2. //= require jquery_ujs
    3. //= require bootstrap.min
  • Then, in that folder, create a new JavaScript file inline_validation.js with the following contents:

    1. function changeHandler() {
    2. var complaint_title = $("#complaint_title").val();
    3. var user_name = $("#user_name").val();
    4. if (complaint_title || user_name ){
    5. $("input[type=submit]").removeAttr("disabled");
    6. } else {
    7. $("input[type=submit]").attr("disabled", "disabled");
    8. }
    9. }
  • Modify the form to match the following:

    1. <!--...-->
    2. <div class="field">
    3. <%= form.label :title %>
    4. <%= form.text_field :title, onkeyup: "changeHandler()" %>
    5. </div>
    6. <!--...-->
    7. <div class="actions">
    8. <%= form.submit id: "complaint_submit", disabled: "disabled" %>
    9. </div>
    10. <!--...-->

Objective 7:

  • Add the following field above the email field in layouts/devise/new.html.erb and layouts/devise/edit.html.erb:

    1. <div class="field">
    2. <%= f.label :name %><br />
    3. <%= f.text_field :name, autofocus: true %>
    4. </div>

    Also remove the ‘autofocus’ attribute from the email field.

  • Generate the User registration controller by the following command:

    rails generate devise:controllers users -c=registrations

  • Navigate to controllers/users/registrations_controller.rb and override the parameters to include a name by adding the following lines:

    1. def sign_up_params
    2. params.require(:user).permit(:name, :email, :password, :password_confirmation)
    3. end
    4. def account_update_params
    5. params.require(:user).permit(:name, :email, :password, :password_confirmation, :current_password)
    6. end
  • To use this new controller as the User registrations controller, add it as a route to routes.rb:

    1. devise_for :users, controllers: { registrations: 'users/registrations' }
  • In the User model, to perform server-side validation, add the line

    1. validates :name, presence: true
  • For client-side validation, modify the text fields and the submit button by following the proceedure outlined in Objective 6.