Ruby on Railsアプリケーションのネストされたリソースを作成する方法

前書き

Ruby on Railsは、https://www.digitalocean.com/community/tags/ruby [Ruby]で記述されたWebアプリケーションフレームワークであり、開発者にアプリケーション開発への意欲的なアプローチを提供します。 Railsを使用すると、開発者は次のことができます。

  • ルーティング、ステートフルデータ、資産管理などの処理に関する規則。

  • アプリケーションのロジックを分離するhttps://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller[model-view-controller](MCV)アーキテクチャパターンの基盤モデルでは、アプリケーション情報の提示とルーティングから。

Railsアプリケーションに複雑さを加えると、おそらくアプリケーションのビジネスロジックとデータベースとのインターフェースを表す複数のモデルを使用することになります。 関連モデルの追加とは、それらの間に意味のある関係を確立することを意味します。これにより、アプリケーションのコントローラーを介した情報の中継方法、およびビューを介したユーザーへの情報の取り込み方法が影響を受けます。

このチュートリアルでは、サメに関する事実をユーザーに提供する既存のRailsアプリケーションをベースに構築します。 このアプリケーションにはすでにサメのデータを処理するためのモデルがありますが、個々のサメに関する投稿用にネストされたリソースを追加します。 これにより、ユーザーは個々のサメについての幅広い考えと意見を構築できます。

前提条件

このチュートリアルを実行するには、次のものが必要です。

  • Ubuntu 18.04を実行しているローカルマシンまたは開発サーバー。 開発マシンには、管理権限を持つ非ルートユーザーと、「+ ufw +」で設定されたファイアウォールが必要です。 これを設定する方法については、https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04 [Ubuntu 18.04での初期サーバー設定]チュートリアルを参照してください。

  • ローカルマシンまたは開発サーバーにインストールされているhttps://nodejs.org [Node.js]およびhttps://www.npmjs.com/[npm]。 このチュートリアルでは、Node.jsバージョンとnpmバージョンを使用します。 Node.jsおよびnpmをUbuntu 18.04にインストールする方法については、https://www.digitalocean.com/community/tutorials/how-to-install-node-js-の「PPAを使用してインストールする」セクションの手順に従ってくださいon-ubuntu-18-04#installing-using-a-ppa [Ubuntu 18.04にNode.jsをインストールする方法]。

  • Ruby、https://github.com/rbenv/rbenv [rbenv]、およびローカルマシンまたは開発サーバーにインストールされているRails、https://www.digitalocean.com/community/tutorials/how-のステップ1〜4 to-install-ruby-on-rails-with-rbenv-on-ubuntu-18-04 [Ubuntu 18.04でrbenvを使用してRuby on Railsをインストールする方法]。 このチュートリアルでは、Ruby、rbenv、およびRailsを使用します。

  • Rubyのビルド方法の指示に従って、SQLiteがインストールされ、基本的なサメ情報アプリケーションが作成されました。 on Railsアプリケーション]。

ステップ1-入れ子モデルの足場

私たちのアプリケーションは、Active Record associationsを利用して、 + Shark +`モデルと `+ Post +`モデル間の関係を構築します。投稿は特定のサメに属し、それぞれサメは複数の投稿を持つことができます。 したがって、 `+ Shark +`および `+ Post +`モデルはhttps://guides.rubyonrails.org/association_basics.html#the-belongs-to-association [+ belongs_to `]およびhttps:// guidesを介して関連付けられます。 rubyonrails.org/association_basics.html#the-has-many-association [` has_many +`]アソシエーション。

この方法でアプリケーションを構築する最初のステップは、 `+ Post `モデルと関連リソースを作成することです。 これを行うには、 ` rails generate scaffold `コマンドを使用します。これにより、モデル、https://guides.rubyonrails.org/active_record_migrations.html [データベースの移行]が得られ、データベーススキーマ、コントローラー、標準のhttps://en.wikipedia.org/wiki/ [作成、読み取り、更新、削除](CRUD)操作を管理するためのビューの完全なセット、およびパーシャル、ヘルパー、テストのテンプレート。 これらのリソースを変更する必要がありますが、 ` scaffold +`コマンドを使用すると、開始点として使用できる構造が生成されるため、時間とエネルギーを節約できます。

最初に、前提条件で作成したRailsプロジェクトの `+ sharkapp +`ディレクトリにいることを確認します。

cd sharkapp

次のコマンドを使用して、 `+ Post +`リソースを作成します。

rails generate scaffold Post body:text shark:references

