【问题标题】:Ruby on Rails - Query Multiple ModelsRuby on Rails - 查询多个模型
【发布时间】:2015-08-09 22:00:55
【问题描述】:

我创建了一个在数据库中没有对应表的 ActiveRecord 模型。我希望它管理应用程序“范围”查询:

class Meter <ActiveRecord::Base
  def self.daily_tests
    self.connection.execute(sanitize_sql(["SELECT b.*, m.*, i.* FROM bgtests AS b JOIN meals AS m ON b.user_id = m.user_id JOIN injections AS i ON i.user_id = m.user_id WHERE b.user_id = 2 AND m.user_id = 2 AND i.user_id = 2"]))
  end
end

查询执行,但结果集返回:

{"id"=>1, "value"=>712, "category"=>"basal", "time_of_day"=>"Before dinner", "comments"=>"Est et aut. Est maxime sunt. Dolor doloribus distinctio sed reprehenderit culpa. Autem ipsam atque modi dolor ut non. Aut dicta voluptate occaecati.", "user_id"=>2, "created_at"=>"2015-06-21 18:58:55.806367", "updated_at"=>"2015-06-21 18:58:55.806367", "name"=>"snack", "carbohydrates"=>142, "description"=>"Facere reiciendis non officia velit consequatur voluptas eum. Veritatis quia cumque. Dolor non eaque quod. Dignissimos quae aut eveniet sunt ea amet. Iste et aut unde consequatur quia commodi.", "num_of_units_taken"=>1.0, 0=>10, 1=>712, 2=>"smbg", 3=>"Before dinner", 4=>"Est et aut. Est maxime sunt. Dolor doloribus distinctio sed reprehenderit culpa. Autem ipsam atque modi dolor ut non. Aut dicta voluptate occaecati.", 5=>2, 6=>"2015-06-21 18:58:55.595625", 7=>"2015-06-21 18:58:55.595625", 8=>12, 9=>"snack", 10=>142, 11=>"Facere reiciendis non officia velit consequatur voluptas eum. Veritatis quia cumque. Dolor non eaque quod. Dignissimos quae aut eveniet sunt ea amet. Iste et aut unde consequatur quia commodi.", 12=>2, 13=>"2015-06-21 18:58:56.115615", 14=>"2015-06-21 18:58:56.115615", 15=>1, 16=>1.0, 17=>"basal", 18=>2, 19=>"2015-06-21 18:58:55.806367", 20=>"2015-06-21 18:58:55.806367"},

初始键值作为列值返回,但随后会切换并添加后续记录,例如 5=>2。

我的问题是如何在 foreign_key 'user_id' 上查询这些多个模型,并让结果集以特定于模型的典型对象表示法返回所有结果?

【问题讨论】:

  • 你能用你使用的数据库来标记吗?还有,为什么要这样查询呢?您可以在 AR 中编写此查询...
  • 我无法重现 Rails 4.1 + PostgreSQL 的问题。您是否在不同的表上有同名的列?
  • 我更喜欢使用 AR。我在三个表中都有一个 user_id 列。

标签: sql ruby-on-rails ruby activerecord


【解决方案1】:

除了文档中指定的其他形式之外,ActiveRecord query interface 定义的大多数方法都接受 SQL 字符串参数。您也可以将这些方法任意链接起来,AR 将结合起来创建合适的 SQL。如有疑问,请使用to_sql 查看生成的 SQL。假设 bgtests 对应于名为 Bgtest 的模型,您可以例如执行以下操作:

Bgtest.select("b.*, m.*, i.*").from("bgtests b")
.joins("JOIN meals AS m ON b.user_id = m.user_id")
.joins("JOIN injections AS i ON i.user_id = m.user_id")
.where("b.user_id = 2 AND m.user_id = 2 AND i.user_id = 2")

方法链之所以如此工作,是因为每个方法都返回一个 ActiveRecord::Relation 对象,该对象接受与 ActiveRecord::Base (您的模型子类)相同的 ActiveRecord::QueryMethods 方法。因此,方法调用的顺序是任意的。在您尝试从关系中提取值之前,该 SQL 不会实际执行,无论是由于控制台调用 to_s 还是因为您在视图中调用 each

请注意,通过在模型上定义正确的associations,可以大大简化上述内容(以及更多“Rails-y”)。特别是,BgtestMealInjection 类显然都会调用belongs_to :user,而User 会调用has_many :bgtests 等。然后您可以在其他类中使用has_many with :through option,例如Bgtest 可以调用has_many :meals, through: user 等。然后AR 会根据单独引用关联名称知道INNER JOIN

Bgtest.joins(:meals, :injections).where(user_id: 2)

LEFT OUTER JOIN:

Bgtest.includes(:meals, :injections).where(user_id: 2)

【讨论】:

    猜你喜欢
    • 2016-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 2020-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多