在多个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"