Ruby on rails 即使外键有效,Rails也属于返回nil 总结

Ruby on rails 即使外键有效,Rails也属于返回nil 总结,ruby-on-rails,foreign-keys,associations,Ruby On Rails,Foreign Keys,Associations,我遇到了一个问题,我的所属关联正在返回nil,而我认为它不应该返回 我想做什么 ChannelUser应该能够从相关的channel返回消息,其中在处创建的大于其用户上次从该频道读取的时间。类别定义如下: class ChannelUser{includes(:通道)} def未读消息 channel.messages.where('created\u at>?',last\u read\u at) 结束 结束 类用户{includes(:channel)},依赖::destroy 拥有多个:频

我遇到了一个问题,我的
所属
关联正在返回
nil
,而我认为它不应该返回

我想做什么
ChannelUser
应该能够从相关的
channel
返回消息,其中在
处创建的
大于其
用户上次从该
频道读取的
时间。类别定义如下:

class ChannelUser{includes(:通道)}
def未读消息
channel.messages.where('created\u at>?',last\u read\u at)
结束
结束
类用户<应用程序记录
拥有多个:channel用户,->{includes(:channel)},依赖::destroy
拥有多个:频道,通过::频道用户
有很多:信息
结束
类通道<应用程序记录
拥有多个:通道用户,依赖::销毁
拥有多个:用户,通过::通道用户
有很多:消息,->{order(在::asc创建)。limit(100)},dependent::destroy
结束
类消息<应用程序记录
属于:频道
属于:用户
有丰富的文本:body
...
结束
我试图呈现来自用户在视图中加入的所有频道的未读邮件总数:


User
类有
有许多:频道用户
有许多:频道,通过::频道用户
Channel
类有
有许多:Channel\u用户
有许多:用户,通过::Channel\u用户

问题 当我使用任何
ChannelUser
实例在rails控制台中执行
unread\u messages
方法时,我没有收到任何错误。但是,当我在开发中运行应用程序时,我得到:

正如您在图片底部的web控制台中所看到的,
channel
返回
nil
,即使
channel\u id
是有效的外键。事实上,模式的定义如下:

class CreateChannelUsers
我还使用
在视图中放置了一个断点,并查看了
当前用户
当前用户、频道用户和
当前用户、频道用户的值。首先,未读消息
。对于
current_user
,我获得了与我的登录帐户关联的
user
实例。对于
current\u user.channel\u users
,我获得了代表我加入的聊天频道的记录。对于
curretn\u user.channel\u users.first.unread\u messages
,我没有收到错误,我得到一个空的关系集,正确地标识我没有任何未读消息。重要的是要注意,当我没有聚合所有未读邮件的总和时,不会发生此错误

更新 我发现我可以通过单击调用堆栈中的行来更改web控制台的范围,因此下面是web控制台的更多输出:

>> current_user.channel_users

=> #<ActiveRecord::Associations::CollectionProxy [#<ChannelUser id: 7, channel_id: 5, user_id: 1, created_at: "2020-11-09 06:42:52", updated_at: "2020-11-15 23:44:28", last_read_at: "2020-11-15 23:44:28">, #<ChannelUser id: 3, channel_id: 4, user_id: 1, created_at: "2020-11-09 06:26:12", updated_at: "2020-11-09 06:27:03", last_read_at: "2020-11-09 06:27:03">, #<ChannelUser id: 4, channel_id: 6, user_id: 1, created_at: "2020-11-09 06:30:41", updated_at: "2020-11-15 23:32:26", last_read_at: "2020-11-15 23:32:26">, #<ChannelUser id: 8, channel_id: 7, user_id: 1, created_at: "2020-11-10 01:20:44", updated_at: "2020-11-15 23:33:24", last_read_at: "2020-11-15 23:33:24">]>

>> current_user.channel_users.map(&:unread_messages)

NoMethodError: undefined method `messages' for nil:NilClass
    from /home/jakehockey10/Code/team-portal/app/models/channel_user.rb:29:in `unread_messages'
    from /home/jakehockey10/Code/team-portal/app/views/dashboard/show.html.erb:9:in `map'
    from /home/jakehockey10/Code/team-portal/app/views/dashboard/show.html.erb:9:in `_app_views_dashboard_show_html_erb___259171981150348787_116880'

>> current_user.channel_users.first.unread_messages

