在多个rails项目中,有时需要共享一些公用的component ,如果你不想通过拷贝文件的方式共享这些文件,那么自己动手是一种灵活而且很cool的方法。
以blog组件为例,过程如下
在lib下添加一个generators 的文件夹,再创建了一个blog的文件夹,这里有2个比较重要的东西,一个是生成器,一个是模板,简单的理解,生成器负责文件的拷贝,模板持有需要被拷贝的文件。
偶们先来看看生成器blog_generator.rb
class BlogGenerator < Rails::Generator::Base def manifest record do |m| # Controllers m.file "controllers/blog_controller.rb", "app/controllers/blog_controller.rb" # Models m.file "models/blog_post.rb", "app/models/blog_post.rb" # Helpers m.file "helpers/blog_helper.rb", "app/helpers/blog_helper.rb" # Views m.directory "app/views/blog" m.file "views/index.html.erb", "app/views/blog/index.html.erb" m.file "views/details.html.erb", "app/views/blog/details.html.erb" m.file "views/feed.rss.builder", "app/views/blog/feed.rss.builder" # Migration m.migration_template "migrate/create_blog.rb", "db/migrate" # Tests m.file "test/fixtures/blog_posts.yml", "test/fixtures/blog_posts.yml" m.file "test/functional/blog_controller_test.rb", "test/functional/blog_controller_test.rb" m.file "test/unit/blog_post_test.rb", "test/unit/blog_post_test.rb" # CSS and images m.file "assets/blog_styles.css", "public/stylesheets/px_blogger.css" m.file "assets/comment_add.gif", "public/images/comment_add.gif" m.file "assets/comment.gif", "public/images/comment.gif" m.readme "INSTALL" end end def file_name "create_blog" end end
以上代码的要点
1 directory 方法:创建文件夹,如果所需的文件夹不存在
2 file方法:拷贝一些文件到给定的文件夹
3 migration_template 方法:拷贝给定的migration文件(根据底部的file_name方法)到db/migrations文件夹
4 readme方法打印一些安装文件的内容
完毕后,文件结构应该如下所示
lib \- generators \- blog \- blog_generator.rb templates \- assets \- blog_styles.css comment_add.gif comment.gif controllers \- blog_controller.rb helpers \- blog_helper.rb INSTALL migrate \- create_blog.rb models \- blog_post.rb test \- fixtures \- blog_posts.yml functional \- blog_controller_test.rb unit \- blog_post_test.rb views \- index.html.erb details.html.erb feed.rss.builder USAGE
执行 script/generate blog 将会触发生成器运行.
另外你可以写出更高级一点的生成器,如果你的生成器继承Rails::Generator::NamedBase 而不是Rails::Generator::Base 的话,那么 你可以利用 template method 向模板传递参数,比如你运行script/generate Account,那么class_name
(返回 “Account”) and file_name
(返回 “account”),你需要修改你的控制器模板
class <%= class_name %>Controller < ApplicationController.
并且修改你的manifest
m.template "controllers/user_controller.rb", "app/controllers/#{file_name}_controller.rb"