mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
More improvements to generators guide.
This commit is contained in:
parent
0468201778
commit
5ecee1cd54
1 changed files with 42 additions and 17 deletions
|
@ -17,7 +17,7 @@ NOTE: This guide is about Rails generators for versions >= 3.0. Rails generators
|
||||||
|
|
||||||
h3. First contact
|
h3. First contact
|
||||||
|
|
||||||
When create an application using the +rails+ command, you are in fact using a Rails generator. After that, you can get a list of all available generators by just invoking +script/generate+:
|
When you create an application using the +rails+ command, you are in fact using a Rails generator. After that, you can get a list of all available generators by just invoking +script/generate+:
|
||||||
|
|
||||||
<shell>
|
<shell>
|
||||||
$ rails myapp
|
$ rails myapp
|
||||||
|
@ -104,16 +104,14 @@ Usage:
|
||||||
script/generate initializer NAME [options]
|
script/generate initializer NAME [options]
|
||||||
</shell>
|
</shell>
|
||||||
|
|
||||||
We can also see in our new generator that it has a class method called +source_root+. This method points to where our generator templates will be placed and by default it points to the created directory under +RAILS_APP/lib/generators/initializer/templates+. In order to understand what a generator template means, let's create one.
|
We can also see in our new generator that it has a class method called +source_root+. This method points to where our generator templates will be placed and by default it points to the created directory under +RAILS_APP/lib/generators/initializer/templates+. In order to understand what a generator template means, let's create a file at +RAILS_APP/lib/generators/initializer/templates/initializer.rb+ with the following content:
|
||||||
|
|
||||||
To do that, create a file at +RAILS_APP/lib/generators/initializer/templates/initializer.rb+ with the following content:
|
|
||||||
|
|
||||||
<ruby>
|
<ruby>
|
||||||
# Add initialization content here
|
# Add initialization content here
|
||||||
|
|
||||||
</ruby>
|
</ruby>
|
||||||
|
|
||||||
And now let's change the generator to use this template when invoked:
|
And now let's change the generator to copy this template when invoked:
|
||||||
|
|
||||||
<ruby>
|
<ruby>
|
||||||
class InitializerGenerator < Rails::Generators::NamedBase
|
class InitializerGenerator < Rails::Generators::NamedBase
|
||||||
|
@ -144,18 +142,18 @@ RAILS_APP/lib/generators
|
||||||
RAILS_APP/lib/rails_generators
|
RAILS_APP/lib/rails_generators
|
||||||
RAILS_APP/vendor/plugins/*/lib/generators
|
RAILS_APP/vendor/plugins/*/lib/generators
|
||||||
RAILS_APP/vendor/plugins/*/lib/rails_generators
|
RAILS_APP/vendor/plugins/*/lib/rails_generators
|
||||||
PATH_TO_GEMS/*/lib/generators
|
GEMS_PATH/*/lib/generators
|
||||||
PATH_TO_GEMS/*/lib/rails_generators
|
GEMS_PATH/*/lib/rails_generators
|
||||||
~/rails/generators
|
~/rails/generators
|
||||||
~/rails/rails_generators
|
~/rails/rails_generators
|
||||||
RAILS_GEM/lib/rails/generators
|
RAILS_GEM/lib/rails/generators
|
||||||
</shell>
|
</shell>
|
||||||
|
|
||||||
First Rails looks for generators in your application, then in plugins and/or gems, then in your home and finally the builtin generators. One thing very important to keep in mind is, that in Rails 3.0 and after, Rails only looks for generators in gems being used in your application. So if you have rspec installed as gem, but it's not declared in your application, Rails won't be able to invoke it.
|
First Rails looks for generators in your application, then in plugins and/or gems, then in your home and finally the builtin generators. One very important thing to keep in mind is that in Rails 3.0 and after it only looks for generators in gems being used in your application. So if you have rspec installed as a gem, but it's not declared in your application, Rails won't be able to invoke it.
|
||||||
|
|
||||||
h3. Customizing your workflow
|
h3. Customizing your workflow
|
||||||
|
|
||||||
Rails generators are flexible enough to let you customize your scaffold the way you want. In your +config/application.rb+ there is section just for generators:
|
Rails generators are flexible enough to let you customize your scaffold the way you want. In your +config/application.rb+ there is a section just for generators:
|
||||||
|
|
||||||
<ruby>
|
<ruby>
|
||||||
config.generators do |g|
|
config.generators do |g|
|
||||||
|
@ -196,7 +194,7 @@ $ ruby script/generate scaffold User name:string
|
||||||
create public/stylesheets/scaffold.css
|
create public/stylesheets/scaffold.css
|
||||||
</shell>
|
</shell>
|
||||||
|
|
||||||
Looking at this output, is easy to understand how generators work on Rails 3.0 and above. The scaffold generator actually doesn't generate anything, it just invokes others that does the work. This allows us to add/replace/remove any of those invocations. For instance, the scaffold generator invokes the scaffold_controller generator, which invokes erb, test_unit and helper generators. Since each generator has a single responsibility, their are easy to reuse, avoiding code duplication.
|
Looking at this output, is easy to understand how generators work on Rails 3.0 and above. The scaffold generator actually doesn't generate anything, it just invokes others to do the work. This allows us to add/replace/remove any of those invocations. For instance, the scaffold generator invokes the scaffold_controller generator, which invokes erb, test_unit and helper generators. Since each generator has a single responsibility, they are easy to reuse, avoiding code duplication.
|
||||||
|
|
||||||
Our first customization on the workflow will be to stop generating stylesheets and test fixtures on scaffold. We can achieve that by changing our application to the following:
|
Our first customization on the workflow will be to stop generating stylesheets and test fixtures on scaffold. We can achieve that by changing our application to the following:
|
||||||
|
|
||||||
|
@ -209,7 +207,7 @@ config.generators do |g|
|
||||||
end
|
end
|
||||||
</ruby>
|
</ruby>
|
||||||
|
|
||||||
If we generate another resource on scaffold, we can notice that stylesheets neither fixtures are created anymore. If you want to customize it further, for example to use +Datamapper+ and +Rspec+ instead of +ActiveRecord+ and +TestUnit+, is just a matter of adding their gems to your application and configuring your generators.
|
If we generate another resource on scaffold, we can notice that neither stylesheets nor fixtures are created anymore. If you want to customize it further, for example to use +Datamapper+ and +Rspec+ instead of +ActiveRecord+ and +TestUnit+, is just a matter of adding their gems to your application and configuring your generators.
|
||||||
|
|
||||||
To show that, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator:
|
To show that, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator:
|
||||||
|
|
||||||
|
@ -237,7 +235,7 @@ We can try out our new generator by creating a helper for users:
|
||||||
$ ruby script/generate my_helper users
|
$ ruby script/generate my_helper users
|
||||||
</shell>
|
</shell>
|
||||||
|
|
||||||
And it will generate:
|
And it will generate the following helper file in app/helpers:
|
||||||
|
|
||||||
<ruby>
|
<ruby>
|
||||||
module UsersHelper
|
module UsersHelper
|
||||||
|
@ -297,7 +295,7 @@ And now you can re-run scaffold for another resource and see it generating tests
|
||||||
|
|
||||||
h3. Customizing your workflow by changing generators templates
|
h3. Customizing your workflow by changing generators templates
|
||||||
|
|
||||||
In the step above, we simply wanted to add a line to the generated helper, without adding any extra functionality. There is a simpler to do that, and it's by replacing the templates of already existing generators.
|
In the step above, we simply wanted to add a line to the generated helper, without adding any extra functionality. There is a simpler way to do that, and it's by replacing the templates of already existing generators.
|
||||||
|
|
||||||
In Rails 3.0 and above, generators does not look only in the source root for templates, they also search for templates in other paths. And one of them is inside +RAILS_APP/lib/templates+. Since we want to customize +Rails::Generators::HelperGenerator+, we can do that by simple making a template copy inside +RAILS_APP/lib/templates/rails/helper+ with the name +helper.rb+. So let's create such file with the following content:
|
In Rails 3.0 and above, generators does not look only in the source root for templates, they also search for templates in other paths. And one of them is inside +RAILS_APP/lib/templates+. Since we want to customize +Rails::Generators::HelperGenerator+, we can do that by simple making a template copy inside +RAILS_APP/lib/templates/rails/helper+ with the name +helper.rb+. So let's create such file with the following content:
|
||||||
|
|
||||||
|
@ -307,7 +305,7 @@ module <%= class_name %>Helper
|
||||||
end
|
end
|
||||||
</erb>
|
</erb>
|
||||||
|
|
||||||
So now we can revert the changes in "config/application.rb":
|
So now we can revert the changes in +config/application.rb+:
|
||||||
|
|
||||||
<ruby>
|
<ruby>
|
||||||
config.generators do |g|
|
config.generators do |g|
|
||||||
|
@ -322,7 +320,7 @@ If you generate another resource, you can see that we got exactly the same resul
|
||||||
|
|
||||||
h3. Adding generators fallbacks
|
h3. Adding generators fallbacks
|
||||||
|
|
||||||
One last feature about generators which is quite useful for plugin generators is fallbacks. For example, imagine that you want to add a feature on top of TestUnit test framework, like "shoulda":http://github.com/thoughtbot/shoulda does. Since TestUnit already implements all generators required by Rails and shoulda just want to overwrite part of it, there is no need for shoulda reimplement some generators again, they can simply tell Rails to use a +TestUnit+ generator if none was found under +Shoulda+ namespace.
|
One last feature about generators which is quite useful for plugin generators is fallbacks. For example, imagine that you want to add a feature on top of TestUnit test framework, like "shoulda":http://github.com/thoughtbot/shoulda does. Since TestUnit already implements all generators required by Rails and shoulda just want to overwrite part of it, there is no need for shoulda to reimplement some generators again, they can simply tell Rails to use a +TestUnit+ generator if none was found under +Shoulda+ namespace.
|
||||||
|
|
||||||
We can easily simulate this behavior by changing our +config/application.rb+ once again:
|
We can easily simulate this behavior by changing our +config/application.rb+ once again:
|
||||||
|
|
||||||
|
@ -342,9 +340,36 @@ require 'rails/generators'
|
||||||
Rails::Generators.fallbacks[:shoulda] = :test_unit
|
Rails::Generators.fallbacks[:shoulda] = :test_unit
|
||||||
</ruby>
|
</ruby>
|
||||||
|
|
||||||
Now, if you invoke any resource, you will see that shoulda generators are being invoked, and at the end, they are just falling back to test unit generators.
|
Now, if create a Comment scaffold, you will see that shoulda generators are being invoked, and at the end, they are just falling back to test unit generators:
|
||||||
|
|
||||||
Such tool allows your generators to have single responsibility, increasing the code reuse and reducing the ammount of code duplication.
|
<shell>
|
||||||
|
$ ruby script/generate scaffold Comment body:text
|
||||||
|
invoke active_record
|
||||||
|
create db/migrate/20091120151323_create_comments.rb
|
||||||
|
create app/models/comment.rb
|
||||||
|
invoke shoulda
|
||||||
|
create test/unit/comment_test.rb
|
||||||
|
create test/fixtures/comments.yml
|
||||||
|
route map.resources :comments
|
||||||
|
invoke scaffold_controller
|
||||||
|
create app/controllers/comments_controller.rb
|
||||||
|
invoke erb
|
||||||
|
create app/views/comments
|
||||||
|
create app/views/comments/index.html.erb
|
||||||
|
create app/views/comments/edit.html.erb
|
||||||
|
create app/views/comments/show.html.erb
|
||||||
|
create app/views/comments/new.html.erb
|
||||||
|
create app/views/comments/_form.html.erb
|
||||||
|
create app/views/layouts/comments.html.erb
|
||||||
|
invoke shoulda
|
||||||
|
create test/functional/comments_controller_test.rb
|
||||||
|
invoke my_helper
|
||||||
|
create app/helpers/comments_helper.rb
|
||||||
|
invoke shoulda
|
||||||
|
create test/unit/helpers/comments_helper_test.rb
|
||||||
|
</shell>
|
||||||
|
|
||||||
|
Such tool allows your generators to have single responsibility, increasing the code reuse and reducing the amount of code duplication.
|
||||||
|
|
||||||
h3. Changelog
|
h3. Changelog
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue