Computer >> Máy Tính >  >> Lập trình >> Ruby

Xây dựng ứng dụng Ruby on Rails có nhiều người thuê với tên miền phụ

Theo định nghĩa về đa quyền, khi một ứng dụng phục vụ nhiều người thuê, điều đó có nghĩa là có một vài nhóm người dùng chia sẻ quyền truy cập chung vào phiên bản phần mềm. Một ví dụ tuyệt vời về ứng dụng hỗ trợ đa thai là nền tảng Jira, nơi mỗi công ty có miền phụ để truy cập phần mềm, ví dụ:mycompany.atlassian.net .

Trong bài viết này, tôi sẽ giúp bạn làm quen với cả khía cạnh lý thuyết và thực tiễn của đa thai. Sau khi thảo luận về một số loại phương pháp tiếp cận phổ biến để triển khai hỗ trợ cho nhiều người thuê trong ứng dụng của bạn, tôi sẽ chỉ cho bạn cách bạn có thể triển khai hai trong số chúng trong ứng dụng Rails của mình. Chúng tôi sẽ cùng nhau xây dựng một ứng dụng đơn giản với nhiều người thuê, trong đó mỗi người thuê sẽ có miền phụ.

Sau khi đọc bài viết này, bạn sẽ có thể:

  • Thảo luận về các loại ứng dụng nhiều người thuê khác nhau và cho biết khi nào thì phương pháp đã cho là lựa chọn phù hợp,
  • Tạo ứng dụng Ruby on Rails với sự hỗ trợ cho nhiều người thuê và
  • Sử dụng các miền phụ tùy chỉnh cho khách hàng của bạn trong ứng dụng Ruby on Rails.

Cần có kiến ​​thức cơ bản về Rails để theo dõi bài viết này và nhận được hầu hết các lợi ích của nó.

Đa năng trong lý thuyết

Như tôi đã đề cập trước đây, chúng ta có thể nói rằng ứng dụng hỗ trợ nhiều quyền khi nó phục vụ một số nhóm người dùng có chung quyền truy cập vào các tính năng của ứng dụng. Một ví dụ điển hình về một ứng dụng như vậy là một nền tảng blog nơi mọi người dùng có một miền phụ riêng biệt trong miền chính. Mỗi blog có tên miền phụ nhưng chia sẻ các tính năng giống như các blog khác:nhận xét, bài viết và trang tổng quan quản trị.

Mặc dù bề ngoài có vẻ như các ứng dụng dành cho nhiều người thuê hoạt động tương tự nhau, nhưng chúng có thể triển khai các loại kiến ​​trúc đa người thuê khác nhau. Hãy xem các loại phổ biến và hiệu quả nhất trong số đó.

Cấp hàng cơ sở dữ liệu

Nếu bạn không muốn sử dụng nhiều cơ sở dữ liệu trong ứng dụng của mình, bạn có thể chọn một phương pháp hoạt động trên một cơ sở dữ liệu trung tâm. Mỗi bảng trong cơ sở dữ liệu bao gồm tenant_id được sử dụng trong mọi truy vấn được thực hiện bên trong ứng dụng để lấy dữ liệu thuộc về đối tượng thuê đã cho.

Thời gian thiết lập của người thuê trong cấu trúc như vậy nhanh chóng, không có chi phí bổ sung và có thể triển khai biến thể này ở mọi nơi. Tuy nhiên, chúng tôi nên cẩn thận vì chúng tôi có thể dẫn đến rò rỉ dữ liệu nếu chúng tôi quên đưa id của người thuê vào truy vấn. Việc sửa đổi cấu trúc cơ sở dữ liệu sẽ khó duy trì đối với một số nhóm người dùng nhất định, vì vậy chúng ta nên lưu ý đến nhược điểm này.

Mức giản đồ

Bạn vẫn có thể có một cơ sở dữ liệu trung tâm nhưng với các bảng và lược đồ riêng biệt cho từng đối tượng thuê. Ngược lại với cách tiếp cận cấp hàng cơ sở dữ liệu, bạn phải thay đổi đường dẫn tìm kiếm đến các bảng khi chuyển đổi giữa các đối tượng thuê thay vì sửa đổi truy vấn. Trong PostgreSQL, bạn có thể sử dụng tập hợp search_path và trong MySQL use câu lệnh để chuyển đổi giữa các lược đồ.

