按个人理解, Admin Interfaces 的主要作用是减少后台管理界面的 CRUD 开发的重复工作量,并提供登录注销等常见功能的实现.

Admin Interfaces 实现主要分两大块.

  1. 基于继承和配置.
    • 代表: Django Admin(最著名的), ActiveAdmin.
    • 优点: 代码量少.
    • 缺点: 定制难度高.
  2. 基于代码生成.
    • 代表: Rails Scaffold(自带的太简单了).
    • 优点: 代码生成在项目里,定制只要直接修改代码即可,非常灵活.
    • 缺点: 写自定义代码生成器有点难度.
  3. 同时使用代码生成和继承方式.
    • 代表: ActiveScaffold
    • 优点: 在减少代码的同时也保证了定制的灵活性.
    • 缺点: 同上

作为有一个有追求的人,虽然已经 ActiveAdmin 和 ActiveScaffold 这样不错 Rails Admin Interfaces.但为了追求定制的灵活性的最大化,必须得自己造个轮子出来,哪怕是方的轮子.

什么是 Meta Generator?

就是写个 Generator A, Generator A 生成一个 Generator B 到你的项目里, 平常你主要运行 Generator B 生成 CRUD 相关代码. 这里的 Generator A 就是 Meta Generator.

Meta Generator 示例

首先,请认真读完 Creating and Customizing Rails Generators & Templates .

文中的 bin/rails generate generator initializer 的 generator 即是一个 Meta Generator,利用 generator 产生的代码存放在你的 Rails 项目的 lib/generators ,这样我们就可以很方便的修改. 我们只要参考 generator ,写一个类似的 Gem ,把代码生成到 lib/generators 目录即可.

cd your_workspace # 修改成你自己的目录
bundle exec rails plugin new meta_generator_demo # 创建一个 Rails Engine 的 Gem 项目
cd meta_generator_demo
vi meta_generator_demo.gemspec # 把里面的带 TODO 的都改成你准备填写的信息
mkdir -p lib/generators


cd your_rails_project
bundle exec rails g generator meta_generator_demo # 创建一个生成器
mv lib/generators/meta_generator_demo your_workspace/meta_generator_demo/lib/generators/meta_generator_demo # 修改成你自己的目录

cd your_workspace/meta_generator_demo # 修改成你自己的目录
vi lib/generators/meta_generator_demo/meta_generator_demo_generator.rb # 文件内容如下
# lib/generators/meta_generator_demo/meta_generator_demo_generator.rb
class MetaGeneratorDemoGenerator < Rails::Generators::NamedBase
  source_root File.expand_path('../templates', __FILE__)

  def create_demo_file
    create_file 'lib/generators/demo_generator.rb', <<-EOS
class DemoGenerator < Rails::Generators::Base
  desc "This generator creates an model file at app/models"
  def create_demo_file
    create_file "app/models/demo.rb", "class Demo; end"
  end
end
    EOS
  end
end

Meta Generator 已经编写完成,可以测试了.

cd your_rails_project
vi Gemfile # 添加 "gem 'meta_generator_demo', path: 'your_workspace/meta_generator_demo'" 到 Gemfile 里面,不包含 " 符号.
bundle install
bundle exec rails g # 是不是可以看到 meta_generator_demo 这个选项了?
bundle exec rails g meta_generator_demo Demo
bundle exec rails g # 是不是可以看到 demo 这个选项了?
bundle exec rails g demo # 是不是可以看到 demo 这个选项了?
cat app/models/demo.rb # 最终生成的文件, 如果需要改 demo.rb 生成的内容,只需要改 Rails 项目里的 lib/generators/demo_generator.rb 文件即可.

总结

  1. Gem 的 lib/generators/meta_generator_demo/meta_generator_demo_generator.rb 文件有个 create_demo_file 方法, 此方法在你的 Rails 项目生成 lib/generators/demo_generator.rb 文件.
  2. 生成的 lib/generators/demo_generator.rb 文件有个 create_demo_file 方法,此方法创建了 app/models.demo.rb 文件.

未完待续…