Create Subdomain Programmatically

Kebetulan saat ini Codename Ramadhan (will be launched soon) menggunakan fitur subdomain dan barangkali teman-teman merasa ingin tahu.

Bagaimana sih caranya implementasi subdomain secara programmatically pada aplikasi Rails?

Begini caranya:

1. Generate Account Model

Pertama kita generate model Account terlebih dahulu sebagai tabel untuk menyimpan nama-nama subdomain yang akan kita gunakan.

rails g model Account subdomain:string

Dari generator tersebut kita akan memperoleh migration file dan kita perlu melakukan rails db:migrate.

2. Tambahkan Constraints Class dan Modifikasi routes.rb

Create new file pada folder /lib dan beri nama subdomain.rb dengan code sebagai berikut:

class Subdomain
  def self.matches?(request)
    request.subdomain.present? && request.subdomain != "www"
  end
end

Kita perlu melakukan sedikit modifikasi pada routes.rbyaitu dengan menambahkan constraints pada url-url yang akan digunakan pada subdomain. Misalnya saja user harus berada pada subdomain untuk mengakses channel pada pages controller, maka akan seperti ini:

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

  constraints(Subdomain) do

    get '/', to: 'pages#channel'

  end

end

3. Tambahkan Otorisasi Pada Controller

Kita akan menambahkan before_action :require_subdomainpada controller yang seharusnya berada pada subdomain. Untuk itu kita perlu memodifikasi pada application_controller.rb sehingga akan menjadi seperti berikut:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  helper_method :require_subdomain

  private

  def require_subdomain
    not_found unless subdomain_exist?
  end

  def subdomain_exist?
    account = Account.find_by_subdomain(request.subdomain)
    !!account
  end

  def not_found
    raise ActionController::RoutingError.new('404')
  end
end

Dari application_controller.rb tersebut kita telah memiliki helper method yang bernama require_subdomainyang nantinya akan kita gunakan pada controller yang membutuhkan.

class PagesController < ApplicationController
  before_action :require_subdomain

  def channel
    # logic goes here
  end
end

4. Try It Out

Gunakan rails console untuk membuat test data (ngomong-ngomong post tentang custom validation ini menjelaskan bagaimana membuat custom validation untuk subdomain).

$ rails c
Running via Spring preloader in process 15151
Loading development environment (Rails 5.1.2)
2.4.1 :001 > Account.new(subdomain: 'test').save
   (0.4ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
   (0.3ms)  BEGIN
  Account Exists (0.7ms)  SELECT  1 AS one FROM `accounts` WHERE `accounts`.`subdomain` = BINARY 'test' LIMIT 1
  SQL (0.5ms)  INSERT INTO `accounts` (`subdomain`, `created_at`, `updated_at`) VALUES ('test', '2017-07-22 14:58:35', '2017-07-22 14:58:35')
   (35.5ms)  COMMIT
 => true 
2.4.1 :002 > 

Check pada browser dengan mengakses http://test.lvh.me dan coba juga random subdomain, misalnya http://tidak-ada.lvh.me.

Contoh Ketika Subdomain Terdaftar pada Account

 

Contoh Ketika Subdomain Tidak Terdaftar pada Account

Silakan masukan email jika merasa implementasi subdomain pada Rails tuh mudah! (:




absyah