Skip to content
By reinteractive

Spree: Adding Custom Admin Tabs For New Resource

by Suman Awal

Spree is one of the most popular open-source eCommerce platforms build with Ruby on Rails. Spree is popular for it's modularity and flexibility in building and managing the store.


Spree provides a robust and clean admin interface to manage the commerce and different resource although it might need to manage the new resource by admin. In order to manage the new resource by admin user, there needs to create a Admin Tabs/Menu. Here we will learn how to create a Admin Tabs/Menu for the new resources.

Deface for adding Tab

Deface is a library that allow to customize HTML (Erb, Haml, Slim) views in Rails application without editing the underlying view.

Adding New Resource

Let's add a new resource called Subscription and allow an admin user to perform CRUD operations on a subscription.

Create a model and migration file.

rails generate migration CreateSubscriptions

# above command will create a file with this content in your db/migrate folder

class CreateSubscriptions < ActiveRecord::Migration[6.1]
  def change
    create_table :spree_subscriptions do |t|
      t.string :name
      t.integer :duration_in_month
      t.integer :status, null: false, default: 0

Execute rake db:migrate to create the table in database and updates the schema.rb.

Create a model.

# app/models/subscription.rb

module Spree
  class Subscription < ApplicationRecord
    scope :active, -> { where(status: :active) }
    enum status: { inactive: 0, active: 1 }

Create a admin tab using deface.

# app/overrides/admin_subscription.rb
  name: 'subscription_tab',
  virtual_path: 'spree/admin/shared/_main_menu',
  insert_after: '#sidebarProduct',
  partial: 'spree/admin/shared/subscription_menu'

Subscription Menu Partial

# app/views/spree/admin/shared/subscription_menu.html.erb

<% if can? :manage, Spree::Subscription %>
  <ul class="nav nav-sidebar border-bottom" id="sidebarSubscriptions">
    <%= tab 'Subscriptions', icon: "icon.svg", sub_menu: "services", url: "admin_subscriptions_path" %>
<% end %>

Routes and Controllers

# config/routes.rb

Spree::Core::Engine.routes.draw do
  namespace :admin do
    resources :subscriptions

# app/controllers/spree/admin/subscriptions_controller.rb

module Spree
  module Admin
    # Aside from index, using the inherited actions as they are sufficient.
    class SubscriptionsController < Spree::Admin::ResourceController
      def index
        @subscriptions =


# app/views/spree/admin/subscriptions/index.html.erb

<% content_for :page_title do %>
<% end %>

<% if can? :manage, Spree::Subscriptions %>
  <% content_for :page_actions do %>
    <%= button_link_to 'New Subscription', new_admin_subscription_path, class: 'btn-success', icon: 'add.svg', id: 'new-admin-subscription' %>
  <% end %>
<% end %>

<table class="table sortable" data-hook="subscriptions_table" data-sortable-link="<%= update_positions_admin_subscriptions_url %>">
    <tr data-hook="subscriptions_header">
      <th class="actions"></th>
    <% @subscriptions.each do |subscription| %>
      <tr id="<%= spree_dom_id subscription %>" data-hook="subscriptions_row">
        <td><%= %></td>
        <td><%= subscription.duration_in_month %> month</td>
        <td><%= subscription.status %></td>

        <td class="actions actions-2 text-right">
          <%= link_to_edit subscription, no_text: true, class: 'edit' if can?(:edit, subscription) %>
          <!-- Add translation icon support -->
          <%= link_to_with_icon 'translate',
                                title: Spree.t(:'i18n.translations'),
                                class: 'btn btn-sm btn-primary' if defined? (SpreeGlobalize)%>
    <% end %>

# app/views/spree/admin/subscriptions/_form.html.erb

<%= render partial: 'spree/admin/shared/error_messages', locals: { target: @subscription } %>

<div class="form-group">
  <%= form_for [:admin, @object] do |form| %>
    <%= f.field_container :name do %>
      <%= f.label :name, 'Name' %>
      <%= f.text_field :name, required: true %>
    <% end %>
    <%= f.field_container :duration_in_month do %>
      <%= f.label :duration_in_month, 'Duration In Month' %>
      <%= f.text_field, :duration_in_month, required: true %>
    <% end %>
    <%= f.field_container :status do %>
      <%= f.label :status %>
      <%= f.radio_button :status, :active %>
      <%= f.label :status, 'Active', :value => :active %>
      <%= f.radio_button :status, :inactive %>
      <%= f.label :status, 'Inactive', :value => :inactive %>
    <% end %>

    <div class="form-actions" data-hook="buttons">
      <%= button (@object.persisted? ? Spree.t('actions.update') : Spree.t('actions.create')), 'save.svg' %>
      <span class="or"><%= Spree.t(:or) %></span>
      <%= button_link_to Spree.t('actions.cancel'), admin_subscriptions_path, icon: "cancel.svg" %>
  <% end %>

# app/views/spree/admin/new.html.erb

<% content_for :page_title do %>
  <%= link_to plural_resource_name(Spree::Subscription), spree.admin_subscriptions_url %> /
  New Subscription
<% end %>

<%= form_for [:admin, @subscription] do |f| %>
    <%= render partial: 'form', locals: { f: f } %>
    <%= render partial: 'spree/admin/shared/new_resource_links' %>
<% end %>

# app/views/spree/admin/edit.html.erb

<% content_for :page_title do %>
  <%= link_to plural_resource_name(Spree::Subscription), spree.admin_subscriptions_url %> /
  <%= %>
<% end %>

<%= form_for [:admin, @subscription] do |f| %>
    <%= render partial: 'form', locals: { f: f } %>
    <%= render partial: 'spree/admin/shared/edit_resource_links' %>
<% end %>

That's it! Once the above is in place, restart your app for good measure and you will see a "Subscriptions" menu in your admin area. From there, you'll have control over your Subscription records.

Popular Articles by Our Team

Our expert team of designers and developers love what the do and enjoy sharing their knowledge with the world.

We Hire Only the Best

reinteractive is Australia’s largest dedicated Ruby on Rails development company. We don’t cut corners and we know what we are doing.

We are an organisation made up of amazing individuals and we take pride in our team. We are 100% remote work enabling us to choose the best talent no matter which part of the country they live in. reinteractive is dedicated to making it a great place for any developer to work.

Free Community Workshops

We created the Ruby on Rails InstallFest and Ruby on Rails Development Hub to help introduce new people to software development and to help existing developers hone their skills. These workshops provide invaluable mentorship to train developers, addressing key skills shortages in the industry. Software development is a great career choice for all ages and these events help you get started and skilled up.

  • Webinars


    Webinars are our online portal for tips, tricks and lessons learned in everything we do. Make the most of this free resource to help you become a better developer.

    Learn more about webinars

  • Installfest


    The Ruby on Rails Installfest includes a full setup of your development environment and step-by-step instructions on how to build your first app hosted on Heroku. Over 1,800 attendees to date and counting.

    Learn more about Installfest

  • Development Hub

    Development Hub

    The Ruby on Rails Development Hub is a monthly event where you will get the chance to spend time with our team and others in the community to improve and hone your Ruby on Rails skills.

    Learn more about Development Hub

Get the “reinteractive Review” Monthly Email