【问题标题】:ActiveRecord: Get all users who should be banned todayActiveRecord:获取今天应该被禁止的所有用户
【发布时间】:2017-08-02 10:31:24
【问题描述】:

我有两个模型:

class User < ActiveRecord::Base
  has_many :ban_messages, dependent: :destroy
end

class BanMessage < ActiveRecord::Base
  belongs_to :user
end

BanMessage 包含一个字段t.datetime :ban_date,该字段存储了应该禁止用户的日期。 User 表包含一个字段status,其中包含状态值之一(活动、暂停、禁止)。当我向用户发送 BanMessage 时,他的状态字段从“活动”变为“暂停”。我也可以重新激活用户,这样他就不会在':ban_date' 被禁止,但他的 BanMessage 不会被破坏。 因此,我需要创建查询以选择所有状态为“已暂停”的用户,这些用户在其最新的 BanMessages 记录“ban_date”字段中具有 DateTime 值,该值介于 'DateTime.now.beginning_of_day''DateTime.now.end_of_day' 之间。

【问题讨论】:

  • 您能否指定您要使用的 SQL 版本? - 到目前为止,您还可以粘贴您在查询中的尝试吗,任何表格和一些示例数据都会有所帮助
  • @jimmy8ball,我正在使用 ActiveRecord。

标签: ruby-on-rails activerecord


【解决方案1】:

您可以使用where 查询过滤您的用户,然后使用join 方法将ban_messageswhere 方法关联,以进一步过滤日期范围。

User.where(status: 'suspended').joins(:ban_messages).where("ban_date >= ? AND ban_date <= ?", DateTime.now.beginning_of_day, DateTime.now.end_of_day )

【讨论】:

  • 不,它会向我显示具有旧 ban_message 且 ban_date 介于 DateTime.now.beginning_of_day 和 DateTime.now.end_of_day 之间的用户,即使用户有较新的 ban_message 和另一个 ban_date。
【解决方案2】:

试试这样的。

User.joins(:ban_messages).where(status: :suspended).where('ban_messages.ban_date BETWEEN :begin_time AND :end_date', begin_time: DateTime.now.beginning_of_day, end_time: DateTime.now.end_of_day)

【讨论】:

  • 不,它会向我显示具有旧 ban_message 且 ban_date 介于 DateTime.now.beginning_of_day 和 DateTime.now.end_of_day 之间的用户,即使用户有较新的 ban_message 和另一个 ban_date。
【解决方案3】:

这是我需要的:

User.joins(:ban_messages)
  .where('users.status = ?', :suspended)
  .where('ban_messages.created_at = (SELECT MAX(ban_messages.created_at) FROM ban_messages WHERE ban_messages.user_id = users.id)')
  .where('ban_messages.ban_date BETWEEN ? and ?',  DateTime.now.beginning_of_day, DateTime.now.end_of_day)
  .group('users.id')

更新

MrYoshiji代码中的警告是,如果你错过了一天,那么 第二天你就看不到应该被禁止的人了 前一天。您可能希望获取 ban_date 所在的所有用户 小于 DateTime.now.end_of_day,在同一视图中或 另一个。

所以最终的查询可能是这样的

User.joins(:ban_messages)
  .where('users.status = ?', :suspended)
  .where('ban_messages.created_at = (SELECT MAX(ban_messages.created_at) FROM ban_messages WHERE ban_messages.user_id = users.id)')
  .where('ban_messages.ban_date < ?', DateTime.now.end_of_day)
  .group('users.id')

【讨论】:

  • 代码中的警告是,如果您错过了一天,那么第二天您将看不到前一天应该被禁止的人。您可能希望在同一视图或另一个视图中获取 ban_date 小于 DateTime.now.end_of_day 的所有用户。
  • @MrYoshiji,此代码将在每天上午 12 点通过 cro 运行。您认为这可能是 cron 无法完成其工作的情况吗?那么你是对的。
  • 嗯,是的。如果您的服务器此时正在重新启动,或者 cron 作业无法读取数据库(例如 db 服务关闭),或者其他任何情况,脚本将不会被执行,这是您不想要的。处理此问题的最佳方法是获取所有“禁止日期小于或等于今天”的记录。
猜你喜欢
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 2020-09-28
  • 2019-11-12
  • 1970-01-01
  • 2021-12-11
  • 2021-02-15
  • 1970-01-01
相关资源
最近更新 更多