Как мне использовать Rails, чтобы найти одно has_many, но не другое? - PullRequest
0 голосов
/ 25 июня 2011

Сообщение has_many user_messages.Он имеет два.

1 UserMessage будет иметь отправителя как user_id

Другой UserMessage будет иметь получателя как user_id

Зная одного пользователя, как я могу, для любого сообщения, найти другой?

Вот что я пробовал в качестве метода для класса Message, но он не работает:

 32   def other_user(one_user)      
 33     um = self.user_messages
 34     um.each do |user_message|
 35       
 36       output_user = User.find(user_message.user_id) unless user_message.user_id == one_user.id
 37     end
 38     
 39     return output_user
 40   end

Ответы [ 2 ]

1 голос
/ 25 июня 2011

Это может быть реализовано как расширение ассоциации. Это будет эффективно для большого объема сообщений, так как отправляет обработку в БД.

class User < ActiveRecord::Base

    has_many :sent_messages, :class_name => "Message", :foreign_key => "sender_id"
    has_many :receivers, :through => :sent_messages, :source => :receiver do 
        def for_message(message_id)
            where("messages.id = ?", message_id)
        end
    end

    # Another association mapping for received_messages

end


class Message < ActiveRecord::Base

    belongs_to :sender, :class_name => "User", :foreign_key => "sender_id"
    belongs_to :receiver, :class_name => "User", :foreign_key => "receiver_id"

end


#Usage
User.first.sent_messages

#all users received messages from first user
User.first.receivers

#all users received messages from first user for message of message_id
User.first.receivers.for_message(message_id)
1 голос
/ 25 июня 2011

Похоже, должно быть лучшее определение того, кто является sender, а кто receiver, но пока что:

def other_user(one_user)
  user_messages.reject do |msg|
    msg.user_id == one_user.id
  end.first.user
end

Он принимает набор user_messages, отфильтровывает тот, который принадлежит one_user. В массиве должен остаться один элемент, поэтому выберите его и верните присоединенного к нему пользователя.

EDIT

Возможно, я не понимаю все ваши требования, но я бы, вероятно, просто добавил sender_id и receiver_id непосредственно к Message и удалил таблицу соединения UserMessage. Тогда вы можете определить отношения как:

class User
  has_many :sent_messages, :class_name => 'Message', :foreign_key => 'sender_id'
  has_many :received_messages, :class_name => 'Message', :foreign_key => 'receiver_id'
end

class Message
  belongs_to :sender, :class_name => 'User'
  belongs_to :recipient, :class_name => 'User'
end

РЕДАКТИРОВАТЬ 2

Если вы хотите, чтобы промежуточная таблица отслеживала пользовательские состояния, вы можете использовать STI для подкласса UserMessage как SentMessageLink и ReceivedMessageLink (эти имена не удивительны - но вы поняли идею), тогда вы можете использовать has_many :through.

class SentMessageLink < UserMessage
  belongs_to :sender, :class_name => 'User'
  belongs_to :message
end

class User
  has_many :sent_message_links
  has_many :sent_messages, :through => :sent_message_links
end

class Message
  has_one :sent_message_link
  has_one :sender, :through => :sent_message_link
end

с аналогичным кодом для полученных сообщений. Тогда вы сможете получить доступ к sender и receiver прямо из сообщения.

...