需要使用范围进行嵌套连接的 ActiveRelation

2024-02-05

我是 Rails 新手。玩得很开心。查询 API 给了我 有些麻烦。我一直在快速地缩放并做很多事情, 但这是我第一次花几个小时试图弄清楚。 它不像我以前使用过的任何东西——常规 SQL 或 Hibernate, 管他呢。

我的模型非常简单。

  • 私人消息有多个收件人
  • A Recipient has a Receiver (which of class User)
    • 收件人还有“is_read”和“is_deleted”字段

我的目标是建立一个查询来查找所有未读且未删除的内容 给定用户的私人消息。为了实现这一目标,我们需要加入 'private_messages' 到 'recipients'...然后 'recipients' 到 “用户”。

这是相关的用户模型代码:

has_many :sent_messages, :class_name => 'PrivateMessage', :foreign_key => 'sender_id'
has_many :recipient_of_messages, :class_name => 'Recipient', :foreign_key => 'receiver_id'

scope :by_id, lambda { |id| where(:id => id) } 

我的收件人模型具有以下相关代码:

belongs_to :receiver, :class_name => 'User', :foreign_key => "receiver_id"
belongs_to :private_message

scope :unread, where(:is_read => false).where(:is_deleted => false)
scope :by_receiver_id, lambda { |id| Recipient.joins(:receiver).merge(User.by_id(id)) }
scope :unread_by_receiver_id, lambda { |id| unread.by_receiver_id(id) }

单独测试时,此方法 100% 有效。

然而,当我编写私人消息查询代码时,我遇到了问题。

belongs_to :sender, :class_name => 'User'
has_many :recipients, :class_name => 'Recipient'

scope :sorted, order("private_messages.created_at desc")
scope :non_deleted, where(:is_deleted_by_sender => false)
scope :non_deleted_by_sender_id, lambda { |id| sorted.non_deleted.joins(:sender).merge(User.by_id(id)) }

# this scope does not work
scope :non_deleted_by_receiver_id, lambda { |id| sorted.joins(:recipients).merge(Recipient.by_receiver_id(id)) }
scope :newest, sorted.limit(3)

# this scope does not work either
scope :newest_unread_by_receiver_id, lambda { |id| newest.joins(:recipients).merge(Recipient.unread_by_receiver_id(id)) }

当我尝试使用“newest_unread_by_receiver_id”或“non_deleted_by_receiver_id”时,出现以下异常:

ActiveRecord::ConfigurationError: Association named 'receiver' was not found; perhaps you misspelled it?

这对我来说没有多大意义......因为如果名字被拼写出来 错了,为什么我测试隔离时它没有失败?

