В домене, подобном этому:
class User
has_many :posts
has_many :topics, :through => :posts
end
class Post
belongs_to :user
belongs_to :topic
end
class Topic
has_many :posts
end
Я могу прочитать все идентификаторы тем через user.topic_ids
, но я не вижу способа применить условия фильтрации к этому методу, так как он возвращает Array
вместо ActiveRecord::Relation
.
Проблема заключается в том, что для пользователя задан существующий набор тем, отмечающий те, для которых есть сообщение пользователя.В настоящее время я делаю что-то вроде этого:
def mark_topics_with_post(user, topics)
# only returns the ids of the topics for which this user has a post
topic_ids = user.topic_ids
topics.each {|t| t[:has_post]=topic_ids.include(t.id)}
end
Но это загружает все идентификаторы темы независимо от набора ввода.В идеале я хотел бы сделать что-то вроде
def mark_topics_with_post(user, topics)
# only returns the topics where user has a post within the subset of interest
topic_ids = user.topic_ids.where(:id=>topics.map(&:id))
topics.each {|t| t[:has_post]=topic_ids.include(t.id)}
end
Но единственное, что я могу сделать конкретно, это
def mark_topics_with_post(user, topics)
# needlessly create Post objects only to unwrap them later
topic_ids = user.posts.where(:topic_id=>topics.map(&:id)).select(:topic_id).map(&:topic_id)
topics.each {|t| t[:has_post]=topic_ids.include(t.id)}
end
Есть ли лучший способ?Можно ли иметь что-то вроде select_values
в ассоциации или области?FWIW, я на рельсах 3.0.x, но мне было бы любопытно и 3,1.
Зачем я это делаю?
По сути, у меня естьСтраница результатов для полусложного поиска (который происходит только на основе данных Темы), и я хочу отметить результаты (Темы) как материал, с которым взаимодействовал пользователь (написал сообщение).
Так что, да, есть еще один вариант, который будет выполнять объединение [Тема, сообщение], чтобы результаты появлялись как отмеченные или нет в результате поиска, но это разрушило бы мою способность кешировать запрос Темы (запрос, даже без объединения, обходится дороже, чем выборка только идентификаторов для пользователя)
Обратите внимание на подходы, описанные выше действительно работают , они просто кажутся неоптимальными.