问题
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:
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
来源:https://stackoverflow.com/questions/44096732/find-image-of-messaged-user-associated-with-chatrooms-using-group-chat-via-actio