我遇到了n + 1个查询的问题,我想加载一个关系,除非我在定义关系时遇到问题。这很复杂,哈哈,听我说。
我有两个模特。
class Pokemon < ActiveRecord::Base
belongs_to :pokemon_detail, primary_key: "level", foreign_key: "level"
end
class PokemonDetail < ActiveRecord::Base
has_one :pokemons, primary_ley: "level", foreign_key: "level"
end
让我们说,我有以下记录:
<Pokemon id: 1, name: "squirtle", level: 1>
这显然与以下PokemonDetail
<PokemonDetail id: 1, name: "squirtle", level: 1, health: 150>
这可以像Pokemon.all.includes(:pokemon_detail)
那样轻松加载,但是,我希望将信息加载到更高的一级。
<PokemonDetail id: 2, name: "squirtle", level: 2, health: 300>
我目前在Pokemon
模型中使用以下方法找到关于更高级别的信息。
def next_level_info
PokemonDetail.where(level: self.level + 1)
end
但这并不急于加载。有什么想法吗?
答案 0 :(得分:0)
首先重构架构,使其更有意义:
pokemons { current_level_value, name }
pokemon_levels {value, pokemon_id (foreign key), health }
重新定义这样的模型:
class PokemonLevel < ActiveRecord::Base
belongs_to :pokemon
end
class Pokemon < ActiveRecord::Base
has_many :pokemon_levels
has_one :current_pokemon_level, -> { joins(:pokemon).where('pokemons.current_level_value = pokemon_levels.value') },
foreign_key: :pokemon_id, class_name: 'PokemonLevel'
has_one :next_pokemon_level, -> { joins(:pokemon).where('pokemons.current_level_value + 1 = pokemon_levels.value') },
foreign_key: :pokemon_id, class_name: 'PokemonLevel'
end
只需使用它,例如:
Pokemon.includes(:current_pokemon_level, :next_pokemon_level).find(123)
我使用PokemonLevel
代替PokemonDetail
,因为它对我来说更清楚