はじめに
「コミュニティアプリにグループ作成機能を実装したい」
「グループへ自由に入会、退会できるようにしたい」
初学者のメモです
実装した主な機能
- オーナーによるグループ作成、削除
- グループ情報は、「イメージ画像」「グループ名」「グループ説明」
- オーナー以外のグループへの入会、退会
手順
- アソシエーション
- ルーティング
- コントローラー(グループ作成)
- コントローラー(グループ入会、退会)
実装
ER図
- このイメージで実装していきます
- 元々、Userモデルがある状態です
- Userにownerカラムを持たせるか悩みました(結局、必要なかったです)
① アソシエーション
user.rb
#省略
has_many :group_users, dependent: :destroy
has_many :groups, through: :group_users
#省略
- userは中間テーブルgroup_usersを介して、groupsを持っているというイメージ
- ブックマーク機能やフォロー機能との関連性を感じます
過去にフォロー機能を作成したときのもの
group.rb
belongs_to :owner, class_name: 'User'
has_many :group_users, dependent: :destroy
has_many :users, through: :group_users, source: :user
validates :name, presence: true
validates :introduction, presence: true
has_one_attached :image
def get_image
(image.attached?) ? image : 'no_image.jpg'
end
-
belongs_to :owner, class_name: 'User'
は、groupはownerを持っていて、それは、userモデルにあるというイメージ。中間テーブルにowner_idがあることで実現できる - groupは中間テーブルgroup_usersを介して、usersを持っているというイメージ。ここも、ブックマーク機能やフォロー機能との関連性を感じます
- バリデーションもOK
- 今回は、Active Recordにimageカラムを持たせたため、
has_one_attached :image
の記述と、get_image
のアクション定義をしています。画像添付がない場合は、no_image.jpgを参照
group_user.rb
belongs_to :user
belongs_to :group
②ルーティング
routes.rb
resources :groups do
resource :group_users, only: [:create, :destroy]
end
- Groupについては、デフォルトのアクションを全て可能にしました
- group_usersについては、「create=グループ入会」「destroy=グループ退会」のみにしました
③コントローラー(グループ作成)
groups_controller/rb
before_action :authenticate_user!
before_action :ensure_correct_user, only: [:edit, :update]
def new
@group = Group.new
end
def index
@groups = Group.all
end
def show
@group = Group.find(params[:id])
end
def create
@group = Group.new(group_params)
@group.owner_id = current_user.id
@group.users << current_user
if @group.save
redirect_to groups_path
else
render 'new'
end
end
def edit
end
def update
if @group.update(group_params)
redirect_to groups_path
else
render "edit"
end
end
def destroy
@group = Group.find(params[:id])
@group.destroy
redirect_to groups_path
end
private
def group_params
params.require(:group).permit(:name, :introduction, :image)
end
def ensure_correct_user
@group = Group.find(params[:id])
unless @group.owner_id == current_user.id
redirect_to groups_path
end
end
-
@group.users << current_user
で、現在のユーザーをグループのユーザー数に追加しました - これで、グループのcreateもdestroyも可能になります
④コントローラー(グループ入会、退会)
group_users_controller.rb
before_action :authenticate_user!
def create
group_user = current_user.group_users.new(group_id: params[:group_id])
group_user.save
redirect_to request.referer
end
def destroy
group_user = current_user.group_users.find_by(group_id: params[:group_id])
group_user.destroy
redirect_to request.referer
end
-
find_by(group_id: params[:group_id])
では、find_byメソッドでによって、group_idを指定しました - HTTPリファラを取得してリダイレクトさせる
redirect_to request.referer
が個人的に便利で好きです - 後は、ビューファイルの記述
まとめ
- グループ機能は中間テーブルを用いて、N対Nのリレーションを実装する
- グループ作成はgroupsに、入会や退会はgroup_usersにアクションを記述する
投稿4回目。
ボリューミーで、整理するのが難しかったです。
今後、グループ内での様々な機能を試していきます。
ご指導、ご教授いただけると幸いです。