Stu*_*nig 2 ruby sql ruby-on-rails relationship has-one
我在 User 模型中有以下关系。
has_many :subscriptions, dependent: :destroy
has_one :subscription, -> { where 'end_date >= ?', Date.today }
Run Code Online (Sandbox Code Playgroud)
:subscription 本质上是他们最新的月度订阅。:subscriptions 是他们之前所有每月订阅(包括最新订阅)的数组。他们列出了 start_date、end_date、user_id、plan_id、payment_method。
当订阅计划升级或降级时,我将当前订阅的 end_date 更改为 Date.today(表示订阅今天结束),然后创建一个从今天开始并在一个月后结束的新订阅。
将 end_date 作为 Date.today 的问题在于 WHERE 子句将获取取消的订阅和新的订阅。但是会倾向于取消订阅,因为 SQL 查询在 ORDER BY 类上生成了主 ID 升序的附加信息。
ORDER BY "subscriptions"."id" ASC LIMIT 1
Run Code Online (Sandbox Code Playgroud)
对于我的一生,我无法弄清楚如何将 ID 上的 ORDER BY 从 ASC 反转为 DESC。但我更喜欢它根据 created_at 时间戳进行排序。以下将是仅用于排序的适当代码,但除了 ORDER BY 子句之外,我还需要 WHERE 子句。
has_one :subscription, -> { order 'created_at desc' }
Run Code Online (Sandbox Code Playgroud)
有没有人想过如何将两者结合起来?
从 Rails 4 开始,当您调用该first方法时,Rails 会自动按 id 添加排序。(你可以调用take来避免这种情况。)所以我猜这has_one是在first内部调用。
既然has_one只是自动创建一个名为 的方法subscription,为什么不自己创建呢?:
def subscription
subscriptions.where('end_date >= ?', Date.today).order("created_at DESC").take
end
Run Code Online (Sandbox Code Playgroud)
如果你不喜欢这个,从你的问题中不清楚你是否尝试过这个:
has_one :subscription, -> { where('end_date >= ?', Date.today).order("created_at DESC") }
Run Code Online (Sandbox Code Playgroud)
没有理由你不能像这样链接这两个项目。但是我记得 Rails 4first将覆盖您的order指令并将其替换为order(:id),因此这可能不起作用。你可以通过说来确定@user.subscription.to_sql。