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

提供:Dev Guides
移動先:案内検索

序章

Ruby on Rails は、 Ruby で記述されたWebアプリケーションフレームワークであり、開発者にアプリケーション開発への意見のあるアプローチを提供します。 Railsを使用すると、開発者は次のことができます。

  • ルーティング、ステートフルデータ、アセット管理などを処理するための規則。
  • model-view-controller (MCV)アーキテクチャパターンの確固たる基盤。これにより、モデル内にあるアプリケーションのロジックが、アプリケーション情報の表示とルーティングから分離されます。

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

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

前提条件

このチュートリアルに従うには、次のものが必要です。

  • Ubuntu18.04を実行しているローカルマシンまたは開発サーバー。 開発マシンには、管理者権限を持つroot以外のユーザーと、ufwで構成されたファイアウォールが必要です。 これを設定する方法については、 Ubuntu18.04を使用した初期サーバー設定のチュートリアルを参照してください。
  • Node.jsおよびnpmがローカルマシンまたは開発サーバーにインストールされています。 このチュートリアルでは、Node.jsバージョン10.16.3とnpmバージョン6.9.0を使用します。 Ubuntu 18.04にNode.jsとnpmをインストールする手順については、 Ubuntu18.04にNode.jsをインストールする方法の「PPAを使用したインストール」セクションの手順に従ってください。
  • Ubuntu18.04でrbenvを使用してRubyonRailsをインストールする方法の手順1〜4に従って、ローカルマシンまたは開発サーバーにインストールされたRuby、 rbenv 、およびRails。 このチュートリアルでは、Ruby 2.5.1 、rbenv 1.1.2 、およびRails 5.2.3を使用します。
  • Ruby on Railsアプリケーションの構築方法の指示に従って、SQLiteをインストールし、基本的なサメ情報アプリケーションを作成しました。

ステップ1—ネストされたモデルの足場

私たちのアプリケーションは、Active Recordアソシエーションを利用してSharkモデルとPostモデル間の関係を構築します。投稿は特定のサメに属し、各サメは複数の投稿を持つことができます。 したがって、SharkおよびPostモデルは、belongs_toおよびhas_manyの関連付けによって関連付けられます。

この方法でアプリケーションを構築するための最初のステップは、Postモデルと関連リソースを作成することです。 これを行うには、rails generate scaffoldコマンドを使用して、モデル、データベース移行を使用してデータベーススキーマ、コントローラー、標準を管理するためのビューのフルセットを提供します。 X187X] Create、Read、Update、およびDelete (CRUD)操作、およびパーシャル、ヘルパー、およびテスト用のテンプレート。 これらのリソースを変更する必要がありますが、scaffoldコマンドを使用すると、開始点として使用できる構造が生成されるため、時間とエネルギーを節約できます。

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

cd sharkapp

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

rails generate scaffold Post body:text shark:references

body:textを使用して、Railsにbodyフィールドをpostsデータベーステーブル(Postモデルにマップするテーブル)に含めるように指示しています。 :referencesキーワードも含まれています。これはSharkモデルとPostモデル間の関連付けを設定します。 具体的には、これにより、sharksデータベースの各サメエントリを表す外部キーpostsデータベースに追加されます。

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

cat db/migrate/20190805132506_create_posts.rb

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

Outputclass CreatePosts < ActiveRecord::Migration[5.2]
  def change
    create_table :posts do |t|
      t.text :body
      t.references :shark, foreign_key: true

      t.timestamps
    end
  end
end

ご覧のとおり、テーブルにはサメの外部キーの列が含まれています。 このキーはmodel_name_idの形式を取ります—この場合はshark_idです。

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

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

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

この関係の設定に加えて、rails generate scaffoldコマンドは、 How To Build Ruby on Railsのステップ3のサメリソースの場合と同様に、投稿のルートとビューも作成しました。アプリケーション。

これは便利なスタートですが、モデルとルートの関係が希望どおりに機能するためには、追加のルーティングを構成し、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
  has_many :posts
  validates :name, presence: true, uniqueness: true
  validates :facts, presence: true
end

ここで検討する価値のあることの1つは、特定のサメが削除されると投稿がどうなるかということです。 削除されたサメに関連付けられた投稿をデータベースに残したくない場合があります。 特定のサメが削除されたときに、そのサメに関連付けられている投稿が確実に削除されるように、dependentオプションを関連付けに含めることができます。

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

〜/ sharkapp / app / models / shark.rb

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

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

次に、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

現在のコードは、ルート間に独立した関係を確立しています。表現したいのは、サメとそれに関連する投稿の間の依存関係です。

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

〜/sharkapp/config/routes.rb

Rails.application.routes.draw do
  resources :sharks do
    resources :posts
  end
  root 'sharks#index'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

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

これらの変更を行うと、postsコントローラーの更新に進むことができます。

ステップ3—投稿コントローラーを更新する

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

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

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

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

私たちの変更は2つのことを利用します:

  • モデルにbelongs_toおよびhas_manyの関連付けを追加したときに使用可能になったメソッド。 具体的には、Sharkモデルで定義したhas_manyアソシエーションのおかげで、ビルドメソッドにアクセスできるようになりました。 このメソッドを使用すると、postsデータベースに存在するshark_id外部キーを使用して、特定のsharkオブジェクトに関連付けられたpostオブジェクトのコレクションを作成できます。
  • ネストされたpostsルートを作成したときに使用可能になったルートとルーティングヘルパー。 リソース間にネストされた関係を作成するときに使用可能になるルート例の完全なリストについては、Railsのドキュメントを参照してください。 今のところ、特定のサメ(たとえば、sharks/1)ごとに、そのサメに関連する投稿に関連付けられたルートsharks/1/postsがあることを知っていれば十分です。 これらのネストされたルートを参照するshark_posts_path(@shark)edit_sharks_posts_path(@shark)などのルーティングヘルパーもあります。

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

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