`+ body:text `を使用すると、 ` posts `データベーステーブル( ` Post `モデルにマッピングされるテーブル)に ` body `フィールドを含めるようにRailsに指示します。 また、 `:references `キーワードも含めています。これは、 ` Shark `モデルと ` Post `モデルの間の関連付けを設定します。 具体的には、これにより、 ` sharks `データベースの各サメエントリを表すhttps://en.wikipedia.org/wiki/Foreign_key[foreign key]が ` posts +`データベースに追加されます。

コマンドを実行すると、アプリケーション用にRailsが生成したリソースを確認する出力が表示されます。 先に進む前に、データベース移行ファイルを確認して、モデルとデータベーステーブルの間に存在する関係を確認できます。 次のコマンドを使用してファイルの内容を確認し、ここに表示されている内容を独自の移行ファイルのタイムスタンプに置き換えてください。

cat db/migrate/_create_posts.rb

次の出力が表示されます。

Outputclass CreatePosts < ActiveRecord::Migration[5.2]
 def change
   create_table :posts do |t|
     t.text :body


     t.timestamps
   end
 end
end

ご覧のとおり、表にはサメの外部キーの列が含まれています。 このキーは「+ _id 」の形式をとります-この例では「 _id +」です。

Railsは他の場所でもモデル間の関係を確立しています。 次のコマンドを使用して、新しく生成された `+ Post +`モデルを見てください。

cat app/models/post.rb
Outputclass Post < ApplicationRecord
 belongs_to :shark
end

`+ belongs_to +`アソシエーションは、宣言モデルの単一インスタンスが名前付きモデルの単一インスタンスに属するモデル間の関係を設定します。 このアプリケーションの場合、これは単一の投稿が単一のサメに属することを意味します。

この関係の設定に加えて、 `+ rails generate scaffold +`コマンドは、https://www.digitalocean.com/community/tutorials/how-to-buildのサメのリソースに対して行ったように、投稿のルートとビューも作成しました-a-ruby-on-rails-application#step-3-%E2%80%94-scaffolding-the-application [ステップ3]のhttps://www.digitalocean.com/community/tutorials/how-to- build-a-ruby-on-rails-application [Ruby on Railsアプリケーションの構築方法]。

これは便利な出発点ですが、モデルとルート間の関係が希望どおりに機能するためには、追加のルーティングを設定し、 `+ Shark +`モデルのアクティブレコードの関連付けを固める必要があります。

手順2-親モデルのネストされたルートと関連付けの指定

Railsは、 `+ rails generate scaffold `コマンドの `:references `キーワードのおかげで、 ` Post `モデルに ` belongs_to `の関連付けを既に設定していますが、その関係が適切に機能するためには、 ` Shark `モデルでも ` has_many +`アソシエーションを指定します。 また、投稿リソースをサメのリソースの子にするために、Railsが提供したデフォルトのルーティングを変更する必要があります。

`+ has_many `アソシエーションを ` Shark `モデルに追加するには、 ` nano `またはお気に入りのエディターを使用して ` app / models / shark.rb +`を開きます。

nano app/models/shark.rb

次の行をファイルに追加して、サメと投稿の関係を確立します。

〜/ sharkapp / app / models / shark.rb

class Shark < ApplicationRecord

 validates :name, presence: true, uniqueness: true
 validates :facts, presence: true
end

ここで考える価値のあることの1つは、特定のサメが削除されると投稿に何が起こるかです。 削除されたサメに関連する投稿がデータベースに保持されることは望ましくありません。 特定のサメに関連付けられている投稿がそのサメが削除されたときに確実に削除されるようにするには、関連付けに `+ dependent +`オプションを含めることができます。

次のコードをファイルに追加して、特定のサメでの `+ destroy +`アクションが関連する投稿を削除するようにします:

〜/ sharkapp / app / models / post.rb

class Shark < ApplicationRecord
 has_many :posts
 validates :name, presence: true, uniqueness: true
 validates :facts, presence: true
end

これらの変更が完了したら、ファイルを保存して閉じます。 + nano +`を使用している場合は、 `+ CTRL + X ++ Y +、次に `+ ENTER +`を押すことでこれを実行できます。

次に、 `+ config / routes.rb +`ファイルを開いて、リソースフルルート間の関係を変更します。

nano config/routes.rb

現在、ファイルは次のようになっています。

〜/ sharkapp / config / routes.rb

Rails.application.routes.draw do
 resources :posts
 resources :sharks

 root 'sharks#index'
 # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

