DEV Community

Discussion on: Ruby on Rails API with Vue.js

Collapse
andrewbrown profile image
Andrew Brown 🇨🇦

A Suggestion About Controllers

I would suggest the following refactors:

  • namespacing on one line
  • create an inherit for a base controller for future namespaces
  • use %w for shorter sytnax
  • name the instance models as model so you have more agitiliy with future renaming
  • use fetch instead of require
class Api::V1::ArtistsController < Api::V1::BaseController
  before_action :find_model, only: %w(show update destroy)

  def index
    @artists = Artist.all
    render json: @artists
  end

  def show
    render json: @artist
  end

  def create
    @artist = Artist.new(params_model)
    if @artist.save
      render json: @artist, status: :created
    else
      render json: @artist.errors, status: :unprocessable_entity
    end
  end

  def update
    if @artist.update(params_model)
      render json: @artist
    else
      render json: @artist.errors, status: :unprocessable_entity
    end
  end

  def destroy
    @artist.destroy
  end

  protected
  def find_model
    @artist = Artist.find(params[:id])
  end

  def params_model
    params.fetch(:artist,{}).permit(:name)
  end
end
Enter fullscreen mode Exit fullscreen mode

Some of the things I suggest above allows you to then conventional your controllers further which helps you avoid the many abstractions that are wrongly and commonly adopted in Rails applications.

So here pulled from one of my many code bases below I show you this conventialize base controller. When you are tasked with building many Rails apps you may come to the same natural conclusion I am showing and will find that the majority of web-apps can fit within this structure allowing for rapid development of insane speeds.

class Admin::Api::BaseController < Admin::BaseController
  before_filter :find_model, only: %i(show edit update destroy)
  def index
    klass = self.controller_name.classify.constantize
    render_paginated_json klass, :admin_index_json, index_params
  end

  def new
    klass = chain
    render json: klass.admin_new_json
  end

  def show
    render json: @model.admin_show_json
  end

  def create
    @model = chain.create params_model
    render_json
  end

  def edit
    render json: @model.admin_edit_json
  end

  def update
    @model.update_attributes(params_model)
    render_json
  end

  def destroy
    @model.destroy
    render json: {id: @model.id}
  end

  protected
    def render_json
      if @model.errors.any?
        render json: @model.errors.to_json, status: 422
      else
        render json: @model.admin_object_json
      end
    end

    def chain
      self.controller_name.classify.constantize
    end

    def find_model
      @model = chain.find params[:id]
    end
end

Enter fullscreen mode Exit fullscreen mode

So the result that occurs is you have controllers that contain the real code and nothing more.

class Admin::Api::CurriculumsController < Admin::Api::BaseController
  protected
    def model_params
      params.fetch(:curriculum,{})
        .permit :pdf,
                :course_id
    end
end
Enter fullscreen mode Exit fullscreen mode
class Admin::Api::MarksController < Admin::Api::BaseController
end
Enter fullscreen mode Exit fullscreen mode

This then opens up your code base to create powerful generators because things are so highly conventialize. When I use to run my own dev-firm we could generate out 80% of a web-app and have an MVP for delivery in two days.

Thoughbot had something similar but not to this level of exterme generation.

A bit of rant but food for thought for thoes getting into Rails.

Collapse
zimski profile image
CHADDA Chakib

Interesting point.

How Pushing all the CRUD logic in a base class make this easier/faster than just scafolding models + controllers ?