Trước khi chọn phương pháp này, hãy đảm bảo rằng có thể sử dụng các câu lệnh đã đề cập trên máy chủ DB của bạn. Cũng nên nhớ rằng việc thêm người thuê mới tương đối chậm vì bạn phải tạo một lược đồ mới và tạo các bảng trong cơ sở dữ liệu.

Cấp cơ sở dữ liệu

Nếu bạn có thể chi trả chi phí cho một cơ sở dữ liệu mới mỗi khi bạn thêm người thuê mới vào ứng dụng của mình, thì cách tiếp cận này có thể phù hợp với bạn. Cách tiếp cận này là chậm nhất so với tất cả các kiến ​​trúc đã thảo luận khi nói đến việc thêm người thuê mới.

Rất có thể dẫn đến rò rỉ dữ liệu vì để chuyển sang đối tượng thuê khác, bạn phải thiết lập một kết nối mới với cơ sở dữ liệu. Bạn cũng có thể dễ dàng sửa đổi cấu trúc cơ sở dữ liệu của mọi nhóm người dùng nếu bạn muốn.

Tạo khung ứng dụng

Chúng tôi sẽ tạo hai ứng dụng riêng biệt:một ứng dụng cho nhiều thuê nhà được hỗ trợ bởi một cơ sở dữ liệu và một ứng dụng cho nhiều thuê nhà được hỗ trợ bởi nhiều cơ sở dữ liệu. Chúng đại diện cho một cách tiếp cận khác nhau để đối phó với nhiều người thuê, nhưng giai đoạn cấu hình là giống nhau.

Phiên bản mới nhất của Ruby là 2.7.2 và 6.1 RC1 của đá quý Ruby on Rails tính đến thời điểm viết bài này. Đảm bảo rằng bạn đã cài đặt đúng phiên bản Ruby trong hệ thống của mình và cố gắng cài đặt đúng phiên bản của khuôn khổ:

gem install rails -v 6.1.0.rc1

Bây giờ chúng ta có thể tạo các tệp dự án bằng lệnh sau:

rails _6.1.0.rc1_ new tenantapp -d=mysql

Nhập thư mục dự án, chạy máy chủ và kiểm tra xem bạn có thể nhìn thấy màn hình chào mừng hay không để chúng tôi có thể tiếp tục:

cd tenantapp/
rails s

Ứng dụng đường ray cho nhiều người thuê với một cơ sở dữ liệu

Đã đến lúc viết mã thứ gì đó. Phần này của bài viết sẽ chỉ cho bạn cách thực hiện đa thai trong ứng dụng Rails của bạn. Tôi sẽ sử dụng phương pháp này với một cơ sở dữ liệu và một lược đồ.

Kế hoạch như sau:

  • Chúng tôi sẽ tạo khung cho ứng dụng Rails bằng cách sử dụng phiên bản mới nhất hiện có của Ruby và khuôn khổ Ruby on Rails
  • Chúng tôi sẽ phân tích một số mô hình để có dữ liệu mà chúng tôi có thể vận hành
  • Đối với chức năng mà chúng tôi đã tạo ở bước trước, chúng tôi sẽ thêm hỗ trợ cho tính năng nhiều người bằng cách cập nhật các bảng và mã cơ sở dữ liệu trong ứng dụng của mình
  • Bước cuối cùng sẽ là thêm hỗ trợ cho các miền phụ tùy chỉnh để cho phép người dùng dễ dàng truy cập đối tượng thuê của họ
  • Chúng tôi sẽ khám phá các ý tưởng về một số tính năng mà bạn có thể tự triển khai sau này

Chuẩn bị dữ liệu thử nghiệm

Giả sử rằng chúng tôi đang xây dựng một nền tảng blog, nơi người dùng có thể xem các bài báo do nhiều tác giả xuất bản.

Trước tiên, tôi sẽ tạo mô hình tác giả, mô hình này sẽ lưu trữ dữ liệu của tác giả:

rails g scaffold author slug:string name:string description:string
rake db:create
rake db:migrate

Bây giờ bạn có thể truy cập địa chỉ https:// localhost:3000 / author và thêm một vài tác giả để sau này chúng tôi có thể gán họ vào các bài báo.

Bước tiếp theo là tạo các bài viết:

