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

9 Mẹo lập trình Web “ẩn mình” giúp tiết kiệm hàng giờ đồng hồ

Hầu hết các lập trình viên (kể cả những người giỏi) đều tốn thời gian x

Can GPT-4o Generate Images? All You Need to Know about GPT-4o-image

OpenAI‘s GPT-4o, introduced on March 25, 2025, has revolutionized the way we create visual con

Khi nào nên dùng main, section, article, header, footer, và aside trong HTML5

HTML5 đã giới thiệu các thẻ ngữ nghĩa giúp cấu trúc nội dung web một cách có

So sánh Webhook và API: Khi nào nên sử dụng?

Trong lĩnh vực công nghệ thông tin và phát triển phần mềm, Webhook và API là hai th