Rails engine

Chào mọi người, bài viết này là tìm hiểu của mình về Rails Engine. Rails engine Mọi Rails developer đều quen với một Rails project (folder app với các subfolder controllers, models, … , folder config chứa routes cho app, folder db chứa những migrations). Nếu ta coi Rails project là một main app thì

Chào mọi người, bài viết này là tìm hiểu của mình về Rails Engine.

Rails engine

Mọi Rails developer đều quen với một Rails project (folder app với các subfolder controllers, models, … , folder config chứa routes cho app, folder db chứa những migrations).

Nếu ta coi Rails project là một main app thì Rails Engine là những mini app được “nhúng” vào main app nhằm mục đích thêm những functionality riêng biệt cho main app.

main app cũng thực chất cũng là 1 Rails Engine, với class Rails::Application kế thừa class Rails::Engine, do đó cả main app và các Engine đều có chung một cấu trúc thư mục giống nhau.

Một số gem quen thuộc có sử dụng Rails engine: Devise, Spree.

Engine structure

Để nhúng một engine vào main app, ta dùng lệnh:

rails plugin new sherlock --mountable

Lệnh này làm 2 việc: tạo folder sherlock (cùng cấp với app, config, … của main app) chứa mini engine folder, và thêm gem sherlock vào Gemfile của main app:

# Gemfile

gem 'sherlock', path:'sherlock'

Và cấu trúc folder sherlock cơ bản sẽ giống với main app, trừ folder lib:

Trong quá trình khởi chạymain app, nó sẽ setup các gem được chỉ định trong Gemfile, vì đã thêm gem sherlockGemfile nên bundler sẽ đọc file sherlock.gemspec và require những file được chỉ định trong option spec.files:

# sherlock/sherlock.gemspec...
spec.files =Dir["{app,config,db,lib}/**/*","MIT-LICENSE","Rakefile","README.md"]

như ta thấy ở trên, bundler sẽ require tất cả các file trong các folder app, config, dblib

folder lib

bắt đầu từ file sherlock.rb define module Sherlock và require tới sherlock/engine

# lib/sherlock.rbrequire"sherlock/engine"moduleSherlock# Your code goes here...end# lib/sherlock/engine.rbmoduleSherlockclassEngine<::Rails::Engine
    isolate_namespace Sherlockendend

dòng

isolate_namespace Sherlock

chỉ định namespace của engine, mỗi engine đều được bọc bởi một module, thường là tên củaengineđó (ở đây là module Sherlock), và tất cả các class trong engine cũng đều bọc trong module này.

class Sherlock::Engine là nơi ta định nghĩa các config, setup cần thiết cho functions được nhúng. Ví dụ ở Spree:

# api/lib/spree/api/engine.rbrequire'rails/engine'moduleSpreemoduleApiclassEngine<Rails::Engine
      isolate_namespace Spree
      engine_name 'spree_api'defself.root@root||=Pathname.new(File.expand_path('../../../../', __FILE__))end
      
      initializer "spree.environment",:before=>:load_config_initializersdo|app|
        app.config.spree =Spree::Core::Environment.newend# ...endendend

initializer là một class method của Rails::Railtie hỗ trợ việc hook vào quá trình Rails init process nhằm mục đích thêm, sửa đổi config của cả Rails app. Ở đây params app chính là instance của Rails::Application, Spree khởi tạo config riêng của mình ở đây, từ đó config này (1 instance của class Spree::Core::Environment) có thể sử dụng ở mọi nơi trong main app:

Rails.application.config.spree

folder config

chứa routes.rb nơi define các endpoint của engine:

# sherlock/config/routes.rbSherlock::Engine.routes.draw do
    get :home, to:"home#index"end

ta cần mount Sherlock::Engine vào config routes của main app để sử dụng:

# config/routes.rb

mount Sherlock::Engine=>"/sherlock"

lúc này ở main app có thể truy cập endpoint: /sherlock/home.

folder app

các folder con trong app đều giống với main app, mọi class, views đều được module hoá (Sherlock):

các controller, helpers, models, … được define ở đây và được sử dụng ở main app.

Devise là một ví dụ điển hình:

các controller, view, helper, mailer đều được define sẵn và sử dụng ở main app như cách ta thường làm với devise: mount routes, include devise trong model => hoàn thành phần authentication với đầy đủ routes, controllers, views, …


Trên đây là tìm hiểu của mình về Rails::Engine, cảm ơn mọi người đã đọc bài viết 😀 .

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