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

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

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

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

1回答

2703閲覧

Ruby on Rails メッセージ機能でのメッセージの取得について

riamk

総合スコア47

Ruby

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

0クリップ

投稿2017/03/28 05:43

編集2017/03/28 11:33

###前提・実現したいこと
rails4 ローカル環境

現在メッセージ機能を実装してラインのようなメッセージのやりとりができるようにしたいと思っています。

###発生している問題・エラーメッセージ

メッセージ機能は無事に実装できて、メッセージのやり取りをしているページで『相手のメッセージは左側』『自分のメッセージは右側』という表示の仕方にしようと思ったのですが、相手のメッセージがCouldn't find User with 'id'=とエラーになり表示できません。

最初に試してみたときは正常に表示できたのですが、機能テストのためユーザーを増やして試してみたところ、先ほどのCouldn't find User with 'id'=というエラーになってしまいました。

あと、

<% if @over_ten %> <%= link_to '以前のメッセージをすべて表示', '?m=all' %> <% end %>

とこのように10件以上の表示はリンクをクリックして表示させているのですが、正常に表示さえているユーザーとのメッセージもこのリンクをクリックするとCouldn't find User with 'id'=と同じようにエラーになってしまいます。

###該当のソースコード
問題があると思われるviewのコード。
また、今回メッセージ機能は会話「conversations」、メッセージ「messages」として関連づけて作成したので、そちらのコントローラーとモデルなども記載します。

views/messages/index.html.erb

views/messages/index.html.erb

1 <% if @over_ten %> 2 <%= link_to '以前のメッセージをすべて表示', '?m=all' %> 3 <% end %> 4 5 <div class="ui segment"> 6 <% @messages.each do |message| %> 7 <% if message.user_id == current_user.id %> 8 <!-- 自分のメッセージ --> 9 <div class="item-right"> 10 <% user = User.find(message.user_id) %> 11 <strong><%= user.name %></strong> 12 <%= message.message_time %> 13 <%= message.body %> 14 </div> 15 <% else %> 16 <!-- 相手のメッセージ --> 17 <div class="item-left"> 18 <% user = User.find(message.user_id) %> 19 <strong><%= user.name %></strong> 20 <%= message.message_time %> 21 <i class="right triangle icon"></i> 22 <%= message.body %> 23 </div> 24 <% end %> 25 <% end %> 26 </div> 27 28 <!-- メッセージの送信 --> 29 <%= form_for [@conversation, @message], html: {class: "ui reply form"} do |f| %> 30 <div class="field"> 31 <%= f.text_area :body, class: "form-control" %> 32 </div> 33 <%= f.text_field :user_id, value: current_user.id, type: "hidden" %> 34 <div> 35 <%= f.submit "メッセージを送る" %> 36 </div> 37 <% end %>

messages_controller.rb

messages_controller.rb

1class MessagesController < ApplicationController 2 before_action :authenticate_user! 3 4 before_action do 5 @conversation = Conversation.find(params[:conversation_id]) 6 end 7 8 def index 9 @messages = @conversation.messages 10 if @messages.length > 10 11 @over_ten = true 12 @messages = @messages[-10..-1] 13 end 14 15 if params[:m] 16 @over_ten = false 17 @messages = @conversation.messages 18 end 19 20 if @messages.last 21 if @messages.last.user_id != current_user.id 22 @messages.last.read = true 23 end 24 end 25 26 @message = @conversation.messages.build 27 end 28 29 def create 30 @message = @conversation.messages.build(message_params) 31 if @message.save 32 redirect_to conversation_messages_path(@conversation) 33 end 34 end 35 36 private 37 def message_params 38 params.require(:message).permit(:body, :user_id) 39 end

messageモデル

class Message < ActiveRecord::Base belongs_to :conversation belongs_to :user validates_presence_of :body, :conversation_id, :user_id def message_time created_at.strftime("%m/%d/%y at %l:%M %p") end end

conversations_controller.rb

class ConversationsController < ApplicationController before_action :authenticate_user! def index @users = User.all @conversations = Conversation.all end def create if Conversation.between(params[:sender_id], params[:recipient_id]).present? @conversation = Conversation.between(params[:sender_id], params[:recipient_id]).first else @conversation = Conversation.create!(conversation_params) end redirect_to conversation_messages_path(@conversation) end private def conversation_params params.permit(:sender_id, :recipient_id) end end