現在のコードは、サメと関連する投稿の間のhttps://guides.rubyonrails.org/routing.html#nested-resources [依存関係]を表現したい場合、ルート間の独立した関係を確立します。

ルート宣言を更新して、 `:sharks +`を `:posts +`の親にします。 ファイル内のコードを次のように更新します。

〜/ sharkapp / config / routes.rb

Rails.application.routes.draw do
 resources
   resources

 root 'sharks#index'
 # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

編集が終了したら、ファイルを保存して閉じます。

これらの変更を適切に行ったら、 `+ posts +`コントローラーの更新に進むことができます。

ステップ3-投稿コントローラーの更新

モデル間の関連付けは、特定のサメに関連付けられた新しい投稿インスタンスを作成するために使用できるメソッドを提供します。 これらのメソッドを使用するには、投稿コントローラーを追加する必要があります。

投稿コントローラーファイルを開きます。

nano app/controllers/posts_controller.rb

現在、ファイルは次のようになっています。

〜/ sharkapp / controllers / posts_controller.rb

class PostsController < ApplicationController
 before_action :set_post, only: [:show, :edit, :update, :destroy]

 # GET /posts
 # GET /posts.json
 def index
   @posts = Post.all
 end

 # GET /posts/1
 # GET /posts/1.json
 def show
 end

 # GET /posts/new
 def new
   @post = Post.new
 end

 # GET /posts/1/edit
 def edit
 end

 # POST /posts
 # POST /posts.json
 def create
   @post = Post.new(post_params)

   respond_to do |format|
     if @post.save
       format.html { redirect_to @post, notice: 'Post was successfully created.' }
       format.json { render :show, status: :created, location: @post }
     else
       format.html { render :new }
       format.json { render json: @post.errors, status: :unprocessable_entity }
     end
   end
 end

 # PATCH/PUT /posts/1
 # PATCH/PUT /posts/1.json
 def update
   respond_to do |format|
     if @post.update(post_params)
       format.html { redirect_to @post, notice: 'Post was successfully updated.' }
       format.json { render :show, status: :ok, location: @post }
     else
       format.html { render :edit }
       format.json { render json: @post.errors, status: :unprocessable_entity }
     end
   end
 end

 # DELETE /posts/1
 # DELETE /posts/1.json
 def destroy
   @post.destroy
   respond_to do |format|
     format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
     format.json { head :no_content }
   end
 end

 private
   # Use callbacks to share common setup or constraints between actions.
   def set_post
     @post = Post.find(params[:id])
   end

   # Never trust parameters from the scary internet, only allow the white list through.
   def post_params
     params.require(:post).permit(:body, :shark_id)
   end
end

サメのコントローラーのように、このコントローラーのメソッドは関連する + Post +`クラスのインスタンスで動作します。 たとえば、 `+ new +`メソッドは `+ Post +`クラスの新しいインスタンスを作成し、 `+ index +`メソッドはクラスのすべてのインスタンスを取得し、 `+ set_post +`メソッドは `+ find +`と `+ params +を使用します+ id `で特定の投稿を選択します。 ただし、postインスタンスを特定のsharkインスタンスに関連付ける場合は、 ` Post +`クラスが現在独立したエンティティとして動作しているため、このコードを変更する必要があります。

変更では、次の2つのことを利用します。

  • モデルに + belongs_to +`および `+ has_many +`アソシエーションを追加したときに利用可能になったメソッド。 具体的には、定義した `+ has_many +`アソシエーションのおかげでhttps://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many [+ build ` method]にアクセスできるようになりました` Shark `モデルで。 このメソッドにより、 ` posts `データベースに存在する ` shark_id +`外部キーを使用して、特定のサメオブジェクトに関連付けられた投稿オブジェクトのコレクションを作成できます。

  • ネストされた `+ posts `ルートを作成したときに使用可能になったルートとルーティングヘルパー。 リソース間にネストされた関係を作成するときに使用可能になるサンプルルートの完全なリストについては、https://guides.rubyonrails.org/routing.html#nested-resources [Rails documentation]を参照してください。 とりあえず、特定のサメごとに(「 sharks / 」など)、そのサメに関連する投稿の関連ルート「 sharks // posts 」があることを知るだけで十分です。 これらのネストされたルートを参照する ` shark_posts_path(@shark)`や ` edit_sharks_posts_path(@shark)+`のようなルーティングヘルパーもあります。