有人可以帮我吗?这让我发疯。有时 像这样,我只想用完整的 sql 或 Hibernate QL 进行编程,这样我就可以完成它了:(

如果我完全错误地处理了这个问题,那么如果您也让我知道这一点,我将不胜感激。我的印象是,使用范围和 ActiveRelation 是 Rails 3.1 中前进的方向。

Thanks


我可能会使用这样的东西。为了清楚起见,我将范围分开。

Models(重命名为 PrivateMessage -> 消息和收件人 -> MessageCopy):

class User < ActiveRecord::Base
  has_many :sent_messages, :class_name => "Message", :foreign_key => :sender_id
  has_many :sent_message_copies, :through => :sent_messages, :source => :message_copies
  has_many :received_messages, :through => :received_message_copies, :source => :message
  has_many :received_message_copies, :class_name => "MessageCopy", :foreign_key => :recipient_id
end

class Message < ActiveRecord::Base
  belongs_to :sender, :class_name => "User"
  has_many :message_copies
  has_many :recipients, :through => :message_copies
end

class MessageCopy < ActiveRecord::Base
  belongs_to :message
  belongs_to :recipient, :class_name => "User"
  scope :unread, where(:read => false)
  scope :undeleted, where(:deleted => false)
  scope :sent_to, lambda { |recipient| where(:recipient_id => recipient.id) }
end

Schema(迁移在这里会占用太多空间):

ActiveRecord::Schema.define(:version => 20110503061008) do
  create_table "message_copies", :force => true do |t|
    t.boolean  "read",         :default => false
    t.boolean  "deleted",      :default => false
    t.integer  "message_id"
    t.integer  "recipient_id"
  end
  create_table "messages", :force => true do |t|
    t.string   "title"
    t.integer  "sender_id"
  end
  create_table "users", :force => true do |t|
    t.string   "name"
  end
end

--edit

使用连接返回消息的示例查询

Message.joins(:message_copies).where(:message_copies => {:read => false, :deleted => false, :recipient_id => 3})

消息范围在其他模型上重用范围

scope :non_deleted_by_recipient, lambda { |recipient|
  joins(:message_copies).merge(MessageCopy.unread.undeleted.sent_to(recipient))
}

--edit2

这个 Railscast 有很好的连接和作用域示例:

  • http://railscasts.com/episodes/215-advanced-queries-in-rails-3 http://railscasts.com/episodes/215-advanced-queries-in-rails-3
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

需要使用范围进行嵌套连接的 ActiveRelation 的相关文章

  • kaminari ajax 分页不更新分页

    我正在使用 kaminari gem 在 Rails3 中实现分页 我一直在关注github上的这段代码https github com amatsuda kaminari example commits ajax https github
  • 什么是 - 获取的是一个目录 - 错误消息

    我收到这个奇怪的错误 Users gideon Documents ca ruby rubytactoe lib player rb 13 in gets Is a directory spec Errno EISDIR 玩家规格 rb r
  • 为什么 rand() 总是返回相同的数字?

    我在用 兰特 200 在我的 Rails 应用程序中 当我在控制台中运行它时 它总是返回随机数 但如果我在应用程序行中使用它 index rand 200 索引总是相同的号码 为什么会这样以及如何克服这个问题 简单的伪随机数生成器实际上生成
  • 在 CircleCI 中设置 Elasticsearch 和 Ruby on Rails

    我正在尝试在 Rails 应用程序中使用 Elasticsearch 设置 CircleCI 我想已经配置了镜像 但是如何在 CI 中连接到它 到目前为止我已经尝试过 https github com elastic elasticsear
  • ||= 是什么意思? [复制]

    这个问题在这里已经有答案了 我的应用程序控制器中有一个受保护的方法 def current user current user User find by id session user id end 我想知道什么 方法 我一直在努力寻找和找
  • 将 ruby​​ 类转换为模块比使用改进更好的方法?

    Module refine http ruby doc org core 2 0 0 Module html method i refine方法接受一个类和一个块并返回一个细化模块 所以我想我可以定义 class Class def inc
  • Rails 3 Mechanize - SocketError:getaddrinfo:主机或名称未知

    我正在使用 mechanize 但出现此错误 有人可以帮帮我吗 我已将元刷新设置为 true 错误日志 SocketError getaddrinfo Host or name not known form C Ruby192 lib ru
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • Yii2:如何在ActiveRecord中设置默认属性值?

    这似乎是一个微不足道的问题 但是我能想到的所有明显的解决方案都有其自身的缺陷 我们想要的是能够仅为新记录设置任何默认的 ActiveRecord 属性值 使其在验证之前和验证期间可读 并且不会干扰用于搜索的派生类 一旦我们实例化该类 就需要
  • class_eval、class_exec、module_eval 和 module_exec 之间有什么区别?

    我正在读Module文档 但似乎无法理解它们的差异以及应该在哪里使用 怎么样eval不同于exec 我将回答比你的问题更多的内容 包括instance eval exec 在你的问题中 所有变体 instance module class
  • 如何在生产服务器中运行 sidekiq?

    我有一个带有apache passenger的服务器 我将如何奔跑sidekiq在生产中 运行所需的任何配置 bundle exec sidekiq Thanks bundle exec sidekiq d L log sidekiq lo
  • Rails 4 和 Turbolinks - 元标签未更改

    我有一个启用了 Turbo Links 的 Rails 4 应用程序 但在更改页面时无法刷新元标记 不是完全刷新 我读到元标记需要包含在加载涡轮链接的 JavaScript 之前 但它没有效果 完全刷新可以完成这项工作 但不幸的是这不是我所
  • 使用redirect_to :create 动作

    我正在尝试重定向到另一个控制器的创建方法 但是 我找不到将方法设置为 POST 的方法 这将导致调用索引方法 使用 method gt post只是创建一个新参数 但不会更改 http 方法 有什么想法如何重定向到创建方法吗 您无法在重定向
  • Emacs、ruby:将 do 结束块转换为大括号,反之亦然

    我经常发现自己转换这样的代码 before do something end to before something 有没有办法在 emacs 中自动执行此任务 我使用 ruby mode 和 rinary 但它们在这里没有太大帮助 rub
  • 在 mac os Sierra 上,卡在“设置 CocoaPods 主存储库”上

    转移到 mac os sierra 后 我完全格式化了我的 mac 现在每次运行时我都面临安装 cocoapods 的问题sudo gem install cocoapods pre一切都安装得很好 当我尝试安装 Pod 时 终端堆栈打开S
  • Rails - 用于集合集的单选按钮

    我有以下输出选择框 br 替代输出单选按钮的 Rails 方法是什么 对于单选按钮 您必须自行迭代并输出每个单选按钮及其标签 事实上这真的很容易
  • 如何以 Rails 形式将图像从 上传到具有 Rails Active Storage 的 S3?

    正如标题中所述 我正在尝试使用 Rails 的 Active Storage 从嵌套在 Rails 表单中的元素将图像上传到我的 S3 存储桶 到目前为止我已经能够使用使用 Active Storage 上传图像 这User class h
  • Rails 3.1 中何时将图像放入 app/assets 以及何时放入 /public/images?

    我仍然不太明白 在这种情况下 在 Rails 3 1 中将图像放在哪里 图像被处理 例如通过回形针或蜻蜓 并存储在文件夹中 不使用像 s3 这样的外部服务 f e 在开发中 当我只有图像时 我将在样式表中使用它 例如背景 图标 AppSto
  • 用于验证目的的动态查找方法

    我正在使用 Ruby on Rails 3 0 7 我想在运行时查找一些记录以进行验证 但为该查找方法传递 设置一个值 也就是说 在我的班级中 我有以下内容 class Group lt lt ActiveRecord Base valid
  • rspec 中的模拟方法链

    有一系列方法可以获得user目的 我试图模拟以下内容以返回user in my Factory Girl current user AuthorizeApiRequest call request headers result 我可以模拟该

随机推荐