我想我在标题中并不是很清楚,但我发现很难描述完全之后的事情。所以最好从一个例子开始:
我有以下型号:
class Song < ActiveRecord::Base
has_many :learnt_items, as: :learnable
has_many :trained_items, as: :learnable
end
class LearntItem < ActiveRecord::Base
belongs_to :learnable, polymorphic: true
end
class TrainedItem < LearntItem
end
例如,如果我选择所有受过训练的项目的歌曲:
Song.joins(:trained_items)
我会看到(大致)返回的记录如下:
learnable_type | learnable_id | type | label
Song | 1 | TrainedItem | happy
Song | 1 | TrainedItem | sad
Song | 1 | TrainedItem | lively
Song | 2 | TrainedItem | lively
如果我想选择所有已经训练过 特定标签的歌曲,我会这样做:
Song.joins(:trained_items).where(learnt_items: { label: [:happy, :sad] })
现在,我需要让所有不的歌曲都有针对给定标签的训练项目。人们会认为以下就足够了:
Song.joins(:trained_items).where.not(learnt_items: { label: [:happy, :sad] })
但这仍然会产生以下记录:
learnable_type | learnable_id | type | label
Song | 1 | TrainedItem | lively
Song | 2 | TrainedItem | lively
这确实不是我的意图。您可以看到查询过滤掉了带有给定标签的记录,但label = 'lively'
的记录仍然存在,因此返回的歌曲为id = 1
。我只需要从此查询中返回id = 2
的歌曲。
如何使用ActiveRecord构建查询以便我的方案得以实现?
答案 0 :(得分:1)
使用子查询查找您不想要的id
并使用where.not
条件中的Song.joins(:trained_items)
.where.not(learnable_id: Song.select(:learnable_id).where(learnt_items: { label: [:happy, :sad] })
:
class Message(object):
pass
class InitMessage(Message):
def __init__(self, queue_in, queue_out):
self.queue_in = queue_in
self.queue_out = queue_out
class Client(Thread):
def __init__(self, server_queue, name):
Thread.__init__(self)
self.control = server_queue
self.my_in_queue = Queue()
self.my_out_queue = Queue()
self.name = name
def run(self):
self.control.put(InitMessage(self.my_in_queue, self.my_out_queue))
while True:
if not self.my_in_queue.empty():
message = self.my_in_queue.get()
print("Client {name} got message from server of type {type}".format(
name=self.name, type=type(message).__name__
))
self.my_in_queue.task_done()
self.my_out_queue.put(Message())
class Server(Thread):
def __init__(self):
Thread.__init__(self)
self.control = Queue()
self.clients = {}
self.id = 0
def run(self):
while True:
while not self.control.empty():
message = self.control.get()
if isinstance(message, InitMessage):
self.clients[self.id] = {'to_client': message.queue_in,
'from_client': message.queue_out}
message.queue_in.put(Message())
self.id += 1
self.control.task_done()
for client in self.clients:
if not self.clients[client]['from_client'].empty():
message = self.clients[client]['from_client'].get()
print("got message from client {id}".format(id=client))
self.clients[client]['from_client'].task_done()
self.clients[client]['to_client'].put(Message())
sleep(1)
server = Server()
client1 = Client(server.control, "a")
client2 = Client(server.control, "b")
server.start()
client1.start()
client2.start()
server.join()