问题类has_many选择。我需要通过一些属性值(通常是id)找到一个选择。
澄清:父记录(问题)是围绕不同的对象和方法传递的,它们使用不同的属性和值搜索子项。
我可以question.choices.find(choice_id)
,但每次都会生成一个SQL查询。
知道问题通常只有少数选择,并且在一条父记录上会有很多不同的搜索,我怀疑在Ruby中加载整个关联和搜索会更便宜:
question.choices.detect{|choice| choice.id == some_choice_id}
Detect来自Enumerable并强制Rails在第一次调用时加载关联(并在将来的搜索中使用缓存数据)。这也很好地与急切加载:我可以做Question.all(包括:选择),并将整个树加载两个查询,然后搜索非常快。但它读起来并不是很好。
如果我想模拟发现它会变得更加毛茸茸!行为:
question.choices.detect{|choice| choice.id == choice_id} or raise ActiveRecord::RecordNotFound.new
这正是我想要的,我只是在寻找更好的语法。
Rails是否提供了某种行为方式(在第一次查询时强制加载整个关联,然后搜索这个预加载的集合)?
答案 0 :(得分:0)
我怀疑我错过了在Rails中烘焙或在流行宝石中可用的东西。如果不是这样的话,我只会自己动手帮助:
Enumerable.module_eval do
def select_by(attribute_name, value)
detect do |item|
item.send(attribute_name) == value
end
end
def select_by!(attribute_name, value)
select_by(attribute_name, value) \
or raise StandardError.new("can't find item with #{attribute_name} equal to #{value} in #{self.inspect}")
end
end
用法是:
question.choices.select_by(:id, 7)
user.question.select_by(:name, "Is it shiny?")
答案 1 :(得分:0)
我相信你想要的东西被称为“渴望加载”,并使用.includes
方法实现。
@questions = Question.includes(:choices).all
将导致执行内部联接的查询,返回问题及其每个选项。这假设您已在模型中声明了关系。据推测,你将使用where where子句而不是.all
来限定。