ファイルでは、コントローラーの各アクションの前に実行されるメソッド「+ get_shark 」を作成することから始めます。 このメソッドは、 ` shark_id `でサメのインスタンスを見つけることにより、ローカルの ` @ shark +`インスタンス変数を作成します。 この変数をファイルで使用できるようにすると、他の方法で特定のサメに投稿を関連付けることができます。

ファイルの下部にある他の `+ private +`メソッドの上に、次のメソッドを追加します。

〜/ sharkapp / controllers / posts_controller.rb

. . .
private



 # Use callbacks to share common setup or constraints between actions.
. . .

次に、対応するフィルターを既存のフィルターの前に、ファイルの* top *に追加します。

〜/ sharkapp / controllers / posts_controller.rb

class PostsController < ApplicationController

これにより、ファイルで定義された各アクションの前に `+ get_shark +`が確実に実行されます。

次に、この `+ @ shark `インスタンスを使用して、 ` index `メソッドを書き換えることができます。 ` Post +`クラスのすべてのインスタンスを取得する代わりに、このメソッドが特定のサメインスタンスに関連付けられたすべてのpostインスタンスを返すようにします。

`+ index +`メソッドを次のように変更します。

〜/ sharkapp / controllers / posts_controller.rb

. . .
 def index
   @posts =
 end
. . .

新しい投稿インスタンスを特定のサメに関連付ける必要があるため、 `+ new `メソッドには同様のリビジョンが必要です。 これを実現するために、ローカルの ` @ shark `インスタンス変数とともに、 ` build +`メソッドを使用できます。

`+ new +`メソッドを次のように変更します。

〜/ sharkapp / controllers / posts_controller.rb

. . .
 def new
   @post =
 end
. . .

このメソッドは、 `+ get_shark +`メソッドから特定のサメインスタンスに関連付けられた投稿オブジェクトを作成します。

次に、 + new`に最も密接に関連するメソッドである + create`に対処します。 `+ create `メソッドは2つのことを行います:ユーザーが ` new `フォームに入力したパラメーターを使用して新しい投稿インスタンスを作成し、エラーがない場合はそのインスタンスを保存し、ルートヘルパーを使用してリダイレクトしますユーザーが新しい投稿を表示できる場所。 エラーの場合、 ` new +`テンプレートを再度レンダリングします。

次のように `+ create +`メソッドを更新します:

〜/ sharkapp / controllers / posts_controller.rb

 def create
   @post = (post_params)

       respond_to do |format|
        if @post.save
           format.html { redirect_to , notice: 'Post was successfully created.' }
           format.json { render :show, status: :created, location: @post }
        else
           format.html { render :new }
           format.json { render json: @post.errors, status: :unprocessable_entity }
     end
   end
 end

次に、 `+ update `メソッドを見てください。 このメソッドは ` @ post +`インスタンス変数を使用しますが、この変数はメソッド自体で明示的に設定されていません。 この変数はどこから来たのですか?

ファイルの上部にあるフィルターを見てください。 2番目の自動生成された `+ before_action +`フィルターは答えを提供します:

〜/ sharkapp / controllers / posts_controller.rb

class PostsController < ApplicationController
 before_action :get_shark
 before_action :set_post, only: [:show, :edit, :update, :destroy]
 . . .

+ update +`メソッド( `+ show ++ edit ++ destroy`など)は、 + set_post + メソッドから + @ post + `変数を受け取ります。 `+ get_shark `メソッドと他の ` private +`メソッドの下にリストされているこのメソッドは、現在次のようになっています。

〜/ sharkapp / controllers / posts_controller.rb

. . .
private
. . .
 def set_post
   @post = Post.find(params[:id])
 end
. . .

ファイルの他の場所で使用したメソッドに合わせて、このメソッドを変更して、 `+ @ post `が特定のサメに関連付けられた*コレクション*の投稿の特定のインスタンスを参照するようにする必要があります。 ここでは、 ` build `メソッドを念頭に置いてください-モデル間の関連付けと、これらの関連付けによって利用可能なメソッド( ` build +`など)のおかげで、各postインスタンスはコレクションの一部です特定のサメに関連付けられているオブジェクトの。 したがって、特定の投稿を照会するときに、特定のサメに関連付けられた投稿のコレクションを照会するのは理にかなっています。

次のように `+ set_post +`を更新します。

〜/ sharkapp / controllers / posts_controller.rb

. . .
private
. . .
 def set_post
   @post = (params[:id])
 end
. . .