rails g scaffold article title:string content:text
rake db:migrate

Thêm Hỗ trợ Mang thai hộ

Trong ứng dụng chúng tôi đang tạo, tác giả là người thuê của chúng tôi. Mỗi tác giả chỉ nên có quyền truy cập vào các bài báo của mình. Như tôi đã đề cập trước đây, khi chúng ta muốn triển khai hỗ trợ đa thai trong một cơ sở dữ liệu và một lược đồ, yêu cầu quan trọng là thêm tenant_id vào mọi mô hình sẽ được quản lý bởi người thuê của chúng tôi.

Tạo di chuyển thích hợp trong cơ sở dữ liệu

rails g migration AddTenantIdToArticle tenant_id:integer
rake db:migrate

Việc di chuyển ở trên sẽ thêm cột mới vào Article của chúng tôi người mẫu. Cột này sẽ được sử dụng trong bất kỳ truy vấn nào để chỉ lấy dữ liệu truy cập được chỉ định cho đối tượng thuê hiện tại.

Giao bài viết cho người thuê

Trong bước này, tôi sẽ cập nhật mã để chúng tôi có thể chỉ định tác giả nhất định cho bài viết và sau đó chỉ hiển thị các bài viết cho tác giả đã chọn. Mở app/controllers/articles_controller.rb và thêm các thay đổi sau:

class ArticlesController < ApplicationController
 before_action :set_article, only: [:show, :edit, :update, :destroy]
 before_action :set_authors, only: [:edit, :update, :new, :create]
 
 # ...
 
 private
   # Only allow a list of trusted parameters through.
   def article_params
     params.require(:article).permit(:title, :content, :tenant_id)
   end
 
   def set_authors
     @authors = Author.all
   end
end

Theo quan điểm của chúng tôi, bây giờ chúng tôi có thể sử dụng @authors biến chứa bộ sưu tập các tác giả được thêm vào ứng dụng của chúng tôi. Giờ đây, chúng tôi có thể thêm trường được chọn chứa tên tác giả và chỉ định một tenant_id thích hợp . Mở app/views/articles/_form.html.erb và thêm phần sau:

<div className="field">
 <%= form.label :author %>
 <%= form.select :tenant_id, options_from_collection_for_select(@authors, 'id', 'name', article.tenant_id), include_blank: true %>
</div>

Hãy tiếp tục và tạo một vài tác giả, sau đó tạo một số bài báo để sau đó hiển thị các bài viết chỉ được chỉ định cho tác giả nhất định.

Thêm hỗ trợ cho các miền phụ tùy chỉnh

Chúng tôi đã tạo tác giả với tên John Doe và đặt giá trị slug thành johndoe . Mục tiêu của chúng tôi là truy cập địa chỉ https://johndoe.localhost:3000 / và xem dữ liệu chỉ liên quan đến người thuê đã cho, John Doe, trong trường hợp này.

Cấu hình tên miền phụ

Chúng tôi muốn quản lý và truy cập các bài viết khi người thuê được đặt. Chúng tôi có thể đạt được điều này bằng cách cập nhật config/routes.rb tập tin và gói định nghĩa của tài nguyên bài viết vào khối ràng buộc:

Rails.application.routes.draw do
 constraints subdomain: /.*/ do
   resources :articles
 end
 
 resources :authors
end

Theo mặc định, Rails đặt độ dài miền cấp cao nhất thành 1, nhưng chúng tôi muốn sử dụng localhost để đặt cài đặt này thành 0. Chúng tôi có thể thực hiện việc này bằng cách thêm dòng sau vào tệp config/environments/development.rb :

config.action_dispatch.tld_length = 0

Làm cho các tên miền phụ hoạt động với tính đa năng

Bây giờ, có thể chỉ định bất kỳ tác giả nào cho bài báo. Không thể thực hiện được khi miền phụ được sử dụng. Chúng tôi phải thay đổi hành vi của ArticlesController và thay vì đặt tất cả các tác giả, chúng tôi phải đặt tác giả mà miền phụ được yêu cầu:

 
class ArticlesController < ApplicationController
 before_action :set_author
 before_action :set_article, only: [:show, :edit, :update, :destroy]
 
 # GET /articles
 # GET /articles.json
 def index
   @articles = Article.where(tenant_id: @author.id)
 end
 
 # ...
 
 private
   def set_article
     @article = Article.find_by!(id: params[:id], tenant_id: @author.id)
   end
 
   # ...
 
   def set_author
     @author = Author.find_by!(slug: request.subdomain)
   end
