mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
a819211984
Add an after_bundle callback in Rails templates Conflicts: railties/CHANGELOG.md
266 lines
6.6 KiB
Markdown
266 lines
6.6 KiB
Markdown
Rails Application Templates
|
|
===========================
|
|
|
|
Application templates are simple Ruby files containing DSL for adding gems/initializers etc. to your freshly created Rails project or an existing Rails project.
|
|
|
|
After reading this guide, you will know:
|
|
|
|
* How to use templates to generate/customize Rails applications.
|
|
* How to write your own reusable application templates using the Rails template API.
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
Usage
|
|
-----
|
|
|
|
To apply a template, you need to provide the Rails generator with the location of the template you wish to apply using the -m option. This can either be a path to a file or a URL.
|
|
|
|
```bash
|
|
$ rails new blog -m ~/template.rb
|
|
$ rails new blog -m http://example.com/template.rb
|
|
```
|
|
|
|
You can use the rake task `rails:template` to apply templates to an existing Rails application. The location of the template needs to be passed in to an environment variable named LOCATION. Again, this can either be path to a file or a URL.
|
|
|
|
```bash
|
|
$ bin/rake rails:template LOCATION=~/template.rb
|
|
$ bin/rake rails:template LOCATION=http://example.com/template.rb
|
|
```
|
|
|
|
Template API
|
|
------------
|
|
|
|
The Rails templates API is easy to understand. Here's an example of a typical Rails template:
|
|
|
|
```ruby
|
|
# template.rb
|
|
generate(:scaffold, "person name:string")
|
|
route "root to: 'people#index'"
|
|
rake("db:migrate")
|
|
|
|
after_bundle do
|
|
git :init
|
|
git add: "."
|
|
git commit: %Q{ -m 'Initial commit' }
|
|
end
|
|
```
|
|
|
|
The following sections outline the primary methods provided by the API:
|
|
|
|
### gem(*args)
|
|
|
|
Adds a `gem` entry for the supplied gem to the generated application's `Gemfile`.
|
|
|
|
For example, if your application depends on the gems `bj` and `nokogiri`:
|
|
|
|
```ruby
|
|
gem "bj"
|
|
gem "nokogiri"
|
|
```
|
|
|
|
Please note that this will NOT install the gems for you and you will have to run `bundle install` to do that.
|
|
|
|
```bash
|
|
bundle install
|
|
```
|
|
|
|
### gem_group(*names, &block)
|
|
|
|
Wraps gem entries inside a group.
|
|
|
|
For example, if you want to load `rspec-rails` only in the `development` and `test` groups:
|
|
|
|
```ruby
|
|
gem_group :development, :test do
|
|
gem "rspec-rails"
|
|
end
|
|
```
|
|
|
|
### add_source(source, options = {})
|
|
|
|
Adds the given source to the generated application's `Gemfile`.
|
|
|
|
For example, if you need to source a gem from `"http://code.whytheluckystiff.net"`:
|
|
|
|
```ruby
|
|
add_source "http://code.whytheluckystiff.net"
|
|
```
|
|
|
|
### environment/application(data=nil, options={}, &block)
|
|
|
|
Adds a line inside the `Application` class for `config/application.rb`.
|
|
|
|
If `options[:env]` is specified, the line is appended to the corresponding file in `config/environments`.
|
|
|
|
```ruby
|
|
environment 'config.action_mailer.default_url_options = {host: "http://yourwebsite.example.com"}', env: 'production'
|
|
```
|
|
|
|
A block can be used in place of the `data` argument.
|
|
|
|
### vendor/lib/file/initializer(filename, data = nil, &block)
|
|
|
|
Adds an initializer to the generated application's `config/initializers` directory.
|
|
|
|
Let's say you like using `Object#not_nil?` and `Object#not_blank?`:
|
|
|
|
```ruby
|
|
initializer 'bloatlol.rb', <<-CODE
|
|
class Object
|
|
def not_nil?
|
|
!nil?
|
|
end
|
|
|
|
def not_blank?
|
|
!blank?
|
|
end
|
|
end
|
|
CODE
|
|
```
|
|
|
|
Similarly, `lib()` creates a file in the `lib/` directory and `vendor()` creates a file in the `vendor/` directory.
|
|
|
|
There is even `file()`, which accepts a relative path from `Rails.root` and creates all the directories/files needed:
|
|
|
|
```ruby
|
|
file 'app/components/foo.rb', <<-CODE
|
|
class Foo
|
|
end
|
|
CODE
|
|
```
|
|
|
|
That'll create the `app/components` directory and put `foo.rb` in there.
|
|
|
|
### rakefile(filename, data = nil, &block)
|
|
|
|
Creates a new rake file under `lib/tasks` with the supplied tasks:
|
|
|
|
```ruby
|
|
rakefile("bootstrap.rake") do
|
|
<<-TASK
|
|
namespace :boot do
|
|
task :strap do
|
|
puts "i like boots!"
|
|
end
|
|
end
|
|
TASK
|
|
end
|
|
```
|
|
|
|
The above creates `lib/tasks/bootstrap.rake` with a `boot:strap` rake task.
|
|
|
|
### generate(what, *args)
|
|
|
|
Runs the supplied rails generator with given arguments.
|
|
|
|
```ruby
|
|
generate(:scaffold, "person", "name:string", "address:text", "age:number")
|
|
```
|
|
|
|
### run(command)
|
|
|
|
Executes an arbitrary command. Just like the backticks. Let's say you want to remove the `README.rdoc` file:
|
|
|
|
```ruby
|
|
run "rm README.rdoc"
|
|
```
|
|
|
|
### rake(command, options = {})
|
|
|
|
Runs the supplied rake tasks in the Rails application. Let's say you want to migrate the database:
|
|
|
|
```ruby
|
|
rake "db:migrate"
|
|
```
|
|
|
|
You can also run rake tasks with a different Rails environment:
|
|
|
|
```ruby
|
|
rake "db:migrate", env: 'production'
|
|
```
|
|
|
|
### route(routing_code)
|
|
|
|
Adds a routing entry to the `config/routes.rb` file. In the steps above, we generated a person scaffold and also removed `README.rdoc`. Now, to make `PeopleController#index` the default page for the application:
|
|
|
|
```ruby
|
|
route "root to: 'person#index'"
|
|
```
|
|
|
|
### inside(dir)
|
|
|
|
Enables you to run a command from the given directory. For example, if you have a copy of edge rails that you wish to symlink from your new apps, you can do this:
|
|
|
|
```ruby
|
|
inside('vendor') do
|
|
run "ln -s ~/commit-rails/rails rails"
|
|
end
|
|
```
|
|
|
|
### ask(question)
|
|
|
|
`ask()` gives you a chance to get some feedback from the user and use it in your templates. Let's say you want your user to name the new shiny library you're adding:
|
|
|
|
```ruby
|
|
lib_name = ask("What do you want to call the shiny library ?")
|
|
lib_name << ".rb" unless lib_name.index(".rb")
|
|
|
|
lib lib_name, <<-CODE
|
|
class Shiny
|
|
end
|
|
CODE
|
|
```
|
|
|
|
### yes?(question) or no?(question)
|
|
|
|
These methods let you ask questions from templates and decide the flow based on the user's answer. Let's say you want to freeze rails only if the user wants to:
|
|
|
|
```ruby
|
|
rake("rails:freeze:gems") if yes?("Freeze rails gems?")
|
|
# no?(question) acts just the opposite.
|
|
```
|
|
|
|
### git(:command)
|
|
|
|
Rails templates let you run any git command:
|
|
|
|
```ruby
|
|
git :init
|
|
git add: "."
|
|
git commit: "-a -m 'Initial commit'"
|
|
```
|
|
|
|
### after_bundle(&block)
|
|
|
|
Registers a callback to be executed after the gems are bundled and binstubs
|
|
are generated. Useful for all generated files to version control:
|
|
|
|
```ruby
|
|
after_bundle do
|
|
git :init
|
|
git add: '.'
|
|
git commit: "-a -m 'Initial commit'"
|
|
end
|
|
```
|
|
|
|
The callbacks gets executed even if `--skip-bundle` and/or `--skip-spring` has
|
|
been passed.
|
|
|
|
Advanced Usage
|
|
--------------
|
|
|
|
The application template is evaluated in the context of a
|
|
`Rails::Generators::AppGenerator` instance. It uses the `apply` action
|
|
provided by
|
|
[Thor](https://github.com/erikhuda/thor/blob/master/lib/thor/actions.rb#L207).
|
|
This means you can extend and change the instance to match your needs.
|
|
|
|
For example by overwriting the `source_paths` method to contain the
|
|
location of your template. Now methods like `copy_file` will accept
|
|
relative paths to your template's location.
|
|
|
|
```ruby
|
|
def source_paths
|
|
[File.expand_path(File.dirname(__FILE__))]
|
|
end
|
|
```
|