`+ id `によって ` Post `クラス全体の特定のインスタンスを見つける代わりに、特定のサメに関連付けられた投稿のコレクションで一致する ` id +`を検索します。

そのメソッドを更新すると、 + update`および + destroy`メソッドを見ることができます。

`+ update `メソッドは ` set_post `の ` @ post `インスタンス変数を利用し、ユーザーが ` edit `フォームに入力した ` post_params `とともに使用します。 成功した場合は、特定のサメに関連付けられた投稿の ` index `ビューにRailsがユーザーを送り返すようにします。 エラーの場合、Railsは ` edit +`テンプレートを再度レンダリングします。

この場合、成功する更新を処理するために必要な変更は、 `+ redirect_to `ステートメントに対する変更のみです。 それを更新して ` shark_post_path(@shark)`にリダイレクトし、選択したサメの投稿の ` index +`ビューにリダイレクトします。

〜/ sharkapp / controllers / posts_controller.rb

. . .
 def update
   respond_to do |format|
     if @post.update(post_params)
       format.html { redirect_to , notice: 'Post was successfully updated.' }
       format.json { render :show, status: :ok, location: @post }
     else
       format.html { render :edit }
       format.json { render json: @post.errors, status: :unprocessable_entity }
     end
   end
 end
. . .

次に、 `+ destroy `メソッドに同様の変更を加えます。 成功した場合にリクエストを ` shark_posts_path(@shark)`にリダイレクトするように ` redirect_to +`メソッドを更新します:

〜/ sharkapp / controllers / posts_controller.rb

. . .
 def destroy
   @post.destroy
    respond_to do |format|
     format.html { redirect_to , notice: 'Post was successfully destroyed.' }
     format.json { head :no_content }
   end
 end
. . .

これが最後の変更です。 これで、次のような投稿コントローラーファイルが作成されました。

〜/ sharkapp / controllers / posts_controller.rb

class PostsController < ApplicationController
 before_action :get_shark
 before_action :set_post, only: [:show, :edit, :update, :destroy]

 # GET /posts
 # GET /posts.json
 def index
   @posts = @shark.posts
 end

 # GET /posts/1
 # GET /posts/1.json
 def show
 end

 # GET /posts/new
 def new
   @post = @shark.posts.build
 end

 # GET /posts/1/edit
 def edit
 end

 # POST /posts
 # POST /posts.json
 def create
   @post = @shark.posts.build(post_params)

       respond_to do |format|
        if @post.save
           format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully created.' }
           format.json { render :show, status: :created, location: @post }
        else
           format.html { render :new }
           format.json { render json: @post.errors, status: :unprocessable_entity }
     end
   end
 end

 # PATCH/PUT /posts/1
 # PATCH/PUT /posts/1.json
 def update
   respond_to do |format|
     if @post.update(post_params)
       format.html { redirect_to shark_post_path(@shark), notice: 'Post was successfully updated.' }
       format.json { render :show, status: :ok, location: @post }
     else
       format.html { render :edit }
       format.json { render json: @post.errors, status: :unprocessable_entity }
     end
   end
 end

 # DELETE /posts/1
 # DELETE /posts/1.json
 def destroy
   @post.destroy
   respond_to do |format|
     format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully destroyed.' }
     format.json { head :no_content }
   end
 end

 private

  def get_shark
    @shark = Shark.find(params[:shark_id])
  end
   # Use callbacks to share common setup or constraints between actions.
   def set_post
     @post = @shark.posts.find(params[:id])
   end

   # Never trust parameters from the scary internet, only allow the white list through.
   def post_params
     params.require(:post).permit(:body, :shark_id)
   end
end

コントローラは、情報がビューテンプレートからデータベースに、またその逆にどのように渡されるかを管理します。 コントローラーは、投稿が特定のサメに関連付けられている `+ Shark `モデルと ` Post +`モデルの関係を反映するようになりました。 次に、ビューテンプレート自体の変更に移ります。ここで、ユーザーは特定のサメに関する投稿情報を渡し、変更します。

ステップ4-ビューの変更

ビューテンプレートのリビジョンには、特定のサメに関連付けられた投稿をユーザーに表示するため、投稿に関連するテンプレートの変更と、サメの `+ show +`ビューの変更が含まれます。

投稿の基本的なテンプレートから始めましょう。複数の投稿テンプレートで再利用される「+ form +」パーシャルです。 今すぐそのフォームを開きます。

nano app/views/posts/_form.html.erb

