gpt4 book ai didi

ruby-on-rails - 具有多态关联的范围和查询

转载 作者:数据小太阳 更新时间:2023-10-29 06:44:31 27 4
gpt4 key购买 nike

关于如何在 Rails 中为多态关联编写作用域,我发现的很少,更不用说如何在多态关联上编写查询了。

在 Rails 文档中,我查看了 Polymorphic Associations section , Joining Tables section , 和 Scopes section .我也做了我应得的谷歌搜索。

以这个设置为例:

class Pet < ActiveRecord::Base
belongs_to :animal, polymorphic: true
end

class Dog < ActiveRecord::Base
has_many :pets, as: :animal
end

class Cat < ActiveRecord::Base
has_many :pets, as: :animal
end

class Bird < ActiveRecord::Base
has_many :pets, as: :animal
end

所以宠物可以是animal_type“狗”、“猫”或“鸟”。

要显示所有表结构:这是我的schema.rb:

create_table "birds", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "cats", force: :cascade do |t|
t.integer "killed_mice"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "dogs", force: :cascade do |t|
t.boolean "sits"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "pets", force: :cascade do |t|
t.string "name"
t.integer "animal_id"
t.string "animal_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

然后我继续做一些记录:

Dog.create(sits: false)
Dog.create(sits: true)
Dog.create(sits: true) #Dog record that will not be tied to a pet
Cat.create(killed_mice: 2)
Cat.create(killed_mice: 15)
Cat.create(killed_mice: 15) #Cat record that will not be tied to a pet
Bird.create

然后我去制作了一些宠物记录:

Pet.create(name: 'dog1', animal_id: 1, animal_type: "Dog")
Pet.create(name: 'dog2', animal_id: 2, animal_type: "Dog")
Pet.create(name: 'cat1', animal_id: 1, animal_type: "Cat")
Pet.create(name: 'cat2', animal_id: 2, animal_type: "Cat")
Pet.create(name: 'bird1', animal_id: 1, animal_type: "Bird")

这就是设置!现在是困难的部分:我想在 Pet 模型上创建一些作用域,以挖掘多态关联。

这里有一些我想写的作用域:

  • 给我所有可以坐下的Pets animal_type == "Dog"
  • 给我所有杀死至少 10 只老鼠的 animal_type == "Cat"的 Pet
  • 给我所有既不是 animal_type“狗”又不能坐的宠物。 (换句话说:给我所有的宠物:所有的宠物:除了不能坐的狗)

所以在我的 Pet 模型中,我想把我的示波器放在那里:

class Pet < ActiveRecord::Base
belongs_to :animal, polymorphic: true

scope :sitting_dogs, -> {#query goes here}
scope :killer_cats, -> {#query goes here}
scope :remove_dogs_that_cannot_sit, -> {#query goes here} #only removes pet records of dogs that cannot sit. All other pet records are returned
end

我发现编写这些范围非常困难。

我在网上找到的一些东西让您看起来只能使用原始 SQL 编写这些作用域。我想知道是否可以对这些范围使用哈希语法。

任何提示/帮助将不胜感激!

最佳答案

在回顾了以前的答案并尝试了一下之后:这就是我要做的。

(请注意,Pet.remove_dogs_that_cannot_sit 返回一个数组。此类方法可读性强,但由于 N + 1 而存在速度慢的缺点。任何建议将不胜感激。)

class Dog < ActiveRecord::Base
has_many :pets, as: :animal
scope :sits, -> {where(sits: true)}
end

class Cat < ActiveRecord::Base
has_many :pets, as: :animal
scope :killer, ->{ where("killed_mice >= ?", 10) }
end

class Pet < ActiveRecord::Base
belongs_to :animal, polymorphic: true

scope :by_type, ->(type) {where(animal_type: type)}
scope :by_dogs, -> {by_type("Dog") }
scope :by_cats, -> {by_type("Cat") }

def self.sitting_dogs
all.by_dogs
.joins("INNER JOIN dogs on animal_type = 'Dog' and animal_id = dogs.id")
.merge(Dog.sits)
end

def self.killer_cats
all.by_cats
.joins("INNER JOIN cats on animal_type = 'Cat' and animal_id = cats.id")
.merge(Cat.killer)
end

# returns an Array not Pet::ActiveRecord_Relation
# slow due to N + 1
def self.remove_dogs_that_cannot_sit
all.reject{|pet| pet.animal_type == "Dog" && !pet.animal.sits}
end
end

关于ruby-on-rails - 具有多态关联的范围和查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41112845/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com