end

Tôi đã thực hiện một vài thay đổi đối với bộ điều khiển:

  • Thay vì set_authors , tôi đã xác định set_author phương thức đặt mà tác giả yêu cầu thông qua tên miền phụ. Điều quan trọng là gọi phương thức này trong before_filter trước set_article được gọi là. Tác giả phải được chỉ định trước khi chúng tôi cố gắng thiết lập bài viết.
  • Tôi đã cập nhật set_article phương pháp để tìm kiếm bài viết với id đã cho và tác giả được chỉ định. Chúng tôi không muốn hiển thị các bài viết do Tom tạo trong khi người thuê hiện tại của chúng tôi là John.
  • Tôi đã cập nhật hành động lập chỉ mục để chỉ chọn các bài viết được giao cho người thuê hiện tại của chúng tôi.

Khi bạn làm việc trên một ứng dụng nhiều đối tượng và sử dụng một cơ sở dữ liệu với một giản đồ, bạn luôn phải nhớ xác định phạm vi bất kỳ truy vấn nào theo tenant_id cột; nếu không, bạn sẽ cung cấp dữ liệu không được chỉ định cho người thuê được yêu cầu.

Bộ điều khiển được cập nhật, vì vậy bước tiếp theo là cập nhật dạng xem biểu mẫu. Mở app/views/articles/_form.html.erb và thay thế phần trước bằng trường ẩn đơn giản:

<%= form.hidden_field :tenant_id, value: @author.id %>

Trước những thay đổi đó, người dùng có thể chọn tác giả của bài viết bằng cách sử dụng biểu mẫu. Người dùng có thể chọn tác giả cho tất cả các hành động bằng cách sử dụng một miền phụ nhất định trong địa chỉ trang web.

Bây giờ bạn có thể kiểm tra mã chúng tôi đã tạo. Ví dụ:tạo một tác giả mới với tên John Doe và slug johndoe . Truy cập địa chỉ https://johndoe.localhost:3000 / posts / new và thêm một bài viết mới. Sau khi thêm một bài viết mới, bạn có thể xem bài viết đó trên danh sách có sẵn dưới https://johndoe.localhost:3000 / posts.

Xin chúc mừng! Bạn vừa tạo một ứng dụng nhiều người thuê, trong đó mỗi tác giả có tên miền phụ.

Cải tiến hơn nữa

Bây giờ bạn có thể mở rộng mã của ứng dụng bằng cách thêm các tính năng mới. Nền tảng blog của chúng tôi rất đơn giản; Có lẽ đã đến lúc thêm một số phần nhận xét? Bất kể bạn thêm chức năng nào, bạn phải nhớ thêm tenant_id vào mô hình mới và sử dụng nó khi truy vấn tài nguyên.

Bạn có thể tạo một phạm vi đặc biệt và gói nó vào mối quan tâm:

module Tenantable
 extend ActiveSupport::Concern
 
 included do
   scope :for_author, -> (author) { where(tenant_id: author.id) }
 end
end

và sau đó sử dụng nó trong mọi mô hình có chứa dữ liệu cho người thuê:

class Article < ApplicationRecord
 include Tenantable
end
 
author = Author.find(1)
Article.for_author(author)

Với cách tiếp cận trên, bạn sẽ chỉ phải cập nhật một nơi trong trường hợp đổi tên tenant_id hoặc giới thiệu thêm các điều kiện khi truy vấn dữ liệu liên quan đến người thuê.

Ứng dụng Rails cho nhiều người thuê với nhiều cơ sở dữ liệu

Trong các đoạn trước, chúng ta đã xây dựng một ứng dụng Rails hỗ trợ nhiều người thuê với một cơ sở dữ liệu và một lược đồ. Nhược điểm đáng kể nhất của cách tiếp cận như vậy là khả năng cao bị rò rỉ dữ liệu.

