engine的安装
#和gem的生成方式一样,只是添加了 --mountable
rails plugin new blorgh --mountable
相比于Gem, engine是功能更加完善的Gem(gem和engine具有相同的lib目录结构), 相比于APP,APP是功能更加强大的engine(APP和engine具有结构相同的app和test结构目录)。
原生代码解析
#lib/blorgh/engine.rb
module Blorgh
class Engine < ::Rails::Engine
isolate_namespace Blorgh #定义独立的命名空间,避免engine和app的冲突
end
end
#app/controllers/blorgh/application_controller.rb
module Blorgh
class ArticlesController < ApplicationController
#默认继承ApplicationController,按照constant查找原则,会寻找Blorgh::ApplicationController
..
end
end
#改进,engine中的controller要访问app中的controller,需要让其controller继承app的ApplicationController,所以代码修改为
module Blorgh
class ArticlesController < ::ApplicationController
..
end
end
#test/dummy/config/routes.rb文件中,需要安装engine的路由
Rails.application.routes.draw do
mount Blorgh::Engine => "/blorgh"
end
为engine添加功能
#使用scaffold, controller, model, routes的生成方法和app中的完全一致
#本项目中建立文件和评论的scaffold
rails g scaffold article title:string content:text
rails g model comment article_id:integer content:text
#在项目中建立两个model的关联,这里不做赘述
article has_many comments
comment belongs_to article
把engine挂载到app中
#本地mount方式不懂,下面使用github的方式来挂载项目
#gemfile
gem 'blorgh', git: '[email protected]:Jayzen/blorgh.git'
#config/routes.rb
Rails.application.routes.draw do
mount Blorgh::Engine => "/blorgh"
end
#目前已经可以使用http://localhost:3000/blorgh来访问项目,但是访问的数据库是engine的
#如果要使用app的数据库
rails blorgh:install:migrations #copy migration from blorgh to app
rails db:migrate #app中执行,访问http://localhost:3000/blorgh来获得app的数据库信息
engine和app相互关联
#为app添加user这个model, 并且在article添加author_name这个字段,这个字段是user中的字段
rails g model user name
#engine中为article添加外键
rails g migration add_author_id_to_blorgh_articles author_id:integer #添加外键
#app中执行迁移
rails blorgh:install:migrations
#app中的user这个model,用户在定义的时候也可能是people这个model,也可以是其他名称的model,所以这里model的名称要配置
#app中config/initializers/blorgh.rb
Blorgh.author_class = "User"
#engine中的lib/blorgh.rb
require "blorgh/engine"
module Blorgh
mattr_accessor :author_class
def self.author_class
@@author_class.constantize
end
end
#使用Blorgh.author_class的方式来灵活配置article.rb中内容
#app/models/blorgh/article.rb
attr_accessor :author_name
belongs_to :author, class_name: Blorgh.author_class.to_s
before_validation :set_author
private
def set_author
self.author = Blorgh.author_class.constantize.find_or_create_by(name: author_name)
end
区分路由
#调用engine的路由, blorgh是engine的名称
blorgh.articles_path
#调用app的路由,使用main_app
main_app.root_path