class Model RunningTracks < ActiveRecord::Base
has_many :achievements
has_many :runners, through: :achievements
class Model Runner < ActiveRecord::Base
has_many :achievements
has_many :running_tracks, through: :achievements
class Model Achievement < ActiveRecord::Base
belongs_to :runner
belongs_to :running_tracks
在HomePage上有一个each do
列表,用于显示所有RunningTracks。在轨道旁边,我们会显示一个按钮,将其标记为运行。在控制器的查询中,一个急切的加载解决方案是includes
和references
(Rails 4):
class RunningTracksController
def index
@running_tracks = RunningTracks.includes(:achievements).references(:achievements)
end
为了提高可用性,如果已经标记了每个记录旁边的按钮,则该按钮不应该是可见的。 (将以辅助方法重构)
@running_tracks.each do |track|
.
- unless track.achievements.map(&:user_id).include? current_user.id
= button_to "done", running_track_mark_as_done_path(track)
这有效......但是......随着数据库获取更多记录,它将查询大量成就,因此只对includes
的成就进行自定义关联和current_user
查询(设计应该是解决方案。
class Model RunningTracks < ActiveRecord::Base
.
has_many :achieved_runns, -> { where user_id: current_user.id }, class_name "Achievement"
但是因为在模型中无法访问current_user,所以这不起作用。我不认为可以将变量传递给hay_many关联,是吗?
是否有一个更有效的解决方案来加载所有 RunningTracks,包括仅当前用户的成就? 谢谢你宝贵的时间!
答案 0 :(得分:1)
以下是丑陋的并打破了ActiveRecord的比喻,但随着DB的大小增加,它会给你非常快速的查找。也许其他人可以通过一种方式将其保持在渴望加载的范例中。
class RunningTrack
# Returns a Set (for fast lookups) of track IDs that have at least one achievement for the provided user
def self.running_track_ids_for_achievements_for_user(user_id)
Set.new Achievement.where(:user_id => user_id).pluck(:running_track_id)
end
end
然后在你的控制器中:
class RunningTracksController
def index
@running_tracks = RunningTracks.all
@running_track_ids_for_achievements_for_user = RunningTrack.running_track_ids_for_achievements_for_user(current_user.id)
end
end
您的观点:
- unless @running_track_ids_with_achievements_for_user.include? track
= button_to "done", running_track_mark_as_done_path(track)