`+ post `モデルのみを ` form_with `フォームヘルパーに渡すのではなく、 ` post `モデルを子リソースとして設定して、 ` shark `モデルと ` post +`モデルの両方を渡します。

サメと投稿リソースの関係を反映して、ファイルの最初の行を次のように変更します。

〜/ sharkapp / views / posts / _form.html.erb

<%= form_with(model: , local: true) do |form| %>
. . .

次に、関連するサメの `+ shark_id +`をリストするセクションを*削除*します。これはビューの必須情報ではないためです。

最初の行の編集が完了し、削除された `+ shark_id +`セクションのない完成したフォームは、次のようになります。

〜/ sharkapp / views / posts / _form.html.erb

<%= form_with(model: [@shark, post], local: true) do |form| %>
 <% if post.errors.any? %>
   <div id="error_explanation">
     <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>

     <ul>
     <% post.errors.full_messages.each do |message| %>
       <li><%= message %></li>
     <% end %>
     </ul>
   </div>
 <% end %>

 <div class="field">
   <%= form.label :body %>
   <%= form.text_area :body %>
 </div>

 <div class="actions">
   <%= form.submit %>
 </div>
<% end %>

編集が終了したら、ファイルを保存して閉じます。

次に、特定のサメに関連付けられている投稿を表示する「+ index +」ビューを開きます。

nano app/views/posts/index.html.erb

`+ rails generate scaffold `コマンドのおかげで、Railsはテンプレートの優れた部分を生成し、各投稿の ` body `フィールドとそれに関連する ` shark +`を示すテーブルを完成させました。

ただし、すでに変更した他のコードと同様に、このテンプレートは、モデルとコレクションとの関連付けとこれらの関連付けが提供するヘルパーメソッドを利用したい場合、投稿を独立したエンティティとして扱います。

表の本文で、次の更新を行います。

まず、 `+ post.shark `を ` post.shark.name +`に更新して、サメオブジェクト自体に関する情報を識別するのではなく、関連するサメの名前フィールドがテーブルに含まれるようにします。

〜/ sharkapp / app / views / posts / index.html.erb

. . .
 <tbody>
   <% @posts.each do |post| %>
     <tr>
       <td><%= post.body %></td>
       <td><%= post.shark %></td>
. . .

次に、 + Show`リダイレクトを変更して、関連するサメの + show s`ビューにユーザーを誘導します。これは、ユーザーが元のサメに戻る方法を必要とする可能性が高いためです。 Railsはコントローラーで作成されたインスタンス変数をすべてのビューで使用できるようにするため、ここでコントローラーで設定した `+ @ shark `インスタンス変数を使用できます。 また、ユーザーがその機能をよりよく理解できるように、リンクのテキストを「 Show」から「+ Show Shark」に変更します。

この行を次のように更新します。

〜/ sharkapp / app / views / posts / index.html.erb

. . .
 <tbody>
   <% @posts.each do |post| %>
     <tr>
       <td><%= post.body %></td>
       <td><%= post.shark.name %></td>
       <td><%= link_to 'Show ',  %></td>

次の行では、ユーザーが投稿を編集するときに正しいネストパスにルーティングされるようにします。 これは、ユーザーが `+ posts // edit `にリダイレクトされるのではなく、 ` sharks // posts // edit `にリダイレクトされることを意味します。 これを行うには、 ` shark_post_path +`ルーティングヘルパーと、RailsがURLとして扱うモデルを使用します。 また、機能を明確にするためにリンクテキストを更新します。

次のように `+ Edit +`行を更新します。

〜/ sharkapp / app / views / posts / index.html.erb

. . .
 <tbody>
   <% @posts.each do |post| %>
     <tr>
       <td><%= post.body %></td>
       <td><%= post.shark.name %></td>
       <td><%= link_to 'Show Shark', [@shark] %></td>
       <td><%= link_to 'Edit ',  %></td>

次に、同様の変更を `+ Destroy `リンクに追加し、文字列内の機能を更新し、 ` shark `および ` post +`リソースを追加します。

〜/ sharkapp / app / views / posts / index.html.erb

. . .
 <tbody>
   <% @posts.each do |post| %>
     <tr>
       <td><%= post.body %></td>
       <td><%= post.shark.name %></td>
       <td><%= link_to 'Show Shark', [@shark] %></td>
       <td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
       <td><%= link_to 'Destroy ', , method: :delete, data: { confirm: 'Are you sure?' } %></td>

