I faced this challenge when working on a Rails 6 application.
I had two types of users: Customers and Admins. I was using the Devise gem for authentication. I wanted the Products views for the Customer to be different from the Admins View.
I already had an app/controllers/admins
directory in the controllers for the Devise configuration for Admins.
Here's how I did it:
First, define a new route for the Admins products
view using the admins
namespace.
namespace :admins do
resources :products do
end
end
Note: This will affect the Paths/URLs for the Admins. Say, the products_path
will not be admins_products_path
.
Then, in the controllers add the products_controller.rb
to the app/controllers/admins
directory:
class Admins::ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
@products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
@product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
@product = Product.new(product_params)
respond_to do |format|
if @product.save
format.html { redirect_to admins_product_path(@product), notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: admins_product_path(@product) }
else
format.html { render :new }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if @product.update(product_params)
format.html { redirect_to admins_product_path(@product), notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: admins_product_path(@product) }
else
format.html { render :edit }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
@product.destroy
respond_to do |format|
format.html { redirect_to admins_products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
@product = Product.find(params[:id])
end
# Only allow a list of trusted parameters through.
def product_params
params.require(:product).permit(:name, :sku, :short_description, :full_description)
end
end
Note: Take note of the ProductsController namespacing using the Admins Module and the modified paths in the create
, update
and destroy
actions od the
And finally, in the views, add the views associated with the Admins Products in the app/views/admins/products
directory.
Note: You may have to modify the paths in the views to correspond with the routes for the admins products. Say, the show
view for admins products will be admins_product_path(product)
and not product
or product_path(product)
.
There is a cleaner approach using the cells gem. This eliminates the need to duplicate code, and it comes in handy when you need to define views for up to 3 or more roles. You can read up more about how to use it here: Object-Oriented Views in Rails.
That's all.
I hope this helps