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

results matching ""

    No results matching ""