〜/ sharkapp / controllers / posts_controller.rb

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

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

〜/ sharkapp / controllers / posts_controller.rb

class PostsController < ApplicationController
  before_action :get_shark

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

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

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

〜/ sharkapp / controllers / posts_controller.rb

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

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

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

〜/ sharkapp / controllers / posts_controller.rb

. . . 
  def new
    @post = @shark.posts.build
  end
. . . 

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

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

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

〜/ sharkapp / controllers / posts_controller.rb

  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

次に、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メソッド(showeditdestroyなど)は、set_postメソッドから@post変数を取得します。 get_sharkメソッドと他のprivateメソッドの下にリストされているそのメソッドは、現在次のようになっています。

〜/ sharkapp / controllers / posts_controller.rb

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

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

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

〜/ sharkapp / controllers / posts_controller.rb

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

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

そのメソッドが更新されると、updateおよびdestroyメソッドを確認できます。

updateメソッドは、set_post@postインスタンス変数を使用し、ユーザーが[に入力したpost_paramsで使用します。 X150X]フォーム。 成功した場合は、Railsがユーザーを特定のサメに関連付けられた投稿のindexビューに戻すようにします。 エラーが発生した場合、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 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
. . .

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

〜/ sharkapp / controllers / posts_controller.rb

. . . 
  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
. . .

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

〜/ 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フォームヘルパーに渡すのではなく、sharkモデルとpostモデルの両方をpostとともに渡します。子リソースとして設定します。

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

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

<%= form_with(model: [@shark, post], local: true) do |form| %>
. . . 

次に、 delete は、関連するサメの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.sharkpost.shark.nameに更新します。これにより、テーブルには、サメオブジェクト自体に関する情報ではなく、関連付けられたサメの名前フィールドが含まれます。

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

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

次に、Showリダイレクトを変更して、関連するサメのshowビューにユーザーを誘導します。これは、元のサメに戻る方法が必要になる可能性が高いためです。 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 Shark', [@shark] %></td>

次の行では、ユーザーが投稿を編集するときに、正しいネストされたパスにルーティングされるようにします。 これは、ユーザーがposts/post_id/editに誘導されるのではなく、sharks/shark_id/posts/post_id/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 Post', edit_shark_post_path(@shark, post) %></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 Post', [@shark, post], 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', new_shark_post_path(@shark) %>

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

〜/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部分を使用しているため、それほど多くはありません。 ただし、formパーシャルに加えた変更を反映するために、他の投稿テンプレートのlink_to参照を更新する必要があります。

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', shark_posts_path(@shark) %>

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

次に、editテンプレートを開きます。

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

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

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

. . . 
<%= link_to 'Show', [@shark, @post] %> |
<%= link_to 'Back', shark_posts_path(@shark) %>

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

次に、showテンプレートを開きます。

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

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

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

. . .
<%= link_to 'Edit', edit_shark_post_path(@shark, @post) %> |
<%= link_to 'Back', shark_posts_path(@shark) %>

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

最後のステップとして、サメの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>

<h2>Posts</h2>
<% for post in @shark.posts %>
    <ul>
      <li><%= post.body %></li>
  </ul>
<% end %>

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

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

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

. . .
<%= link_to 'Edit', edit_shark_path(@shark) %> |
<%= link_to 'Add Post', shark_posts_path(@shark) %> |
<%= link_to 'Back', sharks_path %>

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

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

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

How To Build Ruby onRailsアプリケーションステップ5で、Sharkモデルに検証を追加して、に保存されるデータの均一性と一貫性を確保しました。 sharksデータベース。 postsデータベースの保証も確実にするために、同様の手順を実行します。

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

nano app/models/post.rb

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

〜/ sharkapp / app / models / post.rb

class Post < ApplicationRecord
  belongs_to :shark
  validates :body, presence: true, uniqueness: true
end

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

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

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

rails db:migrate

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

rails s

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

rails s --binding=your_server_ip

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

前提条件となるRailsプロジェクトのチュートリアルでは、 GreatWhiteサメのエントリを追加および編集する手順を説明しました。 これ以上サメを追加していない場合、アプリケーションのランディングページは次のようになります。

グレートホワイトの名前の横にある表示をクリックします。 これにより、このサメのshowビューに移動します。 サメの名前とその事実、およびコンテンツのないPostsヘッダーが表示されます。 フォームのこの部分に入力する投稿を追加しましょう。

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

Ruby on Railsアプリケーションの構築方法ステップ6で導入した認証メカニズムのおかげで、そのステップで作成したユーザー名とパスワードで認証を求められる場合があります、新しいセッションを作成したかどうかによって異なります。

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

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

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

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

indexビューで、新しい投稿をクリックします。 新しいフォームのBodyフィールドに、「これらのサメは怖いです!」と入力してみてください。 また:

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

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

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

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

結論

Railsアプリケーションを配置すると、他のフロントエンドコンポーネントのスタイリングや開発などに取り組むことができます。 ルーティングとネストされたリソースについて詳しく知りたい場合は、Railsドキュメントから始めるのが最適です。

フロントエンドフレームワークをアプリケーションに統合する方法の詳細については、Reactフロントエンドを使用してRubyonRailsプロジェクトをセットアップする方法を参照してください。