- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2017-03-13T15:38:59+09:00","default:wikiwriter","wikiwriter")
#author("2017-03-13T19:24:43+09:00","default:wikiwriter","wikiwriter")
&tag(Rails/プラグイン/チュートリアル);
*目次 [#r8006278]
#contents
*関連ページ [#k731fe49]
-[[Rails/プラグイン]]
*参考情報 [#beef44fa]
-https://railsguides.jp/engines.html
*エンジンプロジェクトの作成 [#w6819aae]
-以下のコマンドを実行する(rails-factoryディレクトリで実行)。
bundle exec rails plugin new ~/work/blorgh --mountable --skip-bundle
- "~/work/blorgh"ディレクトリに移動。
-blorgh.gemspecを編集してTODOを削除。
-bundle installを実行
bundle install --path=vendor/bundle
''ポイント''
-"--mountable"オプションを使用すると、ApplicationControllerやApplicationHelperが名前空間化される。ところが"-full"と違う。
-ダミーのテスト用アプリケーションが test/dummyに配置される。ダミーアプリケーションのルーティングファイルは、test/dummy/config/routes.rbとなる。
**エンジンの構成 [#c9d1c344]
-blorgh.gemspec。エンジンのルートディレクトリに存在。利用側から以下のように使う。
#pre{{
gem 'blorgh', path: "vendor/engines/blorgh"
}}
-アプリケーションあらはlib/blorgh.rbが読み込まれる。ここにプラグインごとの設定を記述するのもよい。
#pre{{
require "blorgh/engine"
module Blorgh
end
}}
-エンジンの基本ファイルはlib/blorgh/engine.rbのなかにある。
#pre{{
module Blorgh
class Engine < ::Rails::Engine
isolate_namespace Blorgh
end
end
}}
-これによってエンジンがRailsアプリにマウントされる。
-isolate_namespaceは名前空間の分離に重要。
-appディレクトリは通常のRailsアプリと同じ構成。
-testディレクトリはエンジンのテストを行うための場所。
-test/dummyにテスト用のRailsアプリが存在。このアプリはtest/dummy/config/routes.rbで以下のようにマウントしている。
#pre{{
Rails.application.routes.draw do
mount Blorgh::Engine => "/blorgh"
end
}}
-test/integrationに統合テスト。test/modelsを作成しても良い。
*エンジン機能を提供する [#wf8f5949]
**Articleリソースの作成 [#n9ae1e08]
-scaffoldを実行。ネームスペース"blorgh"が追加されていることに注意。
#pre{{
$ bundle exec rails generate scaffold article title:string text:text
invoke active_record
create db/migrate/20170313042107_create_blorgh_articles.rb
create app/models/blorgh/article.rb
invoke test_unit
create test/models/blorgh/article_test.rb
create test/fixtures/blorgh/articles.yml
invoke resource_route
route resources :articles
invoke scaffold_controller
create app/controllers/blorgh/articles_controller.rb
invoke erb
create app/views/blorgh/articles
create app/views/blorgh/articles/index.html.erb
create app/views/blorgh/articles/edit.html.erb
create app/views/blorgh/articles/show.html.erb
create app/views/blorgh/articles/new.html.erb
create app/views/blorgh/articles/_form.html.erb
invoke test_unit
create test/controllers/blorgh/articles_controller_test.rb
invoke helper
create app/helpers/blorgh/articles_helper.rb
invoke test_unit
invoke assets
invoke js
create app/assets/javascripts/blorgh/articles.js
invoke css
create app/assets/stylesheets/blorgh/articles.css
invoke css
create app/assets/stylesheets/scaffold.css
}}
-config/routes.rbが以下のように変更となる。
#pre{{
Blorgh::Engine.routes.draw do
resources :articles
end
}}
-コントローラー、ビュー、ヘルパーなども名前空間に分離されている。
-scaffoldで作成されたリソースファイルは、エンジンに適用されない。
-マイグレーション実行(Webサイトのようにbin/rails ではなくrakeでは?)
bundle exec rake db:migrate
-test/dummyディレクトリでrailsアプリが起動できるようになる。
bundle exec rails s
-次のURLにアクセス。http://localhost:3000/blorgh/articles
-エンジンルート/config/routes.rbに以下を追加
root to: "articles#index"
-すると http://localhost:3000/blorgh/ でアクセスできる。
**commentsリソースを作成する [#h34a456a]
***モデルの作成 [#dc6d7ff1]
-エンジンのルートディレクトリでモデルのジェネレータを実行する。
#pre{{
$ bundle exec bin/rails generate model Comment article_id:integer text:text
invoke active_record
create db/migrate/20170313044114_create_blorgh_comments.rb
create app/models/blorgh/comment.rb
invoke test_unit
create test/models/blorgh/comment_test.rb
create test/fixtures/blorgh/comments.yml
}}
-マイグレーション実行。
bundle exec rake db:migrate
-ビューの変更。app/views/blorgh/articles/show.html.erbを編集。Editリンクの前に以下を追加。
#pre{{
<h3>Comments</h3>
<%= render @article.comments %>
}}
-app/models/blorgh/article.rbに追加。
#pre{{
has_many :comments
}}
-記事を作成するためのフォームを作成。app/views/blorgh/articles/show.html.erbのrender @article.comments呼び出しの直後に以下の行を追加。
#pre{{
<%= render "blorgh/comments/form" %>
}}
-app/views/blorgh/commentsディレクトリに_form.html.erbを作成。
#pre{{
<h3>New comment</h3>
<%= form_for [@article, @article.comments.build] do |f| %>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<%= f.submit %>
<% end %>
}}
-コメント用のルーティングを追加。config/routes.rbを編集。
#pre{{
resources :articles do
resources :comments
end
}}
***コントローラーの作成 [#l31af821]
-scaffoldの実行。
#pre{{
$ bundle exec rails g controller comments
Expected string default value for '--helper'; got true (boolean)
Expected string default value for '--assets'; got true (boolean)
create app/controllers/blorgh/comments_controller.rb
invoke erb
exist app/views/blorgh/comments
invoke test_unit
create test/controllers/blorgh/comments_controller_test.rb
invoke helper
create app/helpers/blorgh/comments_helper.rb
invoke test_unit
invoke assets
invoke js
create app/assets/javascripts/blorgh/comments.js
invoke css
create app/assets/stylesheets/blorgh/comments.css
}}
-app/controllers/blorgh/comments_controller.rbを編集。ネストリソースの場合メインオブジェクトのidがパラメータとして(article_idとして)渡されてくる。
#pre{{
require_dependency "blorgh/application_controller"
module Blorgh
class CommentsController < ApplicationController
def create
@article = Article.find(params[:article_id])
@comment = @article.comments.create(comment_params)
flash[:notice] = "Comment has been created!"
redirect_to articles_path
end
private
def comment_params
params.require(:comment).permit(:text)
end
end
end
}}
-app/views/blorgh/comments/_comment.html.erbを作成。 render @article.commentの呼び出しによって。_commet.html.erbが自動で呼び出される。comment_counterはコレクションテンプレートの場合暗黙的に作られる。
#pre{{
<%= comment_counter + 1 %>. <%= comment.text %>
}}
-結局これによってコメントの番号とコメントのテキストが一覧表示されることになる。
*エンジンの作り込み[#l98d448e]
**mountable型の作成 [#h0335811]
***プロジェクトの作成 [#k3f40a79]
-以下のコマンドを実行
bundle exec rails plugin new ~/work/blorgh --mountable --skip-bundle
-blorgh.gemspecを編集してTODOを削除したあと、bundle installの実行
bundle install --path=vendor/bundle
***Articleリソースの作成 [#d01f6ff6]
-以下のコマンドを実行
bundle exec bin/rails generate scaffold article title:string text:text
-モデルやコントローラーにネームスペースが付与されていることに注意。
#pre{{
$ bundle exec bin/rails generate scaffold article title:string text:text
invoke active_record
create db/migrate/20161025072006_create_blorgh_articles.rb
create app/models/blorgh/article.rb
invoke test_unit
create test/models/blorgh/article_test.rb
create test/fixtures/blorgh/articles.yml
invoke resource_route
route resources :articles
invoke scaffold_controller
create app/controllers/blorgh/articles_controller.rb
invoke erb
create app/views/blorgh/articles
create app/views/blorgh/articles/index.html.erb
create app/views/blorgh/articles/edit.html.erb
create app/views/blorgh/articles/show.html.erb
create app/views/blorgh/articles/new.html.erb
create app/views/blorgh/articles/_form.html.erb
invoke test_unit
create test/controllers/blorgh/articles_controller_test.rb
invoke helper
create app/helpers/blorgh/articles_helper.rb
invoke test_unit
invoke assets
invoke js
create app/assets/javascripts/blorgh/articles.js
invoke css
create app/assets/stylesheets/blorgh/articles.css
invoke css
create app/assets/stylesheets/scaffold.css
}}
-miration実行
bundle exec rake db:migrate
-test/dummyディレクトリで実行。http://localhost:3000/blorgh/articlesでアクセスできる。
bundle exec rails s
***Commentリソースの生成 [#t6b759ed]
-記事1に対して複数のコメントがつけられる。
-以下のコマンドを実行。
#pre{{
$ bundle exec bin/rails generate model Comment article_id:integer text:text
invoke active_record
create db/migrate/20161025073042_create_blorgh_comments.rb
create app/models/blorgh/comment.rb
invoke test_unit
create test/models/blorgh/comment_test.rb
create test/fixtures/blorgh/comments.yml
}}
-migration実行
bundle exec rake db:migrate
-以下の概略。app/views/blorgh/articles/show.html.erbにコメント一覧とコメント追加用のフォームを追加する。
*エンジンを使用する [#h6c29c33]
**エンジンを使用するプロジェクトの作成 [#z12ddf05]
-以下のコマンドで作成
bundle exec rails new ~/work/unicorn --skip-bundle
-Gemfileを編集
#pre{{
gem 'devise'
gem 'blorgh', path: "/Users/sora/work/blorgh"
}}
-bundle installを実行
bundle install --path=vendor/bundle
-config/routes.rbを編集。
mount Blorgh::Engine, at: "/blog"
**エンジンの設定 [#v675394d]
-マイグレーションファイルのインストール
#pre{{
$ bundle exec rake railties:install:migrations
Copied migration 20170313063027_create_blorgh_articles.blorgh.rb from blorgh
Copied migration 20170313063028_create_blorgh_comments.blorgh.rb from blorgh
}}
-マイグレーション実行。
bundle exec rake db:migrate
-実行。http://localhost:3000/blog にアクセスする。
bundle exec rails s
**アプリケーションが提供するクラスを使用する [#sdfec224]
-アプリケーション側のクラスをエンジンから使いたい場合がある。例えばUser。ただしクラス名は固定したくない。
-とりあえずアプリケーション側でモデルクラスを作成。
#pre{{
bundle exec rails g model user name:string
bundle exec rake db:migrate
}}
-エンジン側ではauther_nameテキストフィールドを利用して、ユーザー名として保存する。エンジンのapp/views/blorgh/articles/_form.html.erbのタイトルフィールドの下に以下を追加。
#pre{{
<div class="field">
<%= f.label :author_name %><br>
<%= f.text_field :author_name %>
</div>
}}
-エンジンのarticles_controller.rbを修正。
#pre{{
def article_params
params.require(:article).permit(:title, :text, :author_name)
end
}}
-app/models/blorgh/article.rbにしかるべく修正を行う。
#pre{{
attr_accessor :author_name
belongs_to :author, class_name: "User"
before_validation :set_author
private
def set_author
self.author = User.find_or_create_by(name: author_name)
end
}}
-関連付けに必要になるauther_idをblorgh_articlesテーブルに追加。エンジンのディレクトリで実行
#pre{{
$ bin/rails g migration add_author_id_to_blorgh_articles author_id:integer
}}
-今度はアプリ側でマイグレーション実行。
#pre{{
$ bundle exec rake blorgh:install:migrations
$ bundle exec rake db:migrate
}}
-作者名を記事のページに表示する。エンジンのapp/views/blorgh/articles/show.html.erbのTitleの上に追加。
#pre{{
<p>
<b>Author:</b>
<%= @article.author %>
</p>
}}
-Userクラスにto_sを追加。
#pre{{
def to_s
name
end
}}