Command Driven Design Pattern - ROR
Tags: designpatterns, ror, webdev, ruby
Published: 2023-03-30 22:14:57

 In this blog we'll dive into one lesser-known design pattern  but highly efficient for large scaled applications which helps the code repository to keep organised and can be easily scaled up.

#### Design Pattern Name: Command Driven Pattern

Usually the request from client goes to the controller which speaks to the model ( database ) and send back the view or JSON.

But in this design pattern request from controller goes to a command, and a command can be having number of actions items to perform and send the response back.

In layman terms take an example of constructing a shopping mall. the action items are: 

1. Buy the plot.
2. Setting up the base.
3. Raising the walls.
4. Elevators
5. Painting

so all these five steps can we performed a separate file called as **COMMAND**.

Lets consider this scenario:

Example: On User Sign up, consider these following actions are to be performed. 

1. User must be authenticated. 
2. User must be sent a logged-in alert email. 
3. User should be awarded some points. 
4. User should receive push notification.
5. Audit for all the above actions.


Let's create a folder in `app/` called core and file called `Command.rb`

``` 
class Core::Command
  include ActiveModel::Validations

  attr_accessor :token

  def initialize(attributes = {})
    attributes.each do |name, value|
      if methods.include? "#{name}=".to_sym
        method("#{name}=".to_sym).call(value)
      end
    end
  end

  # this method can be ovveridden in other classes
  def run
  end
end
```

Now in Lets create `CreateUserCommand.rb` in core folder

``` 
class Core::CreateUserCommand < Core::Command
  attr_reader :user_params

  def initialize(params)
    super(params)
    @user_params = params
  end

  def run
    ActiveRecord::Base.transaction do
      authenticate_user
      mailer("Account Created")
      award_points
      send_push_notification
      mailer("User Logged In")
    end
    # can be written in JSON builder a seprate file
    return { name: "Samala Sumanth", git: "https://github.com/SamalaSumanth0262"}
  end

  def authenticate_user
    # can be separate command for user authentication
    puts "User Authenticated"
  end

  def mailer(message)
    # can be separate command for mailer
    puts message
  end
  
  def award_points
    # can be written in separate command for awarding points
    puts "User has been awarded 10 points"
  end

  def send_push_notification
    # User Notification Command
    puts "User has been sent push notification"
  end
end

```

And Finally your controller should look like this
```
class UsersController < ApplicationController
  # bypass csrf protection for all the requests made
  protect_from_forgery with: :null_session
  before_action :set_user, only: %i[ show edit update destroy ]
  # /users/
  def create
   render json: ::Core::CreateUserCommand.new(user_params).run
  end

  private
    # Only allow a list of trusted parameters through.
    def user_params
      params.fetch(:user, {})
    end
end
```

Thats It. with this approach we have moved most of the logic into command instead of having them in fatty models.

### Please feel free to comment and suggest any kind of improvement.

This blog is also inspired by: https://blog.slava.dev/command-driven-architecture-for-ruby-on-rails-35949a0b0558

#### You can contact me from my portfolio: https://sumanthsamala.netlify.app