Tin tốt là phiên bản mới nhất của khuôn khổ Ruby on Rails đã tích hợp sẵn hỗ trợ để quản lý nhiều cơ sở dữ liệu. Tôi sẽ khám phá nó và chỉ cho bạn cách bạn có thể sử dụng nó để xây dựng một ứng dụng Rails có nhiều người thuê với nhiều cơ sở dữ liệu và tên miền phụ tùy chỉnh.

Kế hoạch như sau:

  • Chúng tôi sẽ tạo khung cho ứng dụng Rails bằng cách sử dụng phiên bản mới nhất hiện có của Ruby và khuôn khổ Ruby on Rails
  • Chúng tôi sẽ phân tích một số mô hình để có dữ liệu mà chúng tôi có thể vận hành
  • Chúng tôi sẽ hỗ trợ thêm cho các miền phụ tùy chỉnh.
  • Chúng ta sẽ tìm hiểu cách thêm người thuê mới bằng cách tạo và định cấu hình cơ sở dữ liệu mới.
  • Bước cuối cùng là cập nhật ứng dụng để chuyển đổi cơ sở dữ liệu khi miền phụ nhất định được yêu cầu.

Chuẩn bị dữ liệu thử nghiệm

Giả sử rằng chúng tôi đang xây dựng một nền tảng blog, nơi người dùng có thể xem các bài báo do nhiều tác giả xuất bản. Mỗi tác giả sẽ có một cơ sở dữ liệu riêng.

Bắt đầu với việc tạo Author mô hình cùng với các tính năng tổng hợp sẽ giúp chúng tôi xem và tạo tác giả mới:

rails g scaffold author slug:string name:string description:string
rake db:create
rake db:migrate

Bây giờ bạn có thể truy cập https:// localhost:3000 / author và xem những gì Rails đã tạo ra cho chúng tôi.

Thêm tác giả mới

Tôi đã tạo một tác giả mới với tên John Doe và slug johndoe . Giá trị slug sẽ được sử dụng sau này để phát hiện tác giả nào mà chúng tôi nên hiển thị thông tin bằng tên miền phụ.

Bởi vì mỗi tác giả sẽ có một cơ sở dữ liệu riêng biệt, chúng tôi phải thêm cơ sở dữ liệu mới theo cách thủ công cho John. Mở config/database.yml và thêm các thay đổi sau:

development:
 primary:
   <<: *default
   database: tenantapp_development
 primary_johndoe:
   <<: *default
   database: tenantapp_johndoe_development
   migrations_paths: db/tenants_migrations

Chúng tôi sẽ sử dụng một thư mục riêng cho việc di chuyển được những người thuê của chúng tôi sử dụng. Chúng tôi không cần chúng trong cơ sở dữ liệu trung tâm. Bây giờ bạn có thể tạo cơ sở dữ liệu cho John bằng cách sử dụng lệnh mặc định:

rake db:create

Thêm bài viết

Bây giờ chúng ta có thể mở đầu cho Article mô hình cùng với bộ điều khiển và chế độ xem:

rails g scaffold article title:string content:text --database primary_johndoe

Tôi đã vượt qua --database tham số để cho Rails biết rằng không nên đặt quá trình di chuyển trong db/migrations mặc định thư mục được sử dụng bởi cơ sở dữ liệu chính. Bây giờ chúng ta có thể chạy lệnh di chuyển:

rake db:migrate

Ngay bây giờ, chúng tôi có hai lược đồ:db/schema.rbdb/primary_johndoe_schema.rb . Nếu bạn muốn tạo các bảng khác nhau cho người thuê, bạn có thể đạt được điều này bằng cách đặt một migrations_path duy nhất giá trị trong config/database.yml hồ sơ cho người thuê đã cho. Trong bài viết này, chúng tôi muốn có các bảng giống nhau cho tất cả người thuê, vì vậy đường dẫn đến quá trình di chuyển sẽ giống nhau.

Thêm hỗ trợ cho thuê nhiều người

Trong ứng dụng mà nhiều người thuê nhà được hỗ trợ bởi một cơ sở dữ liệu, để lấy dữ liệu cho người thuê nhà đã cho, chúng tôi chỉ cần cập nhật truy vấn vào cơ sở dữ liệu với tenant_id thích hợp giá trị. Trong trường hợp của chúng tôi, mỗi người thuê có cơ sở dữ liệu của họ, vì vậy chúng tôi phải chuyển đổi giữa các cơ sở dữ liệu.