最後に、フォームの下部で、ユーザーが新しい投稿を作成するときに適切なネストされたパスにユーザーを導くために、 `+ New Post `パスを更新します。 ファイルの最後の行を更新して、 ` new_shark_post_path(@shark)+`ルーティングヘルパーを使用します。

〜/ sharkapp / app / views / posts / index.html.erb

. . .
<%= link_to 'New Post',  %>

完成したファイルは次のようになります。

〜/ sharkapp / app / views / posts / index.html.erb

<p id="notice"><%= notice %></p>

<h1>Posts</h1>

<table>
 <thead>
   <tr>
     <th>Body</th>
     <th>Shark</th>
     <th colspan="3"></th>
   </tr>
 </thead>

 <tbody>
   <% @posts.each do |post| %>
     <tr>
       <td><%= post.body %></td>
       <td><%= post.shark.name %></td>
       <td><%= link_to 'Show Shark', [@shark] %></td>
       <td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
       <td><%= link_to 'Destroy Post', [@shark, post], method: :delete, data: { confirm: 'Are you sure?' } %></td>
     </tr>
   <% end %>
 </tbody>
</table>

<br>

<%= link_to 'New Post', new_shark_post_path(@shark) %>

編集が終了したら、ファイルを保存して閉じます。

ビューを投稿するために行う他の編集はそれほど多くありません。これは、他のビューが既に編集した「+ form 」パーシャルを使用するためです。 ただし、他の投稿テンプレートの ` link_to `参照を更新して、 ` form +`パーシャルに加えた変更を反映する必要があります。

`+ app / views / posts / new.html.erb +`を開きます:

nano app/views/posts/new.html.erb

ファイルの下部にある `+ link_to `参照を更新して、 ` shark_posts_path(@shark)+`ヘルパーを使用します。

〜/ sharkapp / app / views / posts / new.html.erb

. . .
<%= link_to 'Back',  %>

この変更が完了したら、ファイルを保存して閉じます。

次に、 `+ edit +`テンプレートを開きます:

nano app/views/posts/edit.html.erb

+ Back puthに加えて、ネストされたリソースを反映するように` + Shows`を更新します。 ファイルの最後の2行を次のように変更します。

〜/ sharkapp / app / views / posts / edit.html.erb

. . .
<%= link_to 'Show',  %> |
<%= link_to 'Back',  %>

ファイルを保存して閉じます。

次に、 `+ show +`テンプレートを開きます:

nano app/views/posts/show.html.erb

ファイルの下部にある `+ Edit `および ` Back +`パスに次の編集を加えます。

〜/ sharkapp / app / views / posts / edit.html.erb

. . .
<%= link_to 'Edit',  %> |
<%= link_to 'Back',  %>

完了したら、ファイルを保存して閉じます。

最後のステップとして、サメの `+ show +`ビューを更新して、個々のサメの投稿が表示されるようにします。 今すぐそのファイルを開きます。

nano app/views/sharks/show.html.erb

ここでの編集には、フォームに `+ Posts `セクションを追加し、ファイルの下部に ` Add Post +`リンクを追加します。

特定のサメの「+ Facts 」の下に、このサメに関連付けられた投稿のコレクション内の各インスタンスを反復処理する新しいセクションを追加し、各投稿の「 body +」を出力します。

フォームの `+ Facts +`セクションの下、およびファイルの下部のリダイレクトの上に次のコードを追加します。

〜/ sharkapp / app / views / sharks / show.html.erb

. . .
<p>
 <strong>Facts:</strong>
 <%= @shark.facts %>
</p>








<%= link_to 'Edit', edit_shark_path(@shark) %> |
. . .

次に、ユーザーがこの特定のサメの新しい投稿を追加できるように、新しいリダイレクトを追加します。

〜/ sharkapp / app / views / sharks / show.html.erb

. . .
<%= link_to 'Edit', edit_shark_path(@shark) %> |

<%= link_to 'Back', sharks_path %>

編集が終了したら、ファイルを保存して閉じます。

これで、投稿が常に特定のサメに関連付けられるように、アプリケーションのモデル、コントローラー、ビューに変更を加えました。 最後のステップとして、データベースに保存されるデータの一貫性を保証するために、 `+ Post +`モデルにいくつかの検証を追加できます。

ステップ5-検証の追加とアプリケーションのテスト

Step 5 of Ruby on Railsアプリケーションを構築する方法では、 + Shark +`モデルに検証を追加しました+ sharks `データベースに保存されるデータの均一性と一貫性を確保します。 同様に、「 posts +」データベースの保証も確保するために同様の手順を実行します。

