質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

1035閲覧

【Ruby on Rails】チャットアプリで、既成のグループがある場合新たにグループ作成されないようにしたい

kumamin

総合スコア12

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2020/09/01 06:23

編集2020/09/01 08:36

前提・実現したいこと

今、Ruby on Railsでアプリを作っており、その中でユーザー同士のチャット機能しています。
ユーザーの詳細ページ(user#show)に行くと「メッセージを送る」というボタンがあり、
そのボタンをクリックするとそのユーザーとのチャットルーム(message#index)に飛ぶようにしています。

ここでは、メッセージを送る対象のユーザーとログイン中のユーザーとの関係をgroupと定義しています。
ログイン中のユーザーが「メッセージを送る」ボタンをクリックしたとき、
そのユーザーとのグループが作成されたことがない場合はgroup#createを経由してmessage#indexに飛び、
すでにグループが作成されている場合は直接message#indexに飛ぶように設定したいです。

今その実装がなかなか上手く行かず、すでにグループが作成されている場合でも
同じユーザーとのグループが複数作成されてしまうので困っています。

解決法を教えていただけますと幸いです。

また、users_controller.rbのshowアクション内のよりシンプルな書き方があれば
それも合わせて教えていただけると大変助かります。

よろしくお願いいたします。

該当のソースコード

▼users_controller.rb

rb

1class UsersController < ApplicationController 2 3 def show 4 @user = User.find(params[:id]) 5 group_ids = @user.groups.pluck(:id) 6 7 group_users = GroupUser.where(group_id: group_ids) 8 group_user = group_users.where(user_id: current_user.id) 9 10 @group_id = group_user.pluck(:group_id).first 11 end 12 13end

▼groups_controller.rb

rb

1class GroupsController < ApplicationController 2 before_action :authenticate_user! 3 4 def index 5 groups = current_user.groups.includes(:messages) 6 @groups = groups.joins(:messages).order("messages.created_at DESC") 7 end 8 9 def create 10 group = Group.create 11 group_user = GroupUser.create(group_id: group.id, user_id: current_user.id) 12 @user = User.find(params[:id]) 13 group_user = GroupUser.create(group_id: group.id, user_id: @user.id) 14 @group_id = group_user.group_id 15 redirect_to group_messages_path(@group_id, user_id: @user.id) 16 end 17 18 private 19 def group_params 20 params.permit(:id, user_ids: []) 21 end 22 23end

▼views/users/show.html.haml

haml

1.Title 2 = "#{@user.name}さんのページ" 3.Profile 4 - if @user.profile_image? 5 = image_tag @user.profile_image.url, class: "Profile__Image" 6 - else 7 = image_tag "no-image.jpg", class: "Profile__Image" 8 .Profile__Content 9 .Profile__Content__Upper 10 .Name 11 = @user.name 12 .Info_right 13 - if user_signed_in? && @user.id == current_user.id 14 = link_to "プロフィールを編集", edit_user_path(current_user), class: "Info_right__Btn" 15 - else 16 - if @group_id.nil? 17 = link_to "メッセージを送る", "/groups/#{@user.id}/create", class: "Info_right__Btn" 18 - else 19 = link_to "メッセージを送る", group_messages_path(@group_id, user_id: @user.id), class: "Info_right__Btn"

▼models/user.rb

rb

1class User < ApplicationRecord 2 devise :database_authenticatable, :registerable, 3 :recoverable, :rememberable, :validatable 4 5 validates :name, presence: true, length: {maximum: 10} 6 7 has_many :group_users, dependent: :destroy 8 has_many :groups, through: :group_users 9 10 has_many :messages, dependent: :destroy 11 12end

▼models/group.rb

rb

1class Group < ApplicationRecord 2 has_many :group_users, dependent: :destroy 3 has_many :users, through: :group_users 4 has_many :messages, dependent: :destroy 5end

試したこと

users_controller.rbのshowアクション内に
@is_exists_user_group = current_user.groups.pluck(:user_id).include?(@user.id)
と記述し、show.html.hamlにif @is_exists_user_groupと条件分岐で書いてみたりもしましたが、
状況は変わらず、やはり複数同じグループが作られてしまいました。

補足情報(FW/ツールのバージョンなど)

▼rails routesの結果

group_messages GET /groups/:group_id/messages(.:format) messages#index         GET /groups/:id/create(.:format) groups#create

▼コンソールでGroupUser.allと打った結果
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

- if @group_id.nil? の書き方をみると @group_id は login ユーザーとshowされているユーザーとのgroupのidのことだと思われます。

しかし、UsersControllerの show ではそうなって居ません。
というよりそれ以前にmodelの設計がおかしいかも。
User、Group、GroupUserの関連定義を載せてください。
特に気になるのは
userAをshow、userBがcurrent_user の時のGroupと
userBをshow、userAがcurrent_user の時のGroupとは
同じGroupなのですよね?それが実現するようになっているかどうか。

追記

となると、そのgroupをどうやって得るかなぁ

  1. @user.groupscurrent_user.groups で一致するもの
  2. @user.group_users.pluck(:group_id) の中にcurrent_userと同じgroup_idのものがあるか


前者は
@group = (@user.groups & current_user.groups).first
(ないときはnil。 なので nil.idとならないように注意)
後者は
group_user = GroupUser.where(group_id: @user.group_users.pluck(:group_id).first @group = group_user.try(:group)
両方共DB2回アクセスするなぁ。。。

投稿2020/09/01 08:09

編集2020/09/01 09:17
winterboum

総合スコア23360

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kumamin

2020/09/01 08:38

コメントありがとうございます。 まさに、@group_idは、 ログイン中のユーザーとshowページのユーザーとのgroupのidです。 userとgroupのモデルとgroupsコントローラーのコード、GroupUserの中身がわかるターミナルの画像を追加しましたので、ご確認いただけると助かります。
kumamin

2020/09/01 08:59

すみませんなぜかわからないのですが、解決しました。 これから何が原因だったか探ってみたいと思います。 winterboumさんには以前にもご回答いただいたことがあり、大変感謝しています。 ありがとうございました。
kumamin

2020/09/01 09:56

追記ありがとうございます。 showアクション内でgroupのidを取り出すのに5行も書いていたので、 追記の1番のように書いてみたところコードをとてもシンプルにすることができ、グループ作成も思うように実装できたのでよかったです。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問