はじめに
2024年2月からプログラミン学習を始めたばかりなので間違ったことを記載している可能性もあります。間違っている部分やアドバイスがありましたらご指摘していただけたら幸いです。
また、今回の記事は以下の記事の続きになっています。
前提
ruby
rails
gem device
上記の環境で作成します。
実装
今回は顧客側で投稿をする際に使用するジャンルの追加・編集ができるよう管理者側にジャンル投稿機能を実装したいと思います。
テーブルの追加
Model名は大文字から始まる単数形になります
今回は投稿のジャンル名をtitileカラムとして作成をします。
rails g model Genre title:string
マイグレーションファイルを確認し少し編集します。
class CreateGenres < ActiveRecord::Migration[7.1]
def change
create_table :genres do |t|
t.string :title, null: false #追記
t.timestamps
end
end
end
このカラムには必ず値が入っていないといけないため、null: false 制約をつけて空の値を許可されないようにします。
データベースに反映させる
データベースにテーブルを作成しカラムを追加する。
rails db:migrate
コントローラーの追加
今回は、新規投稿機能と一覧機能を同じビュー内で完結させる予定なので以下のようにします。
rails g controller admin/genres index show create edit update
そうすると対応のビューとコントローラーが作成されます。
class Admin::GenresController < ApplicationController
def index
end
def show
end
def create
end
def edit
end
def update
end
end
必要のないビューもありますが、最後に削除することにします。
コントローラーの編集
class Admin::GenresController < ApplicationController
def index
@genres = Genre.all
@genre = Genre.new
end
def show
@genres = Genre.all
redirect_to edit_admin_genre_path(params[:id])
end
def create
@genre = Genre.new(genre_params)
@genres = Genre.all
if @genre.save
flash[:notice] = "ジャンルを追加しました。"
redirect_to admin_genres_path
else
flash.now[:alert] = "ジャンルの追加に失敗しました。"
render :index
end
end
def edit
@genres = Genre.all
@genre = Genre.find(params[:id])
end
def update
@genres = Genre.all
@genre = Genre.find(params[:id])
if @genre.update(genre_params)
flash[:notice] = "ジャンルを変更しました。"
redirect_to admin_genres_path
else
flash.now[:alert] = "ジャンルの変更に失敗しました。"
render :edit
end
end
private
def genre_params
params.require(:genre).permit(:title)
end
end
コントローラーの詳細
管理者向けのジャンルに関するCRUD操作(作成、読み取り、更新、削除)を提供するものです。以下に各アクションとその役割について詳しく解説します。
※今回は削除機能を設けません。
indexアクション
- すべてのジャンル(@genres)を取得します
- 新しいジャンルを作成するためのオブジェクト(@genre)を初期化します
- このアクションは通常、ジャンル一覧と新規作成フォームを表示するビューに対応します
showアクション:
- すべてのジャンルを取得します
- 指定されたジャンルの編集ページにリダイレクトします(edit_admin_genre_path)
- showアクションは通常詳細表示を行いますが、このコードでは編集ページにリダイレクトしています
createアクション
- 新しいジャンルオブジェクトを作成し、パラメーターから値を設定します(@genre)
- すべてのジャンルを取得します
- ジャンルが正常に保存された場合、成功メッセージを表示し、ジャンル一覧ページにリダイレクトします
- 保存に失敗した場合、エラーメッセージを表示し、indexビューを再表示します
editアクション
- すべてのジャンルを取得します
- 指定されたIDのジャンルを取得します(@genre)
- このアクションは通常、ジャンルの編集フォームを表示するビューに対応します
updateアクション
- すべてのジャンルを取得します
- 指定されたIDのジャンルを取得します
- ジャンルの更新が成功した場合、成功メッセージを表示し、ジャンル一覧ページにリダイレクトします
- 更新に失敗した場合、エラーメッセージを表示し、editビューを再表示します
プライベートメソッド(genre_paramsメソッド)
- ストロングパラメーターとして、許可されたジャンルの属性(title)を定義します
- 外部からの不正な入力を防ぐために、パラメーターを制限します
ルーティングの編集
namespace :admin do
resources :genres, only: [:index, :show, :create, :edit, :update] #追加
get 'genres/index' #削除
get 'genres/show' #削除
get 'genres/create' #削除
get 'genres/edit' #削除
get 'genres/update' #削除
resources :posts
end
念のため、'rails routes'で確認
ビューの編集
新規投稿・一覧画面(/admin/genres)
<h3>ジャンル一覧・追加</h3>
<%= form_with url: admin_genres_path, model: @genre, class: "mb-4" do |g| %>
<div>
<%= g.text_field :title, placeholder: 'ジャンル' %>
</div>
<%= g.submit '新規登録' %>
<% end %>
<div>
<% @genres.each do |ge| %>
<%= link_to edit_admin_genre_path(ge) do %>
<%= ge.title %>
<% end %>
<% end %>
</div>
詳細
- form_with: ジャンルの新規登録フォームを作成するために使用されるヘルパーです。urlはフォームの送信先のURL (admin_genres_path) を指定し、modelはフォームに関連付けるモデル (@genre) を指定します。
- g.text_field :title, placeholder: 'ジャンル':ジャンルの名前を入力するためのテキストフィールドです。プレースホルダーに「ジャンル」と表示されます。
- g.submit '新規登録': フォームを送信するためのボタンです。「新規登録」と表示されます。
- @genres.each do |ge|: @genres配列の各ジャンル (ge) について繰り返し処理を行います。
- link_to edit_admin_genre_path(ge) do: 各ジャンルタイトルにリンクを設定します。このリンクをクリックすると、ジャンルの編集ページ (edit_admin_genre_path(ge)) に移動します。
- <%= ge.title %>: ジャンルのタイトルを表示します。
編集画面(/admin/genres/〇/edit)
<div>
<div>
<div>
<h3>ジャンル編集</h3>
<%= form_with url: admin_genre_path, method: :patch, model: @genre do |g| %>
<div>
<%= g.text_field :title, placeholder: 'ジャンル' %>
</div>
<%= g.submit '保存' %>
<% end %>
</div>
</div>
</div>
詳細
- form_with: フォームを作成するためのヘルパーメソッドです。
- url: admin_genre_path: フォームの送信先URLを指定します。admin_genre_path は編集アクションに対応するURLです。
- method: :patch: HTTPメソッドをPATCHに設定します。PATCHはリソースの部分的な更新に使用されます。
- model: @genre: フォームに関連付けるモデル (@genre) を指定します。これにより、フォームフィールドがモデルの属性にバインドされます。
- <%= g.text_field :title, placeholder: 'ジャンル' %>: ジャンルの名前を入力するためのテキストフィールドです。プレースホルダーには「ジャンル」と表示されます。
- g.submit '保存': フォームの送信ボタンです。「保存」というラベルが表示されます。
ビューの編集が完了しました。
最後にバリデーションの定義します。
モデルの編集
class Genre < ApplicationRecord
validates :title, presence: true, uniqueness: true
end
詳細
- validates :title: title属性に対してバリデーションを設定します。
- presence: true: titleが空でないことを検証します。空の値(nilまたは空文字列)を保存しようとするとバリデーションエラーになります。
- uniqueness: true: titleが一意であることを検証します。同じタイトルが既にデータベースに存在する場合、バリデーションエラーになります。
最後に
今回は、管理者側で投稿機能を作成しました。
次回は、顧客側で今回管理者側の投稿機能で作成したデータを使用した投稿機能を実装します。
参考資料