Rails 6.1 đi kèm với hỗ trợ tích hợp cho tính năng phân sắc ngang. Shard là một phân vùng dữ liệu ngang chứa một tập hợp con của tổng số tập dữ liệu. Chúng tôi có thể lưu trữ các bài báo của tất cả các tác giả trong một bảng trong một cơ sở dữ liệu, nhưng nhờ tính năng sharding, chúng tôi có thể chia dữ liệu thành nhiều bảng có cùng cấu trúc nhưng được đặt trong các cơ sở dữ liệu riêng biệt.

Hãy xác định các phân đoạn của chúng ta trong lớp cha cho tất cả các mô hình. Chúng được lưu trữ trong app/models/application_record.rb :

ActiveRecord::Base.connected_to(role: :reading, shard: :johndoe) do
  Article.all # get all articles created by John
end

Mà không cần gói cuộc gọi của chúng tôi vào connected_to khối, phân đoạn mặc định sẽ được sử dụng. Trước khi tiếp tục, chúng tôi phải giới thiệu một thay đổi nữa. Vì tất cả các phân đoạn chia sẻ cùng một cấu trúc dữ liệu, chúng tôi có thể xóa app/models/primary_johndoe_record.rb mô hình được tạo tự động khi chúng tôi là các bài báo về giàn giáo.

Chúng tôi cũng phải chỉnh sửa app/models/article.rb mô hình hóa và thay đổi lớp cha từ PrimaryJohndoeRecord tới ApplicationRecord :

class Article < ApplicationRecord
end

Thêm nhiều người thuê hơn

Hiện tại, chúng tôi chỉ có một tác giả trong cơ sở dữ liệu của chúng tôi. Để kiểm tra chức năng chuyển đổi giữa các đối tượng thuê của chúng tôi (cơ sở dữ liệu), chúng tôi phải thêm một tác giả nữa. Mở địa chỉ https:// localhost:3000 / author / new và thêm tác giả mới. Tôi đã thêm tác giả với tên Tim Doe và slug timdoe .

Chúng tôi có một bản ghi cho tác giả mới, vì vậy chúng tôi phải xác định một cơ sở dữ liệu mới:

development:
 primary:
   <<: *default
   database: tenantapp_development
 primary_johndoe:
   <<: *default
   database: tenantapp_johndoe_development
   migrations_paths: db/tenants_migrations
 primary_timdoe:
   <<: *default
   database: tenantapp_timdoe_development
   migrations_paths: db/tenants_migrations

Bây giờ, hãy tạo một cơ sở dữ liệu mới và chạy quá trình di chuyển:

rake db:create
rake db:migrate

Bước cuối cùng là cập nhật ApplicationRecord mô hình và xác định một phân đoạn mới:

class ApplicationRecord < ActiveRecord::Base
 self.abstract_class = true
 
 connects_to shards: {
   default: { writing: :primary, reading: :primary },
   johndoe: { writing: :primary_johndoe, reading: :primary_johndoe },
   timdoe: { writing: :primary_timdoe, reading: :primary_timdoe },
 }
end

Bây giờ bạn có thể tạo bài viết cho từng tác giả:

ActiveRecord::Base.connected_to(role: :writing, shard: :johndoe) do
  Article.create!(title: 'Article from John', content: 'content')
end
 
ActiveRecord::Base.connected_to(role: :writing, shard: :timdoe) do
  Article.create!(title: 'Article from Tim', content: 'content')
end

Thêm hỗ trợ cho miền phụ tùy chỉnh

Chúng tôi chưa thể truy cập danh sách bài viết cho tác giả nhất định vì chúng tôi không biết khi nào chúng tôi nên hiển thị các bài viết của John và Tim. Chúng tôi sẽ giải quyết vấn đề này bằng cách triển khai các miền phụ tùy chỉnh. Khi truy cập https://johndoe.localhost:3000 / bài viết, chúng ta sẽ thấy các bài báo của John và khi truy cập vào https://timedoe.localhost:3000 / bài viết của Tim.

Cấu hình tên miền phụ

Chúng tôi muốn quản lý và truy cập các bài viết khi người thuê được đặt. Chúng tôi có thể đạt được điều này bằng cách cập nhật config/routes.rb tập tin và gói định nghĩa của tài nguyên bài viết vào khối ràng buộc:

