You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rails控制器中从has_many through关联随机获取记录?

问题描述

我有一个能返回随机Recipe记录的Rails控制器方法:

@recipe =  Recipe.order('RANDOM()').first

现在需要基于Recipe和Season的has_many through关联,返回属于指定season_id的随机Recipe记录。

模型关联定义如下:
Recipe模型:

class Recipe < ApplicationRecord
  attribute :name

  has_many :recipe_seasons
  has_many :seasons, through: :recipe_seasons
end

Season模型:

class Season < ApplicationRecord
    has_many :recipe_seasons
    has_many :recipes, through: :recipe_seasons
end

RecipeSeason模型:

class RecipeSeason < ApplicationRecord
  belongs_to :recipe
  belongs_to :season
end

我当前的代码尝试:

@date = Time.now
@month = @date.month
@season = Season.find(@month)

@recipe =  Recipe.where(recipe_seasons: @month).order('RANDOM()').first

这段代码错误地返回了recipe_season_id等于@month的记录,而我需要的是season_id等于@month的随机Recipe记录。尝试了Recipe.where(recipe_seasons: season_id: @month)...也无效,求正确实现方式。

正确实现方式

方式一:通过关联表条件查询

使用嵌套哈希指定关联表的字段条件,同时必须通过joins关联中间表,让Rails正确识别关联字段:

@date = Time.now
@month = @date.month
@recipe = Recipe.joins(:recipe_seasons)
                .where(recipe_seasons: { season_id: @month })
                .order('RANDOM()')
                .first

方式二:通过Season关联直接获取

既然已经查询到目标Season记录,可直接从其关联的recipes集合中取随机记录,写法更符合Rails关联语义:

@date = Time.now
@month = @date.month
@season = Season.find(@month)
@recipe = @season.recipes.order('RANDOM()').first

方式三:跨数据库兼容的随机查询(Rails 6+)

如果使用Rails 6及以上版本,可使用order(:random)或Arel.sql('random()')替代原生SQL,提升跨数据库兼容性:

# 对应方式一的升级写法
@recipe = Recipe.joins(:recipe_seasons)
                .where(recipe_seasons: { season_id: @month })
                .order(:random)
                .first

# 对应方式二的升级写法
@recipe = @season.recipes.order(:random).first

内容的提问来源于stack exchange,提问作者cinameng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:25:22