`+ Post +`モデルが定義されているファイルを開きます:

nano app/models/post.rb

ここでは、投稿が空白にならないようにし、他のユーザーが投稿したコンテンツと重複しないようにします。 これを実現するには、次の行をファイルに追加します。

〜/ sharkapp / app / models / post.rb

class Post < ApplicationRecord
 belongs_to :shark

end

編集が終了したら、ファイルを保存して閉じます。

この最後の変更が完了すると、移行を実行してアプリケーションをテストする準備が整います。

まず、移行を実行します。

rails db:migrate

次に、サーバーを起動します。 ローカルで作業している場合は、次を実行して実行できます。

rails s

開発サーバーで作業している場合は、代わりに次のコマンドを実行します。

rails s --binding=

`+ http:// localhost:3000 `または ` http://:3000 +`でアプリケーションのルートに移動します。

必須のRailsプロジェクトチュートリアルでは、* Great White *サメのエントリを追加および編集します。 サメを追加していない場合、アプリケーションのランディングページは次のようになります。

image:https://assets.digitalocean.com/articles/rails_nested_resource/shark_post_landing_2.png [Shark App Landing Page]

  • Great White の名前の横にある Show をクリックします。 これにより、このサメの「+ show +」ビューに移動します。 サメの名前とその事実、およびコンテンツのない Posts *ヘッダーが表示されます。 フォームのこの部分を埋めるために投稿を追加しましょう。

[投稿]ヘッダーの下にある[投稿を追加]をクリックします。 これにより、投稿の「+ index +」ビューが表示され、*新しい投稿*を選択できます。

image:https://assets.digitalocean.com/articles/rails_nested_resource/new_post_landing.png [投稿インデックスビュー]

https://www.digitalocean.com/community/tutorials/how-to-build-a-ruby-on-rails-application#step-6--%E2%80%に配置した認証メカニズムのおかげで94-adding-authentication [ステップ6]のhttps://www.digitalocean.com/community/tutorials/how-to-build-a-ruby-on-rails-application[Ruby on Railsアプリケーションをビルドする方法]、新しいセッションを作成したかどうかに応じて、そのステップで作成したユーザー名とパスワードで認証するように求められる場合があります。

*新しい投稿*をクリックすると、投稿の「+ new +」テンプレートが表示されます。

image:https://assets.digitalocean.com/articles/rails_nested_resource/new_post_form.png [新しい投稿]

  • Body *フィールドに、「これらのサメは怖い!」と入力します

image:https://assets.digitalocean.com/articles/rails_nested_resource/new_shark_post_2.png [New Shark Post]

[投稿の作成]をクリックします。 このサメに属するすべての投稿の `+ index +`ビューにリダイレクトされます:

image:https://assets.digitalocean.com/articles/rails_nested_resource/post_success.png [投稿成功]

投稿リソースが機能することで、データ検証をテストして、必要なデータのみがデータベースに保存されることを確認できます。

`+ index +`ビューから、* New Post *をクリックします。 新しいフォームの[本文]フィールドに、「これらのサメは怖い!」ともう一度入力してみてください。

image:https://assets.digitalocean.com/articles/rails_nested_resource/new_shark_post_2.png [サメの繰り返し投稿]

[投稿の作成]をクリックします。 次のエラーが表示されます。

image:https://assets.digitalocean.com/articles/rails_nested_resource/post_unique_error.png [ユニークな投稿エラー]

[戻る]をクリックして、メインの投稿ページに戻ります。

他の検証をテストするには、[新しい投稿]をもう一度クリックします。 投稿を空白のままにして、[投稿の作成]をクリックします。 次のエラーが表示されます。

image:https://assets.digitalocean.com/articles/rails_nested_resource/post_blank_error.png [Blank Post Error]

ネストされたリソースと検証が適切に機能することで、さらなる開発の出発点として使用できる実用的なRailsアプリケーションができました。

結論

Railsアプリケーションを適切に配置すると、他のフロントエンドコンポーネントのスタイル設定や開発などの作業ができるようになります。 ルーティングとネストされたリソースの詳細を知りたい場合は、https://edgeguides.rubyonrails.org/routing.html [Rails documentation]から始めるのが最適です。

フロントエンドフレームワークとアプリケーションの統合の詳細については、https://www.digitalocean.com/community/tutorials/how-to-set-up-a-ruby-on-rails-project-withをご覧ください。 -a-react-frontend [ReactフロントエンドでRuby on Railsプロジェクトをセットアップする方法]。