Rails.application.routes.draw do
 constraints subdomain: /.*/ do
   resources :articles
 end
 
 resources :authors
end

Theo mặc định, Rails đặt độ dài miền cấp cao nhất thành 1, nhưng chúng tôi muốn sử dụng localhost để đặt cài đặt này thành 0. Chúng tôi có thể thực hiện việc này bằng cách thêm dòng sau vào tệp config/environments/development.rb :

config.action_dispatch.tld_length = 0

Làm cho các tên miền phụ hoạt động với tính đa năng

Để chuẩn hóa việc đọc cơ sở dữ liệu cho đối tượng thuê hiện tại, tôi sẽ tạo mối quan tâm của bộ điều khiển có tên là Tenantable . Nó cung cấp read_with_tenant phương thức chấp nhận một khối và thực thi nó trong ngữ cảnh của đối tượng thuê được yêu cầu:

module Tenantable
 extend ActiveSupport::Concern
 
 private
 
 def read_with_tenant(&block)
   author = Author.find_by!(slug: request.subdomain)
 
   ActiveRecord::Base.connected_to(role: :reading, shard: author.slug.to_sym) do
     block.call
   end
 end
end

Lưu tệp này dưới dạng app/controllers/concerns/tenantable.rb và đưa vào ArticlesController :

class ArticlesController < ApplicationController
 include Tenantable
 
 before_action :set_article, only: [:show, :edit, :update, :destroy]
 
 def index
   read_with_tenant do
     @articles = Article.all
   end
 end
 # ...
end

Bây giờ bạn có thể truy cập https://johndoe.localhost:3000 / posts hoặc https://timdoe.localhost:3000 / posts, và bạn sẽ thấy các bài báo khác nhau được hiển thị trên danh sách.

Nếu bạn muốn tạo các bài viết mới bằng cách sử dụng biểu mẫu, bạn phải xác định một phương thức mới được gọi là write_with_tenant và cập nhật mối quan tâm và phương pháp của Người thuê bên trong ArticlesController theo đó.

Cải tiến hơn nữa

Cách tiếp cận được trình bày ở trên chỉ là một phương thức trình bao bọc đơn giản thực thi mã được gói thành một khối trong một kết nối nhất định với cơ sở dữ liệu. Để làm cho nó phổ biến hơn, bạn có thể tạo một phần mềm trung gian sẽ phân tích cú pháp miền phụ và thiết lập kết nối trước khi thực thi bất kỳ mã nào:

ActiveRecord::Base.establish_connection(:primary_timdoe)

Giải pháp cuối cùng phụ thuộc vào nhu cầu của bạn và số lượng nơi bạn muốn sử dụng dữ liệu được chỉ định cho một đối tượng thuê cụ thể.

Tóm tắt

Xin chúc mừng, bạn vừa xây dựng hai phiên bản của ứng dụng Rails nhiều người thuê và có được kiến ​​thức về các cách khác nhau để giao dịch với nhiều người thuê trong một ứng dụng web hiện đại.

Hãy nhanh chóng tóm tắt những gì chúng ta đã học được trong bài viết này:

  • Có ba mức cho thuê nhiều lần chính trong một ứng dụng web - hàng cơ sở dữ liệu, giản đồ và mức cơ sở dữ liệu.
  • Mỗi cách tiếp cận đều có ưu và nhược điểm và lựa chọn của bạn tùy thuộc vào khả năng phần cứng và mức độ cô lập của thông tin về người thuê.
  • Có thể triển khai tất cả các mức cho thuê nhiều lần trong khuôn khổ Ruby on Rails mà không cần bất kỳ thư viện bên ngoài nào.
  • Ruby on Rails hỗ trợ miền phụ tùy chỉnh ngay lập tức, vì vậy nó là một bổ sung hoàn hảo cho ứng dụng nhiều người thuê nơi mỗi người thuê có thể được chỉ định miền phụ của mình.

Tôi hy vọng bạn thích đọc bài viết này và xây dựng các ứng dụng Ruby on Rails cho nhiều người thuê.

Tái bút. Nếu bạn muốn đọc các bài đăng của Ruby Magic ngay khi chúng xuất hiện trên báo chí, hãy đăng ký bản tin Ruby Magic của chúng tôi và không bao giờ bỏ lỡ một bài đăng nào!