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

Thay đổi Package Name của Android Studio dể dàng với plugin APR

Nếu bạn đang gặp khó khăn hoặc bế tắc trong việc thay đổi package name trong And

Lỗi không Update Meta_Value Khi thay thế hình ảnh cũ bằng hình ảnh mới trong WordPress

Mã dưới đây hoạt động tốt có 1 lỗi không update được postmeta ” meta_key=

Bài 1 – React Native DevOps các khái niệm và các cài đặt căn bản

Hướng dẫn setup jenkins agent để bắt đầu build mobile bằng jenkins cho devloper an t

Chuyển đổi từ monolith sang microservices qua ví dụ

1. Why microservices? Microservices là kiến trúc hệ thống phần mềm hướng dịch vụ,