Chapter 13

Contacts Exercise: Extending the Admin Panel

Not sure if you noticed, but we didn’t touch the admin panel in this module, even though we probably should have. There are three things that we should add:

  1. We need an admin contacts controller, just like the one we created for users. The complete list of contacts should be accessible for admins only at /admin/contacts.
  2. We want a link to the list of contacts we just created. We need to add this link to the admin navigation menu.
  3. We should show the last 3 created contacts in the admin dashboard, just like what we did for the last 3 users.

The good news is that we’re not going to show you how to do it. We want you to try it on your own, using what you’ve learned in this chapter. Don’t worry though, we’re not going to let you swim in the deep end with no help; we’ll give you the steps to follow, but you’ll have to write the code yourself. We’ll even throw in a few screenshots!

Here are the steps:

  1. Create a new branch (Chapter-13)
  2. Create a contacts admin controller, an index view and the admin routes (Hint: don’t forget to add the ordered scope to the Contacts Model)
  3. Create the AdminController decorator
  4. Add a hook in the admin navigation (Hint: it’s in the Core module) and its override
  5. Add the Contacts link in the Admin navigation
  6. Add a hook in the admin index view and its override
  7. Add the override view with the Contacts list
Figure 1: The Contacts list in the Admin Panel
Figure 2: The Contacts summary in the Admin Dashboard

Good luck!

Box 13.1. Something wonky with the user count

Because we know how good you are, we know that you would have noticed something funny happening with the user count: When clicking on the “Contacts” link, you would’ve noticed that the user count is blank, as shown in Figure 3 below:
Figure 3: Blank user count

This is because in the AdminController, the user count is only updated in this index action of this controller and not that of any other, like the ContactsController. To fix this, we will have to move the .count method into a before_action, as show below:

Listing 0.1: Moving the user count to a beforeaction engines/core/apps/controllers/blast/admin/admin_controller.rb
module Blast
  module Admin
    class AdminController < ApplicationController
      before_action :set_user_count, only: :index

      def index
        authorize [:blast, :admin], :index?
        @users = policy_scope(Blast::User).ordered.limit(3)


        def set_user_count
          @users_count = policy_scope(Blast::User).count

13.1. Pushing Our Changes

Don’t forget to push your changes to GitHub.

  1. Check the changes:
    git status
  2. Stage them:
    git add .
  3. Commit them:
    git commit -m "Extending the Admin Panel"
  4. Push to your GitHub repo if you’ve configured it:
    git push origin Chapter-13

13.2. Wrap Up

We finally reached the end of this module. Let’s go over everything we’ve learned!

13.2.1. What did we learn?

In this chapter, we learned everything about extending anything! We used decorators to extend Models, Controllers and Views.

We built our first feature module on top of the Core module we created in the last module: the Contacts module.

First, we created the Contact model, its associated controller and its views. Then things got interesting: we extended the Core views to add some info about the contacts, and we also had to extend the Core models to achieve our desired result. Finally, to remove some logic from the views, we also extended the Core controller.

13.2.2. Main points to remember

  • Anything can be extended, but you need to keep it clean and organized
  • Deface is a great gem to extend views with the use of overrides
  • Adding the routes to the Core routes makes it easier to use them in all our engines (by calling blast.my_path)

13.2.3. Next Step

In the next module, we’re going to build a new feature module: Tasks. With this module, a user will be able to create tasks and link them to a contact. We’ll re-use what we learned in this chapter, but also talk about how we can keep the Contacts module and the Tasks module independent.