【发布时间】:2016-08-12 05:20:43
【问题描述】:
我想在 Rails 4 中以 ActiveRecord 和 Postgres 作为数据库的一对多关系获取在特定日期创建的 no 记录的所有父记录。
迁移:
class CreateParents < ActiveRecord::Migration
def change
enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')
create_table :parents, id: :uuid, default: 'gen_random_uuid()' do |t|
t.string :name
t.timestamps null: false
end
end
class CreateChilds < ActiveRecord::Migration
def change
create_table :childs, id: false do |t|
t.uuid :parent_id, null: false
t.date :created_at, null: false
t.string :name
end
add_foreign_key :childs, :parents
add_index :childs, [:parent_id, :created_at], :unique => true
end
end
型号:
class Parent < ActiveRecord::Base
has_many :childs
end
class Child < ActiveRecord::Base
belongs_to :parent
end
现在我想让所有在特定日期没有孩子的父母都有一个范围:
class Parent < ActiveRecord::Base
has_many :childs
def self.with_no_childs_created_at(date)
...
end
end
有人可以帮我吗?我真的要疯了。我用.includes、.references、.where、.not、.joins 等尝试了很多东西,但我不明白。
更新 1
一个建议的解决方案如下所示:
def self.with_no_stats_created_at(date)
joins(:childs).where.not(childs: {created_at: date})
end
但这仅适用于父级过去已经创建了一个子级的情况。 SQL 应该能说明问题:
SELECT "parents".*
FROM "parents"
INNER JOIN "childs" ON "childs"."parent_id" = "parents"."id"
WHERE ("childs"."created_at" != $1) [["created_at", "2016-04-19"]]
更新 2
这解决了问题(@Ilya 建议):
def self.with_no_childs_created_at(date)
preload(:childs).select {|p| p.childs.all? {|c| c.created_at != date }}
end
【问题讨论】:
-
“没有孩子的父母”这个概念好奇怪,看到你的标题我笑死了!谢谢!
-
不幸的是,没有父母的孩子很常见。但直到现在还没有听说过相反的事情!
标签: ruby-on-rails ruby postgresql ruby-on-rails-4 activerecord