Find Image of Messaged User associated with chatro

2019-08-03 18:56发布

Apologies for the basic question. I managed to follow tutorials and with the help of the SO community managed to build a Group Chat with Action Cable and learned loads from doing so. However, I'm trying to pull up on a specific html page - the image of a Messaged User associated with a current_users Chatrooms. I've already been able to pull the chatrooms associated with a current user as well as the last message delivered in those chatrooms. I tried the following but this only gave me the image of my messaged user in my current chatroom . I have listed below all my relevant code.

show.html.erb (In my chatrooms html folder)

<% @chatroomall.each do |chatroom| %>
<div>
<%= image_tag @messageduser.avatar.url(:thumb), id: "css-style3"    %>
<%= chatroom.name %>
<%= chatroom.messages.last(1).pluck(:created_at) %>
<%= chatroom.messages.last(1).pluck(:body) %>                           
</div>
<% end %>

Chatroom.rb

class Chatroom < ApplicationRecord
has_many :chatroomusers
has_many :users, through: :chatroomusers
has_many :messages

scope :public_channels, ->{where(direct_message: false) }
scope :direct_messages, ->{ where(direct_message: true) }

def self.direct_message_for_users(users)
    user_ids = users.map(&:username).sort
    name = "#{user_ids.join(" and ")}"

    if chatroom = direct_messages.where(name: name).first
        chatroom
    else

        chatroom = new(name: name, direct_message: true)
        chatroom.users = users
        chatroom.save
        chatroom
    end

end
end

chatroomuser.rb

class Chatroomuser < ApplicationRecord
belongs_to :user
belongs_to :chatroom
end

message.rb

class Message < ApplicationRecord
belongs_to :user
belongs_to :chatroom
end

User.rb

class User < ApplicationRecord
devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :omniauthable, omniauth_providers: [:facebook]

cattr_accessor :current_user
has_many :chatroomusers
has_many :chatrooms, through: :chatroomusers
has_many :messages
end

Chatrooms_controller.rb

class ChatroomsController < ApplicationController
before_action :set_chatroom, only: [:show, :edit, :update, :destroy]
def index
@chatrooms = Chatroom.public_channels
end
def show
@messages = @chatroom.messages.order(created_at: :desc).limit(100).reverse
end
private
def set_chatroom
  @chatroom = Chatroom.find(params[:id])
end
def chatroom_params
  params.require(:chatroom).permit(:name)
end
end

Direct Messages Controller

class DirectMessagesController < ApplicationController
before_action :authenticate_user!

def show
    users = [current_user, User.find(params[:id])]
    @messageduser = User.find(params[:id])      
    @chatroom = Chatroom.direct_message_for_users(users)        
    @chatroomall = current_user.chatrooms
    @messages = @chatroom.messages.order(created_at: :desc).limit(100).reverse
    @messagelast = @chatroom.messages.last(1)
    render "chatrooms/show"
end
private

def chatroomuserlocator
    @chatroomlocator = Chatroom.find(params[:chatroom_id])
end
end

ChatroomUsers Controller

class ChatroomUsersController < ApplicationController
before_action :authenticate_user!
before_action :set_chatroom
def create
@chatroomuser = @chatroom.chatroomusers.where(user_id: current_user.id).first_or_create
redirect_to @chatroom
end
def destroy
@chatroomuser = @chatroom.chatroomusers.where(user_id: current_user.id).destroy_all
redirect_to chatrooms_path
end
  private

def set_chatroom
  @chatroom = Chatroom.find(params[:chatroom_id])
end
end

Schema.rb

create_table "chatrooms", force: :cascade do |t|
t.string   "name"
t.datetime "created_at",     null: false
t.datetime "updated_at",     null: false
t.boolean  "direct_message"
end
create_table "chatroomusers", force: :cascade do |t|
t.integer  "user_id"
t.integer  "chatroom_id"
t.datetime "created_at",   null: false
t.datetime "updated_at",   null: false
t.datetime "last_read_at"
t.index ["chatroom_id"], name: "index_chatroomusers_on_chatroom_id"
t.index ["user_id"], name: "index_chatroomusers_on_user_id"
end
create_table "create_messages", force: :cascade do |t|
t.integer  "user_id"
t.integer  "chatroom_id"
t.text     "body"
t.datetime "created_at",  null: false
t.datetime "updated_at",  null: false
t.index ["chatroom_id"], name: "index_create_messages_on_chatroom_id"
t.index ["user_id"], name: "index_create_messages_on_user_id"
end

1条回答
Explosion°爆炸
2楼-- · 2019-08-03 19:23

So you have a list of chatrooms that you are loping through

<% @chatroomall.each do |chatroom| %>

so inside the loop you have access to each specific chatroom in a variable called chatroom right?

so for each specific chatroom then you want to show the avatar of the last messaged user right?

<% @chatroomall.each do |chatroom| %>
    <%= image_tag chatroom.messages.last.user.avatar.url(:thumb), id: "css-style3"    %>

etc...

should do the trick

UPDATE

Of course there may be occasions where there are no messages in a chatroom so this needs to be taken care of with a simple check

<% @chatroomall.each do |chatroom| %>
  <% if chatroom.messages.empty? %>
    No messages in this chatroom
  <% else %>    
    <%= image_tag chatroom.messages.last.user.avatar.url(:thumb), id: "css-style3" unless chatroom.messages.last.user.blank?%> //Note additional check for a user

  <% end %>

You may want to style the above by using ul li tags or something so you don't just get a list on one long line

Another reason to put logic like this in the model that way you can do all your check in one place and never have to worry about it when it's time to fetch the info you are looking for something like a last_user method on the chatroom model maybe then just a simple chatroom.last_user.name unless last_user.blank? will do the trick whenever you need it. Much cleaner and it's the Rails way!

END UPDATE

however you should refactor some of your repeated code into your chatroom model by creating a named scope or method called last_message

def last_message
   messages.last
end

that way if you need to refactor the way you get the last message for a chatroom you have only one place to do that then you can replace things like

chatroom.messages.last(1).pluck(:created_at)

with

chatroom.last_message.pluck(:created_at)

Note my code is untested and there may be errors but should give you the right idea and if I have misunderstood your question then please say as it wasn't easy to decipher your actual requirement which is a massive hint for you if you can clearly define your actual require,ent you usually find the answer is staring you in the face e.g. I interpreted your question as

"How do I display the avatar for the last messaged user in each chatroom for the currently logged in user?"

Flow charts or structured diagrams are often helpful when trying to figure out more complex logic see if you can get your head round something like https://en.wikipedia.org/wiki/Jackson_structured_programming

查看更多
登录 后发表回答