[英]Setting up has_many through association
I have 3 models 我有3个型号
class Battle < ActiveRecord::Base
has_many :battle_videos
has_many :videos, :through => :battle_videos
...
end
class BattleVideo < ActiveRecord::Base
belongs_to :battle
belongs_to :video
validates :code, :presence => true
end
class Video < ActiveRecord::Base
belongs_to :user, :foreign_key => :user_id, :class_name => "User"
...
end
BattleVideo has attribute "code" (left_side || right_side) which determines BATTLE SIDE (there are always 2 sides in battles, coz always playing -- 1 vs. 1, team vs. team etc.) BattleVideo具有属性“代码”(left_side || right_side),该属性确定了战斗面(战斗中总是有2面,战斗总是持续-1对1,团队对团队等)
I would like to specify association (left_side_video, right_side_video) in model video , which gets video for chosen side. 我想在模型video中指定关联(left_side_video,right_side_video),该关联会获取所选边的视频。
Now to get video for SIDE 1 (left) - use this code 现在获取SIDE 1(左侧)的视频-使用此代码
Battle.first.battle_videos.where("battle_videos.code = 'left_side'").first.video
I want to get my battle videos like this 我想得到这样的战斗视频
Battle.first.left_side_video
I think, Battle model should look like this, but it doesnt work (works only left side) 我认为,战斗模型应如下所示,但它不起作用(仅在左侧起作用)
class Battle < ActiveRecord::Base
has_many :battle_videos
has_many :videos, :through => :battle_videos
has_many :left_side_video, :through => :battle_videos, :source => :video, :conditions => ["battle_videos.code = 'left_side'"]
has_many :right_side_video, :through => :battle_videos, :source => :video, :conditions => ["battle_videos.code = 'right_side'"]
end
UPDATE: Works, but not in desired way. 更新:有效 ,但不按预期方式。 The problem was in includes
chain. 问题出在includes
连锁。 model Battle
has scope :all_inclusive
, which loads all associations Battle
模型具有范围:all_inclusive
,它会加载所有关联
scope :all_inclusive, includes(:battle_category).includes(:bets).includes(:votes).includes(:left_side_video).includes(:right_side_video)
Generated SQL: 生成的SQL:
Battle Load (0.6ms) SELECT `battles`.* FROM `battles` WHERE (battles.status = 1 AND valid_from < '2012-01-31 13:31:50' AND battles.valid_to > '2012-01-31 13:31:50') ORDER BY battles.id DESC
BattleCategory Load (0.1ms) SELECT `battle_categories`.* FROM `battle_categories` WHERE `battle_categories`.`id` IN (1)
Bet Load (0.1ms) SELECT `bets`.* FROM `bets` WHERE `bets`.`parent_type` = 'Battle' AND `bets`.`parent_id` IN (1, 2)
Vote Load (0.2ms) SELECT `votes`.* FROM `votes` WHERE `votes`.`parent_type` = 'Battle' AND `votes`.`parent_id` IN (1, 2)
BattleVideo Load (0.1ms) SELECT `battle_videos`.* FROM `battle_videos` WHERE `battle_videos`.`battle_id` IN (1, 2) AND (battle_videos.code = 'user_1')
Video Load (0.1ms) SELECT `videos`.* FROM `videos` WHERE `videos`.`id` IN (1, 3)
NOTICE THAT VIDEOS 2 AND 4 (FOR RIGHT SIDE) - dont load. 注意视频2和4(在右侧)-不要加载。 I can access only 1,3 videos 我只能访问1,3个视频
Videos id, battle_id (side) 影片ID,Battle_id(侧面)
[1 , 1 (lft)] [1,1(lft)]
[2 , 1 (rgt)] [2,1(rgt)]
[3 , 2 (lft)] [3,2(lft)]
[4 , 2 (rgt)] [4,2(rgt)]
When I remove .includes(:right_side_video)
from :all_inclusive
chain I got this sql: 当我从:all_inclusive
链中删除.includes(:right_side_video)
,我得到了以下sql:
Battle Load (0.6ms) SELECT `battles`.* FROM `battles` WHERE (battles.status = 1 AND valid_from < '2012-01-31 13:39:26' AND battles.valid_to > '2012-01-31 13:39:26') ORDER BY battles.id DESC
BattleCategory Load (0.1ms) SELECT `battle_categories`.* FROM `battle_categories` WHERE `battle_categories`.`id` IN (1)
Bet Load (0.1ms) SELECT `bets`.* FROM `bets` WHERE `bets`.`parent_type` = 'Battle' AND `bets`.`parent_id` IN (1,2)
Vote Load (0.2ms) SELECT `votes`.* FROM `votes` WHERE `votes`.`parent_type` = 'Battle' AND `votes`.`parent_id` IN (1,2)
BattleVideo Load (0.3ms) SELECT `battle_videos`.* FROM `battle_videos` WHERE `battle_videos`.`battle_id` IN (1,2) AND (battle_videos.code = 'left_side')
Video Load (0.1ms) SELECT `videos`.* FROM `videos` WHERE `videos`.`id` IN (1, 3)
Video Load (0.2ms) SELECT `videos`.* FROM `videos` INNER JOIN `battle_videos` ON `videos`.`id` = `battle_videos`.`video_id` WHERE `battle_videos`.`battle_id` = 1 AND (battle_videos.code = 'right_side') LIMIT 1
Video Load (0.1ms) SELECT `videos`.* FROM `videos` INNER JOIN `battle_videos` ON `videos`.`id` = `battle_videos`.`video_id` WHERE `battle_videos`.`battle_id` = 2 AND (battle_videos.code = 'right_side') LIMIT 1
Now this works fine. 现在可以正常工作了。 But IN SQL level - its not as perfect as I want. 但是在SQL级别上-并不是我想要的那么完美。 You can see, that videos 1, 3 are loaded in correct way 您可以看到视频1、3的加载方式正确
Video Load (0.1ms) SELECT `videos`.* FROM `videos` WHERE `videos`.`id` IN (1, 3)
But video 2, 4 load by seperate sqls: 但是视频2、4由单独的sql加载:
Video Load (0.2ms) SELECT `videos`.* FROM `videos` INNER JOIN `battle_videos` ON `videos`.`id` = `battle_videos`.`video_id` WHERE `battle_videos`.`battle_id` = 1 AND (battle_videos.code = 'right_side') LIMIT 1
Video Load (0.1ms) SELECT `videos`.* FROM `videos` INNER JOIN `battle_videos` ON `videos`.`id` = `battle_videos`.`video_id` WHERE `battle_videos`.`battle_id` = 2 AND (battle_videos.code = 'right_side') LIMIT 1
What I want? 我想要的是? FINAL SQL GENERATED BY RUBY RUBY生成的最终SQL
Video Load (0.1ms) SELECT `videos`.* FROM `videos` WHERE `videos`.`id` IN (1, 2, 3, 4)
Why don't you try with "joins" instead of "includes"? 为什么不尝试使用“联接”而不是“包含”?
You can create named_scope like this 您可以像这样创建named_scope
named_scope : left_side_video, {
:select => "videos.*",
:joins => "INNER JOIN battle_videos ON battle_videos.video_id = videos.id INNER JOIN battles on battles.id = battle_videos.battle_id",
:conditions=>"battle_videos.code = 'left_side'"
}
Haven't tested this yet. 尚未测试。 But the perfect query should be more or less the similar one. 但是完美的查询应该或多或少是相似的。
I think, you should use preload
instead of includes
for loading associations. 我认为,应该使用preload
而不是includes
来加载关联。
scope :all_inclusive, preload(:battle_category, :bets, :votes, :left_side_video, :right_side_video) 范围:all_inclusive,preload(:battle_category,:bets,:votes,:left_side_video,:right_side_video)
preload
doesn't affect original query, it makes separate query for every association you specify. preload
不会影响原始查询,它会为您指定的每个关联进行单独的查询。
It works great in rails 3.0.x. 它在rails 3.0.x中很好用。 Dunno which version you use, it may differ... Dunno您使用的是哪个版本,可能会有所不同...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.