Railsの各種ジェネレータとアプリケーションテンプレートは、定型コードを自動的に生成してワークフローを改善するツールとして非常に有用です。
このガイドの内容:
rails newコマンドでアプリケーションを作成すると、Railsのジェネレータが使われます。ジェネレータ(generator)は、アプリケーションの特定のファイルを作成し、定型コードの自動化を可能にします。
Railsアプリケーション内で以下のようにbin/rails generateコマンドを呼び出すと、利用可能なすべてのジェネレータのリストを取得できます。
$ rails new myapp $ cd myapp $ bin/rails generate Usage: bin/rails generate GENERATOR [args] [options] General options: -h, [--help] # Print generator's options and usage -p, [--pretend] # Run but do not make any changes -f, [--force] # Overwrite files that already exist -s, [--skip] # Skip files that already exist -q, [--quiet] # Suppress status output Please choose a generator below. Rails: application_record authentication benchmark channel controller generator ... SolidQueue: solid_queue:install Stimulus: stimulus TestUnit: test_unit:authentication test_unit:channel ...
Railsアプリケーションを新しく作成するときは、gem install railsでインストールしたバージョンのRailsを使うグローバルなrailsコマンドが使われますが、作成したアプリケーションのディレクトリ内では、アプリケーションにバンドルされているバージョンのRailsを使うbin/railsコマンドが使われる点が異なります。
上のコマンドによって、Railsで利用可能なすべてのジェネレータのリストと利用方法を表示できます。
ジェネレータを実行するときに、以下のように--pretend(または-p)オプションを付けて実行すると、ジェネレータがどのような処理を行うかを、ファイルを変更せずに確認できます。
$ bin/rails generate model product name:string --pretend invoke active_record create db/migrate/20260407190300_create_products.rb create app/models/product.rb invoke test_unit create test/models/product_test.rb create test/fixtures/products.yml
上記のファイルは、--pretendオプションを付けて実行した場合、実際には作成されません。
--pretendオプションは、関連するジェネレータが生成するファイルの差分を、実際に実行する前に確認するのに便利です。たとえば、modelとresourceジェネレータの違いを確認できます。
特定のジェネレータの詳しい説明を表示するには、以下のように--helpオプションを付けてジェネレータを呼び出します。
$ bin/rails generate scaffold --help Usage: bin/rails generate scaffold NAME [field[:type][:index] field[:type][:index]] [options] ... Description: Scaffolds an entire resource, from model and migration to controller and views, along with a full test suite. The resource is ready to use as a starting point for your RESTful, resource-oriented application. ... Examples: `bin/rails generate scaffold post` `bin/rails generate scaffold post title:string body:text published:boolean` `bin/rails generate scaffold purchase amount:decimal tracking_id:integer:uniq` `bin/rails generate scaffold user email:uniq password:digest` ...
--helpオプションを付けると詳しい利用方法や実行例が出力されるので、特定のジェネレータについて詳しく知るための良い情報源となります。
Railsでは、ジェネレータに加えて、カスタムジェネレータを構築する機能も提供されています。ここでは、config/initializers/フォルダ内にhello_generator.rbという名前のイニシャライザファイルを作成するジェネレータを作成してみましょう。最初は手動でジェネレータを作成し、次にgeneratorコマンドでジェネレータを作成する方法も見ていきます。
ジェネレータはThorをベースとして構築されています。Thorは解析機能などの便利なオプションやファイル操作用のAPIを提供するライブラリです。
ジェネレータを手書きするときの最初のステップとして、lib/generators/ディレクトリの下にinitializer_generator.rbという名前のファイルを以下の内容で作成します。
class InitializerGenerator < Rails::Generators::Base def create_initializer_file create_file "config/initializers/hello_generator.rb", <<~RUBY # hello_generator.rbファイルの内容をここに追加する RUBY end end
このジェネレータの名前は、ファイル名とRubyクラス名に基づいてinitializerとし、Rails::Generators::Baseクラスを継承しています。ジェネレータが呼び出されると、ジェネレータ内の各パブリックメソッドが定義された順序で順番に実行されます。
この新しいジェネレータは意図的にシンプルなものにしてあり、メソッド定義は1個しかありません。このメソッドはcreate_fileを呼び出し、指定された場所に指定の内容でファイルを作成します。
新しいジェネレータを呼び出すには、以下を実行します。
$ bin/rails generate initializer
これで、config/initializersフォルダ内にhello_generator.rbという空のファイルが作成されます。
次に進む前に、今作成したばかりのジェネレータの説明を表示してみましょう。
$ bin/rails generate initializer --help
通常は、ジェネレータがActiveRecord::Generators::ModelGeneratorのように名前空間化されていれば、実用的な説明文を生成できますが、今作成したジェネレータはそうなっていません。
この問題は2通りの方法で解決できます。1つ目の方法は、ジェネレータ内でdescメソッドを呼び出すことです。
class InitializerGenerator < Rails::Generators::Base desc "このジェネレータはconfig/initializersにイニシャライザファイルを作成します" def create_initializer_file create_file "config/initializers/hello_generator.rb", <<~RUBY # hello_generator.rbファイルの内容をここに追加する RUBY end end
これで、--helpを付けて新しいジェネレータを呼び出すと新しい説明文が表示されるようになりました。
説明文を追加する2つ目の方法は、ジェネレータと同じディレクトリにUSAGEという名前のファイルを作成することです。次に、この方法で実際に説明文を追加してみましょう。
Railsには、ジェネレータを生成するためのジェネレータもあります。
今作ったInitializerGeneratorを削除してから、bin/rails generate generatorを実行し、あらためてジェネレータを生成してみましょう。
$ rm lib/generators/initializer_generator.rb $ bin/rails generate generator initializer create lib/generators/initializer create lib/generators/initializer/initializer_generator.rb create lib/generators/initializer/USAGE create lib/generators/initializer/templates invoke test_unit create test/lib/generators/initializer_generator_test.rb
これで、以下のようなジェネレータが作成されます。
# lib/generators/initializer/initializer_generator.rb class InitializerGenerator < Rails::Generators::NamedBase source_root File.expand_path("templates", __dir__) end
上のジェネレータを見て最初に気付く点は、Rails::Generators::BaseではなくRails::Generators::NamedBaseを継承していることです。これは、このジェネレータを実行するには引数が1つ以上必要であることを意味します。この引数はイニシャライザ名で、コードはこのイニシャライザ名をnameで参照できます。
このことは、新しいジェネレータの説明文を表示してみると確認できます。
$ bin/rails generate initializer --help Usage: bin/rails generate initializer NAME [options]
次に、生成されたジェネレータにsource_rootという名前のクラスメソッドが含まれている点にもご注目ください。このメソッドは、ジェネレータのテンプレートの置き場所を指定するのに使われます。テンプレートファイルとは、ジェネレータがアプリケーション内に新しいファイルを作成するときの設計図として使うファイルのことです。テンプレートファイルは、デフォルトでは、作成されたlib/generators/initializer/templatesディレクトリに置かれます。
ジェネレータのテンプレートの機能を理解するために、lib/generators/initializer/templates/initializer.rbファイルを以下の内容で作成しましょう。
# 初期化用のコンテンツをここに追加する
次に、ジェネレータを以下のように変更して、ジェネレータが呼び出されたときにこのテンプレートをコピーするようにします。
# lib/generators/initializer/initializer_generator.rb class InitializerGenerator < Rails::Generators::NamedBase source_root File.expand_path("templates", __dir__) def copy_initializer_file copy_file "initializer.rb", "config/initializers/#{file_name}.rb" end end
それでは、このジェネレータを実行してみましょう。
$ bin/rails generate initializer core_extensions create config/initializers/core_extensions.rb $ cat config/initializers/core_extensions.rb # 初期化用のコンテンツをここに追加する
copy_fileによってconfig/initializers/core_extensions.rbが作成され、テンプレートの内容がコピーされたことがわかります(宛先パスで使われているfile_nameメソッドはRails::Generators::NamedBaseから継承されています)。
ジェネレータでコマンドラインオプションをサポートするには、以下のようにclass_optionメソッドを使います。
class InitializerGenerator < Rails::Generators::NamedBase class_option :scope, type: :string, default: "app" end
これで、--scopeオプションを指定してジェネレータを呼び出せるようになります。
$ bin/rails generate initializer theme --scope dashboard
これにより、デフォルト値の"app"が"dashboard"で上書きされます。
オプションの値は、ジェネレータ内のメソッドからoptionsでアクセスできます。
def copy_initializer_file @scope = options["scope"] copy_file "initializer.rb", "config/initializers/#{@scope}/#{file_name}.rb" end
これで、ジェネレータで--scopeオプションを設定すると、theme.rbファイルがconfig/initializers/dashboard/に生成されるようになりました。
Railsがジェネレータ名を解決するときは、複数のファイル名を使ってジェネレータを探索します。
たとえば、bin/rails generate initializer core_extensionsを実行すると、Railsはジェネレータが見つかるまで以下の順にファイルを探索します。
rails/generators/initializer/initializer_generator.rbgenerators/initializer/initializer_generator.rbrails/generators/initializer_generator.rbgenerators/initializer_generator.rbジェネレータがどのファイルにも見つからない場合は、エラーがraiseされます。
上の例でジェネレータのファイルをアプリケーションのlib/ディレクトリの下に置いた理由は、このディレクトリが$LOAD_PATH(Rubyがファイルを読み込むときに探索するディレクトリのリスト)に含まれているからです。これにより、Railsがこのファイルを検索して読み込めるようになります。
$LOAD_PATHはRubyによって初期化され、起動時にBundlerとRailsによって拡張されます。Bundlerは各gemに含まれているlib/ディレクトリを追加し、Railsはアプリケーションのlib/ディレクトリを追加します。これにより、そこに配置されたジェネレータが見つかるようになります。bin/rails runner 'puts $LOAD_PATH'を実行すると、完全な読み込みパスを確認できます。読み込みパスは、application.rbファイルのconfig.autoload_pathsで変更することも可能です。
config.generatorsを設定することで、Rails組み込みのジェネレータをオーバーライドできます。Railsアプリケーションの成長に応じて、生成されるコントローラに独自のメソッドを追加したり、生成されるビューのフォーマットを変更したりしたくなることもあるでしょう。
組み込みジェネレータをオーバーライドする方法の例として、scaffoldジェネレータの動作を詳しく見てみましょう。
$ bin/rails generate scaffold User name:string invoke active_record create db/migrate/20230518000000_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml invoke resource_route route resources :users invoke scaffold_controller create app/controllers/users_controller.rb invoke erb create app/views/users create app/views/users/index.html.erb create app/views/users/edit.html.erb create app/views/users/show.html.erb create app/views/users/new.html.erb create app/views/users/_form.html.erb create app/views/users/_user.html.erb invoke resource_route invoke test_unit create test/controllers/users_controller_test.rb create test/system/users_test.rb invoke helper create app/helpers/users_helper.rb invoke test_unit invoke jbuilder create app/views/users/index.json.jbuilder create app/views/users/show.json.jbuilder
この出力結果を見ると、scaffoldジェネレータが別のジェネレータ(scaffold_controllerなど)を実行していることがわかります。また、一部のジェネレータはさらに別のジェネレータを実行しています。特に、scaffold_controllerジェネレータはhelperジェネレータを実行しています。
組み込みのhelperジェネレータを新しいジェネレータでオーバーライドしてみましょう。新しいジェネレータの名前はmy_helperにします。
generatorコマンドを使って、ジェネレータをlib/generators/railsディレクトリの下に作成します。
$ bin/rails generate generator rails/my_helper create lib/generators/rails/my_helper create lib/generators/rails/my_helper/my_helper_generator.rb create lib/generators/rails/my_helper/USAGE create lib/generators/rails/my_helper/templates invoke test_unit create test/lib/generators/rails/my_helper_generator_test.rb
次に、lib/generators/rails/my_helper/my_helper_generator.rbファイルを開いて以下のジェネレータを定義します。
# lib/generators/rails/my_helper/my_helper_generator.rb class Rails::MyHelperGenerator < Rails::Generators::NamedBase def create_helper_file create_file "app/helpers/#{file_name}_helper.rb", <<~RUBY module #{class_name}Helper # 私はヘルパー end RUBY end end
最後に、組み込みのhelperジェネレータではなくmy_helperジェネレータを使うようRailsに指示する必要があります。これにはconfig.generators設定を使います。config/application.rbファイルに以下を追加しましょう。
config.generators do |g| g.helper :my_helper end
これで、scaffoldジェネレータをもう一度実行すると、my_helperジェネレータが動作していることがわかります。
$ bin/rails generate scaffold Article body:text ... invoke scaffold_controller ... invoke my_helper create app/helpers/articles_helper.rb ...
組み込みのhelperジェネレータの出力にはinvoke test_unitという行がありますが、今作ったmy_helperジェネレータにはありません。helperジェネレータはデフォルトではテストを生成しませんが、hook_forでテストを生成するためのフックを提供しています。MyHelperGeneratorクラスにhook_for :test_framework, as: :helperを追加すれば、これと同じことを実現できます。詳しくはhook_forのドキュメントを参照してください。
特定のジェネレータをオーバーライドする別の方法は、フォールバックを使う方法です。フォールバックを使うと、マッチするジェネレータが見つからない場合に、ジェネレータの名前空間を別のジェネレータの名前空間に委譲できます。
たとえば、my_test_unit:modelジェネレータを作成してtest_unit:modelジェネレータをオーバーライドしたいとします。しかし、test_unit:controllerジェネレータなどの他のtest_unit:*ジェネレータはオーバーライドしたくないとします。
このような場合、すべてのジェネレータをmy_test_unit名前空間に実装する代わりに、明示的に定義していないジェネレータについてはtest_unitにフォールバックするようにmy_test_unitを設定できます。
最初に、my_test_unit:modelジェネレータをlib/generators/my_test_unit/model/model_generator.rbファイルに作成します。
module MyTestUnit class ModelGenerator < Rails::Generators::NamedBase source_root File.expand_path("templates", __dir__) def do_different_stuff say "別の作業を実行中..." end end end
my_test_unitは、Rails組み込みのジェネレータをオーバーライドするのではなく、カスタム名前空間であるため、ここではlib/generators/rails/ディレクトリではなくlib/generators/my_test_unit/ディレクトリに配置しています。Railsは通常の読み込みパスの探索でこのジェネレータを見つけます。次のステップで、config.generatorsを使ってtest_frameworkとして登録する必要があります。
次に、config.generators設定を以下のように変更して、test_frameworkジェネレータをmy_test_unitに設定します。さらに、my_test_unit:*ジェネレータが見つからない場合はtest_unit:*ジェネレータに解決するフォールバックも設定します。
config.generators do |g| g.test_framework :my_test_unit, fixture: false g.fallbacks[:my_test_unit] = :test_unit end
これで、scaffoldジェネレータを実行すると、test_unitがmy_test_unitに置き換えられているものの、影響を受けたのはモデルのテストだけであることがわかります。
$ bin/rails generate scaffold Comment body:text invoke active_record create db/migrate/20230518000000_create_comments.rb create app/models/comment.rb invoke my_test_unit 別の作業を実行中... invoke resource_route route 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/comments/_comment.html.erb invoke resource_route invoke my_test_unit create test/controllers/comments_controller_test.rb create test/system/comments_test.rb invoke helper create app/helpers/comments_helper.rb invoke my_test_unit invoke jbuilder create app/views/comments/index.json.jbuilder create app/views/comments/show.json.jbuilder
モデルでのmy_test_unitジェネレータの呼び出しは、"別の作業を実行中..."と表示されるだけで、テストファイルは作成されません。これは、カスタムジェネレータがテストを作成していないためです。コントローラとヘルパーでのmy_test_unitの呼び出しはtest_unitにフォールバックするため、test/controllers/comments_controller_test.rbは通常通り生成されます。
Railsは、ジェネレータのテンプレートファイルを解決するときに、最初にアプリケーションのlib/templates/ディレクトリを探索し、それからジェネレータ自身のsource_rootディレクトリを探索します。つまり、lib/templates/ディレクトリに自分のバージョンのテンプレートを置くことで、Rails組み込みのジェネレータで使われるテンプレートをオーバーライドできるということです。
たとえば、コントローラのscaffoldテンプレートやビューのscaffoldテンプレートをオーバーライドできます。
これを実際に見るために、lib/templates/erb/scaffold/index.html.erb.ttファイルを作成して以下のコンテンツを追加してみましょう。なお、.ttという拡張子が追加されているのは、このファイルがThorによって最初に処理される必要があるジェネレータテンプレートであることをRailsに伝えるためです(.ttは"thor template"の略です)。
<%%= @<%= plural_table_name %>.count %> <%= human_name.pluralize %>
ここで作成するERBテンプレートは、そこからさらに別のERBテンプレートをレンダリングします。そのため、生成されるテンプレートに出力する<%は、ジェネレータのテンプレートで<%%のようにすべてエスケープしておく必要がある点にご注意ください。
それでは、Rails組み込みのscaffoldジェネレータを実行してみましょう。
$ bin/rails generate scaffold Post title:string ... create app/views/posts/index.html.erb ...
app/views/posts/index.html.erbファイルを開くと、以下のようになっているはずです。
<%= @posts.count %> Posts
アプリケーションテンプレートは、ジェネレータと若干異なる点があります。
ジェネレータは、既存のRailsアプリケーションにモデルやビューなどのファイルを追加しますが、アプリケーションテンプレートは、rails newコマンドで生成する新規Railsアプリケーションをその場で自動セットアップするのに使われます。アプリケーションテンプレートは、新しいRailsアプリケーションを生成した直後にカスタマイズを実行するRubyスクリプトであり、通常はtemplate.rbという名前です。
Railsアプリケーションをアプリケーションテンプレートで作成する方法を見てみましょう。
最初は、サンプルのRubyスクリプトテンプレートを作成してみましょう。
以下のテンプレートは、ユーザーに確認した後、GemfileにDeviseを追加し、Deviseユーザーモデル名を入力できるようにします。bundle installの実行後、テンプレートはDeviseジェネレータとマイグレーションを実行します。最後に、git addとgit commitを実行します。
# template.rb if yes?("Deviseをインストールしますか?") gem "devise" devise_model = ask("ユーザーモデル名は何にしますか?", default: "User") end after_bundle do if devise_model generate "devise:install" generate "devise", devise_model rails_command "db:migrate" end git add: ".", commit: %(-m 'Initial commit') end
rails newコマンドでこのテンプレートを使って新しいRailsアプリケーションを作成するには、以下のように-mオプションでテンプレートの場所を指定します。
$ rails new blog -m ~/template.rb
これで、新規Railsアプリケーションをblogという名前で作成するときに、Devise gemも設定されるようになります。
app:templateコマンドを使えば、既存のRailsアプリケーションにテンプレートを適用することも可能です。
この場合、テンプレートファイルの場所をLOCATION環境変数で指定する必要があります。
$ bin/rails app:template LOCATION=~/template.rb
テンプレートは必ずしもローカルに保存する必要はありません。ファイルパスの代わりに外部URLも指定できます。
$ rails new blog -m https://example.com/template.rb $ bin/rails app:template LOCATION=https://example.com/template.rb
第三者が提供するリモートスクリプトを実行するときは注意が必要です。テンプレートは単なるRubyスクリプトなので、ローカルコンピュータを危険にさらすコード(ウイルスのダウンロード、ファイルの削除、個人ファイルのサーバーへのアップロードなど)を簡単に仕込めてしまいます。
上述のtemplate.rbファイルでは、after_bundleやrails_commandなどのヘルパーメソッドを使い、yes?のようなユーザーインタラクティビティも追加しています。これらのメソッドはすべてRailsテンプレートAPIの一部です。これらのメソッドの利用例を以後のセクションで示します。
ジェネレータやテンプレートのRubyスクリプトは、DSL(ドメイン固有言語)を使ってさまざまなヘルパーメソッドにアクセスできます。これらのメソッドはRailsジェネレータAPIの一部であり、詳しくはThor::ActionsやRails::Generators::ActionsのAPIドキュメントで確認できます。
もう一つの典型的なRailsテンプレートの例を見てみましょう。このテンプレートはモデルをscaffoldで生成してからマイグレーションを実行し、変更をgitでコミットします。
# template.rb generate(:scaffold, "person name:string") route "root to: 'people#index'" rails_command("db:migrate") after_bundle do git :init git add: "." git commit: %Q{ -m 'Initial commit' } end
以下の例で使われているコードスニペットは、すべて上記のtemplate.rbファイルなどのテンプレートファイルで利用可能です。
add_sourceadd_sourceメソッドは、指定したソース(gemの取得元)を、生成されるアプリケーションのGemfileに追加します。
add_source "https://rubygems.org"
このメソッドにブロックを渡すと、ブロック内のgemエントリがソースグループにラップされます。
たとえば、gemを"http://gems.github.com"から取得する必要がある場合は以下のようにします。
add_source "http://gems.github.com/" do gem "rspec-rails" end
after_bundleafter_bundleメソッドは、gemのバンドルが完了した後に実行されるコールバックを登録します。
たとえば、tailwindcss-railsとdeviseのインストールコマンドは、それらのgemがバンドルされた後に実行するのが合理的です。
# gemをインストールする after_bundle do # TailwindCSSをインストールする rails_command "tailwindcss:install" # Deviseをインストールする generate "devise:install" end
このコールバックは、rails newコマンドで--skip-bundleオプションを指定した場合でも実行される点にご注意ください。
environmentenvironmentメソッドは、config/application.rbのApplicationクラス内に行を追加します。options[:env]が指定されている場合、その行はconfig/environments/ディレクトリ内の対応するファイルに追加されます。
environment 'config.action_mailer.default_url_options = {host: "http://yourwebsite.example.com"}', env: "production"
上のコードは、config/environments/production.rbに設定行を追加します。
gemgemメソッドは、指定のgemエントリを、生成されるアプリケーションのGemfileに追加します。
たとえば、アプリケーションをdevise gemとtailwindcss-rails gemに依存させる場合は、以下のようにします。
gem "devise" gem "tailwindcss-rails"
このメソッドは、gemをGemfileに追加するだけで、gemのインストールは行わない点にご注意ください。
gemのバージョンも指定できます。
gem "devise", "~> 4.9.4"
Gemfileにコメント付きでgemを追加することも可能です。
gem "devise", comment: "Add devise for authentication."
gem_groupgem_groupメソッドは、gemエントリをグループにラップします。
たとえば、rspec-railsをdevelopmentグループとtestグループでのみ読み込むには、以下のようにします。
gem_group :development, :test do gem "rspec-rails" end
generategenerateメソッドを使うと、template.rbファイル内でRailsジェネレータを呼び出せます。
たとえば、scaffoldジェネレータを呼び出してPersonモデルを生成するには、以下のようにします。
generate(:scaffold, "person", "name:string", "address:text", "age:number")
gitgitヘルパーメソッドを使うと、Railsテンプレート内で任意のgitコマンドを実行できます。
git :init git add: "." git commit: "-a -m 'Initial commit'"
initializer、vendor、lib、fileinitializerヘルパーメソッドは、生成されるアプリケーションのconfig/initializers/ディレクトリにイニシャライザファイルを追加します。
template.rbファイルに以下のコードを追加すると、アプリケーションでObject#not_nil?とObject#not_blank?を使えるようになります。
initializer "not_methods.rb", <<-CODE class Object def not_nil? !nil? end def not_blank? !blank? end end CODE
同様に、libメソッドはファイルをlib/ディレクトリに作成し、vendorメソッドはファイルをvendor/ディレクトリに作成します。
fileメソッドはcreate_fileのエイリアスです。これはRails.rootからの相対パスを受け取って、必要なディレクトリとファイルをすべて作成します。
file "app/components/foo.rb", <<-CODE class Foo end CODE
上のコードはapp/components/ディレクトリを作成し、その中にfoo.rbを配置します。
rakefilerakefileメソッドは、指定のタスクを含む新しいRakeファイルをlib/tasks/ディレクトリに作成します。
rakefile("bootstrap.rake") do <<-TASK namespace :boot do task :strap do puts "I like boots!" end end TASK end
上のコードは、lib/tasks/bootstrap.rakeファイルを作成し、boot:strap rakeタスクを定義します。
runrunメソッドは、任意のコマンドを実行します。
たとえば、README.rdocファイルを削除したい場合は、以下のようにします。
run "rm README.rdoc"
rails_commandrails_commandメソッドを使うと、生成されるアプリケーションでRailsコマンドを実行できます。
たとえば、テンプレートのRubyスクリプト内でデータベースをマイグレーションしたい場合は、以下のようにします。
rails_command "db:migrate"
Railsの環境を指定してコマンドを実行することも可能です。
rails_command "db:migrate", env: "production"
abort_on_failureオプションを指定することで、コマンド実行に失敗した場合はアプリケーションの生成を中止することも可能です。
rails_command "db:migrate", abort_on_failure: true
routerouteメソッドは、config/routes.rbファイルにエントリを追加します。
アプリケーションのデフォルトページをPeopleController#indexにするには、以下を追加します。
route "root to: 'people#index'"
この他にも、copy_file、create_file、insert_into_file、insideなどのローカルファイルシステムを操作するヘルパーメソッドが多数用意されています。詳しくはThorのAPIドキュメントを参照してください。
以下にそのようなメソッドの例を示します。
insideinsideメソッドは、コマンドを指定のディレクトリ内から実行できるようにします。
たとえば、新しいアプリケーションからedge railsのコピーへのシンボリックリンクを作成したい場合は、以下のようにします。
inside("vendor") do run "ln -s ~/my-forks/rails rails" end
この他に、ask、yes?、no?など、Rubyテンプレートからユーザーと対話できるメソッドも利用できます。すべてのユーザー対話メソッドについては、Thorのシェルドキュメントで確認できます。
以下にask、yes?、no?の例を示します。
askaskメソッドを使うと、ユーザーからの入力を受け取ってテンプレートで利用できます。
たとえば、新しいライブラリの名前をユーザーに尋ねたい場合は、以下のようにします。
lib_name = ask("新しいライブラリの名前を入力してください:") lib_name << ".rb" unless lib_name.index(".rb") lib lib_name, <<-CODE class Shiny end CODE
yes?とno?yes?メソッドやno?メソッドを使って、yes/noで答えられる質問を手軽にユーザーに表示して、ユーザーの回答に応じて処理の流れを決められます。
たとえば、ユーザーにマイグレーションを実行するかどうか尋ねたい場合は、以下のようにします。
rails_command("db:migrate") if yes?("マイグレーションを実行しますか?") # no?メソッドはyes?メソッドの逆の動作
Railsは、Rails::Generators::Testing::Behaviorで以下のようなテストヘルパーメソッドを提供しています。
ジェネレータをテストする場合、デバッグツールが機能するために以下のようにコマンドでRAILS_LOG_TO_STDOUT=trueを指定する必要があります。
RAILS_LOG_TO_STDOUT=true ./bin/test test/generators/actions_test.rb
Railsではその他にも、Rails::Generators::Testing::Assertionsで追加のアサーションを提供しています。
Railsガイドは GitHub の yasslab/railsguides.jp で管理・公開されております。本ガイドを読んで気になる文章や間違ったコードを見かけたら、気軽に Pull Request を出して頂けると嬉しいです。Pull Request の送り方については GitHub の README をご参照ください。
原著における間違いを見つけたら『Rails のドキュメントに貢献する』を参考にしながらぜひ Rails コミュニティに貢献してみてください 🛠💨✨
本ガイドの品質向上に向けて、皆さまのご協力が得られれば嬉しいです。
Railsガイド運営チーム (@RailsGuidesJP)
Railsガイドは下記の協賛企業から継続的な支援を受けています。もしご興味あれば、協賛プランから気軽にお問い合わせいただけると嬉しいです。