Conversationモデル

class Conversation < ActiveRecord::Base belongs_to :sender, foreign_key: :sender_id, class_name: 'User' belongs_to :recipient, foreign_key: :recipient_id, class_name: 'User' has_many :messages, dependent: :destroy validates_uniqueness_of :sender_id, scope: :recipient_id scope :between, -> (sender_id,recipient_id) do where("(conversations.sender_id = ? AND conversations.recipient_id =?) OR (conversations.sender_id = ? AND conversations.recipient_id =?)", sender_id,recipient_id, recipient_id, sender_id) end def target_user(current_user) if sender_id == current_user.id User.find(recipient_id) elsif recipient_id == current_user.id User.find(sender_id) end end end

データベーステーブル

create_table "messages", force: :cascade do |t| t.text "body" t.integer "conversation_id" t.integer "user_id" t.boolean "read", default: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end add_index "messages", ["conversation_id"], name: "index_messages_on_conversation_id", using: :btree add_index "messages", ["user_id"], name: "index_messages_on_user_id", using: :btree create_table "conversations", force: :cascade do |t| t.integer "sender_id" t.integer "recipient_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end

どのように相手のメッセージを取得したらいいのか教えて頂けると嬉しいです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

errorは

ruby

1<% else %> 2 <!-- 相手のメッセージ --> 3 <div class="item-left"> 4 <% user = User.find(message.user_id) %> 5 <strong><%= user.name %></strong>

<% user = User.find(message.user_id) %>
ここで発生しているようです。
おそらくmessage.user_idが正しく入っていないmassageがあるということでしょう。
つまり名無しによって投稿されたメッセージがあるということです。

ruby

1<% else %> 2 <!-- 相手のメッセージ --> 3 <div class="item-left"> 4 <% user = User.find_by(id: message.user_id) %> 5 <strong><%= user.try(:name) %></strong>

とすれば、とりあえず、エラーメッセージは出なくなると思いますが。
誰の発言かわからないメッセージを許容するということで
ソフトウェア的にはバグだということに注意してください

もし、名無しメッセージが増えるようでしたら、messages_controller.rbとviews/_form.html.erb views/new.html.erbも晒してください。

投稿2017/03/28 05:55

moke

総合スコア2241

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

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

riamk

2017/03/28 06:28

ご回答ありがとうございます。 さっそく教えて頂いたコードのように試してみましたが、 undefined method `strftime' for nil:NilClass とエラーが出てしまいました。 なぜ、strftimeがエラーになってしまうのか分からず苦戦しております。 コントローラーやモデル、テーブルなど、現在のコードを追記しましたので、再度アドバイス頂けると嬉しいです。
moke

2017/03/28 07:14

massage.created_at も登録されていないようですね これも def message_time created_at.try(:strftime,"%m/%d/%y at %l:%M %p") end とすればとりあえずエラー回避は可能です。 これ以上解説が必要でしたら さらに massages_controllers.rbの def message_params と app/views/massages/_form.html.erb app/views/massages/new.html.erb も見せてください
riamk

2017/03/28 11:37

ありがとうございます! とりあえずは無事に表示できました。 massages_controllers.rbのdef message_paramsは追記しました。 app/views/massages/_form.html.erb app/views/massages/new.html.erb この2点に関しては現時点では作成していません。 現状は正常に表示できていますが、何か修正した方がいいポイントなどご指摘があれば教えて頂けると嬉しいです。
moke

2017/03/28 11:56

Massage controller のindex内の @message = @conversation.messages.build を message = @conversation.messages.build(user: current_user)にしてみてはいかがでしょう?
riamk

2017/03/28 12:33

ご指摘ありがとうございます。 message = @conversation.messages.build(user: current_user) にしてみたところ、 First argument in form cannot contain nil or be empty とエラーになったので @message = @conversation.messages.build(user: current_user) としました。 表示は正常にできていますが問題はありますでしょうか?
moke

2017/03/28 13:16 編集

@が抜けてましたねそれで大丈夫です。それでうまくいくと思います。
riamk

2017/03/28 13:27

はい、現状はこれでうまくいっています。 ありがとうございました。 私はまだ初心者で全然分からないことばかりですが、機会があればまたよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問