Rails 使用 Meta Generator 打造你的 Rails Admin

cxh116 · August 08, 2017 · 2640 hits

按个人理解,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 文件。

Rails Admin Generator 示例

示例项目:https://github.com/adminonrails/aor

此项目已经弃坑,作为示例提供参考。抛砖引玉,希望高手们能定制出更加适合自己的方案

挖了这个坑,后面因为做的项目都是前后端分离,就没有再填了。另外觉得这个项目也比较鸡肋,对新手不友好,上手和定制有点难度。对高手来说,有自己的一套方式,一般是自己挖个坑。

大部分功能都有写单元测试,项目有在生产环境使用过。

项目介绍:

  • bootstrap: bootstrap 的静态资源,无 sass 依赖。
  • authentication: 提供登录验证的一些辅助方法,源码就一个文件。主要提供 logged_in?, current_user 等方法。参考老版 publify .
  • authorization: 基于 cancancan 提供后台权限验证的一些辅助方法。主要基于 controller_name 和 action_name 来限制。参考 spree 的后台验证逻辑。
  • theme: 代码生成器

使用请参考 test 和 dummy 目录测试代码。

theme 详解:

https://github.com/adminonrails/aor/blob/master/theme/Rakefile

上文件 DummyGenerator 部分,是一个新 rails 项目使用 aor 的主要流程,这里是用来每次运行 dummy rails 测试项目,先生成最新的 aor 代码。

  1. 生成 kaminari 的 bootstrap3 模板。
  2. 添加 cancan 的 AdmAbility 文件。
  3. 运行 aor:theme
  4. 生成 admin user model.

https://github.com/adminonrails/aor/blob/master/theme/lib/generators/aor/theme/theme_generator.rb

上文件主要在安装了 aor-theme gem,运行 aor:theme 命令的代码。

  1. 复制 admin js 和 css 文件。
  2. 添加公共的头部,侧边,表单验证错误提示文件。
  3. 添加 base admin controller 和 helper 文件。
  4. 把 admin.js 和 admin.css 添加到 assets 里,这样编译 js 和 css 会单独生成 admin 文件。
  5. 生成表单验证错误提示的 bootstrap 样式. 6 复制项目的 admin generator 到当前 rails 的 lib/generators 目录。

https://github.com/adminonrails/aor/tree/master/theme/lib/generators/aor/theme/templates/generator

此目录的文件,主要增强 rails 自带的 scaffold, scaffold_controller . 我们不覆盖 rails scaffold,只是添加一个自己的 admin:scaffold . 使用时运行 rails g admin:scaffold .

里面的 rb 文件逻辑,主要是修改 scaffold 的 source_paths 路径,优先使用我们的 controller 和 views 模板。

子目录 erb 和 rails 即是模板。

总结

此项目混合两种方式,一种是通过代码继承,子类通过重写父类方法来实现自定义。一种是生成代码,再修改生成的生成器代码,来实现自定义。

No Reply at the moment.
You need to Sign in before reply, if you don't have an account, please Sign up first.