NoMethodError: undefined method `messages' for nil:NilClass
    from /home/jakehockey10/Code/team-portal/app/models/channel_user.rb:29:in `unread_messages'
    from /home/jakehockey10/Code/team-portal/app/views/dashboard/show.html.erb:9:in `_app_views_dashboard_show_html_erb___259171981150348787_116880'

>> current_user.channel_users.first

=> #<ChannelUser id: 7, channel_id: 5, user_id: 1, created_at: "2020-11-09 06:42:52", updated_at: "2020-11-15 23:44:28", last_read_at: "2020-11-15 23:44:28">

>> current_user.channel_users.first.channel

=> nil

>> Channel.find(5)

=> #<Channel id: 5, name: "general", account_id: 2, created_at: "2020-11-09 06:30:32", updated_at: "2020-11-09 06:30:32", direct_message: false>

另一个更新 这是蛋糕上的糖霜:

我不知道这是怎么回事,我想知道这是否是某种名称冲突问题或其他什么。如何诊断

更新 同样的问题,尝试不同的方法:


为什么它会在这一行抛出错误,但如果我将同一行粘贴到web控制台的错误页面上,它不会抛出错误?我遗漏了什么?

尝试删除
包含的内容,我不是100%确定,但这可能是潜在的问题

class User < ApplicationRecord
  has_many :channel_users, dependent: :destroy
class用户
您可以用替换模型中的
包括


我95%确信问题来自消息模型

似乎channel.messages不等于channel.user.messages。

首先,您没有在问题中向我们展示消息的模型,请更新问题

其次,您有两个模型:频道和用户,它们都与消息模型有关联(
有许多:消息
),而对我来说,这并不是很好的关联(在看到消息模型之前,我无法了解解决方案)

第三,在您的查询中:

User.first.channel_users.sum(&:unread_messages)
其中一行:

Message Load (0.4ms)  SELECT "messages".* FROM "messages" WHERE "messages"."channel_id" = $1 AND (created_at > '2020-11-15 23:44:28.787257') ORDER BY "messages"."created_at" ASC LIMIT $2  [["channel_id", 5], ["LIMIT", 100]]
  Message Load (0.2ms)  SELECT "messages".* FROM "messages" WHERE "messages"."channel_id" = $1 AND (created_at > '2020-11-09 06:27:03.105358') ORDER BY "messages"."created_at" ASC LIMIT $2  [["channel_id", 4], ["LIMIT", 100]]
  Message Load (0.2ms)  SELECT "messages".* FROM "messages" WHERE "messages"."channel_id" = $1 AND (created_at > '2020-11-15 23:32:26.070403') ORDER BY "messages"."created_at" ASC LIMIT $2  [["channel_id", 6], ["LIMIT", 100]]
  Message Load (0.2ms)  SELECT "messages".* FROM "messages" WHERE "messages"."channel_id" = $1 AND (created_at > '2020-11-15 23:33:24.022821') ORDER BY "messages"."created_at" ASC LIMIT $2  [["channel_id", 7], ["LIMIT", 100]]
例如,第一行类似于:

Message Load (0.4ms)  SELECT "messages".* FROM "messages" WHERE "messages"."channel_id" = 5 AND (created_at > '2020-11-15 23:44:28.787257') ORDER BY "messages"."created_at" ASC LIMIT 100
这意味着:获取100条已排序的消息,其通道id=5。这个返回空值!或空消息集


因此,我的问题就来自于此。

我终于解决了这个问题。在此应用程序中,为了提供多租户,每个用户都有一个关联的帐户。账户可以是个人账户,也可以是非个人账户。登录后,您可以将视角从个人帐户更改为与您关联的任何非个人帐户。然后,具有
account\u id
列的资源将被过滤为当前帐户。这种过滤发生在中间件中,因此与执行实际查询的代码分离

当我第一次开始实现此功能时,我在尝试将通道(作为一个整体功能)限制为非个人帐户上下文之前,在我的个人帐户上创建了一些通道。因此,我的数据库中有一些与个人账户相关的渠道

在我的屏幕截图中,应用程序使用该中间件将频道限制为具有特定当前
帐户id的频道。但当我在web控制台或rails控制台中模拟相同的查询时,显然没有运行中间件来过滤当前帐户的内容
Message Load (0.4ms)  SELECT "messages".* FROM "messages" WHERE "messages"."channel_id" = 5 AND (created_at > '2020-11-15 23:44:28.787257') ORDER BY "messages"."created_at" ASC LIMIT 100