繁体   English   中英

Rails查询通过关联使用了多个has_many

[英]Rails query using more then one has_many through associations

嗨,我有6个相互关联的模型:

可以具有多个标签和元素以及一个环(也称为级别)的咒语模型

class Spell < ActiveRecord::Base

  belongs_to :spell_ring

  has_many :element_of_spells, dependent: :destroy
  has_many :spell_elements, through: :element_of_spells

  has_many :tag_of_spells, dependent: :destroy
  has_many :spell_tags, through: :tag_of_spells

  validates_presence_of :name
end

可以有很多咒语的咒语元素

class SpellElement < ActiveRecord::Base

  has_many :element_of_spells, dependent: :destroy
  has_many :spells, through: :element_of_spells
end

咒语标记,可以包含许多咒语:

class SpellTag < ActiveRecord::Base

  has_many :tag_of_spells, dependent: :destroy
  has_many :spells, through: :tag_of_spells
end

咒语环:

class SpellRing < ActiveRecord::Base

  has_many :spells
end

并加入模型:

class ElementOfSpell < ActiveRecord::Base
  belongs_to :spell
  belongs_to :spell_element
end

class TagOfSpell < ActiveRecord::Base
  belongs_to :spell
  belongs_to :spell_tag
end

好吧,现在我想好好利用它们了:)

我知道的:

如果我带了任何spell_tag或spell_element或spell_ring对象,那么我可以获得所有关联的咒语。

element = SpellElement.first
spells_of_element = element.spells >> give me all associated spells

我知道我可以使用spell_ring_id范围,因为它是spell对象的一部分。

spell_ring = SpellRing.first
spells_of_element_and_ring = spells_of_element.where( spell_ring_id: spell_ring.id ) >> returns spells of given element and ring

我不知道的是:

如何用给定的标签来spells_of_element_and_ring范围。

tag = SpellTag.first

spells_of_element_ring_and_tag = ?? 

更新

我想要的是?

是为了能够查询拼写:

  • 通过spell_tags
  • 通过spell_rings
  • 通过spell_elements

以及这三个模型的任意组合。

在发布到StackOverflow时,最好删除尽可能多的代码,然后将您的问题归结为最简单的示例,这是一个好主意。 这将获得更快的答案,并且对更多人有用。

让我们从一个简单的学校示例开始,该学校有很多教室,每个教室有很多学生。

让我们创建模型:

rails generate model school name:string
rails generate model classroom school_id:integer grade:integer
rails generate model student name:string classroom_id:integer

现在让我们创建关联:

class School < ActiveRecord::Base
  has_many :classrooms
  has_many :students, through: :classrooms
end

class Classroom < ActiveRecord::Base
  belongs_to :school
  has_many :students
end

class Student < ActiveRecord::Base
  belongs_to :classroom
end

最后,我们将创建三个快速记录:

school = School.create name: 'City Elementary'
classroom = school.classrooms.create grade: 4
student = classroom.students.create name: 'Bob'

现在,我们可以像这样获取学校所有学生的列表:

school.students

之所以has_many ,是因为学校through教室有很多学生。

我认为您实际想要的有点复杂-一个咒语可以包含许多元素,而一个元素可以属于许多咒语。 在这种情况下,您需要一个“联接表”。 让我们通过消除除咒语和元素之外的所有内容来简化示例。

我们首先创建模型:

rails generate model spell name:string
rails generate model element name:string

现在,我们创建一个联接表,该表跟踪哪些咒语和元素彼此所属:

rails generate migration create_elements_spells element_id:integer spell_id:integer

现在,我们定义关联(关系):

class Element < ActiveRecord::Base
  has_and_belongs_to_many :spells
end

class Spell < ActiveRecord::Base
  has_and_belongs_to_many :elements
end

has_and_belongs_to_many自动以字母顺序以复数形式查找具有两个模型的组合名称的表。 现在我们可以做类似的事情:

spell = Spell.create name: 'set on fire'

flint = Element.create name: 'flint'
steel = Element.create name: 'steel'

spell.elements << flint
spell.elements << steel

现在, spell.elements列出了火石和钢铁。 flint.spells将列出我们的“放火”咒语。 steel.spells也会列出我们的咒语。 您可以从那里扩展。

但是,如果您不仅需要了解什么元素,该怎么办-如果您需要了解多少,该怎么办? 现在您有了额外的数据,这些数据不属于Spell记录或Element记录。 它属于协会本身。 我们可以将元素/数量组合称为“成分”,并为其创建一个表,如下所示:

rails generate model ingredient spell_id:integer element_id:integer amount:string

并且我们更新了关联:

class Element < ActiveRecord::Base
  has_many :ingredients
  has_many :spells, through: :ingredients
end

class Spell < ActiveRecord::Base
  has_many :ingredients
  has_many :elements, through: :ingredients
end

class Ingredient < ActiveRecord::Base
  belongs_to :element
  belongs_to :spell
end

现在,我们可以为我们的咒语添加成分:

spell.ingredients.create element: flint, amount: '1 gram'
spell.ingredients.create element: steel, amount: '1 piece'

因此, spell.ingredients将同时列出火石和钢铁,以及每种的含量。 这应该使您在构建应用程序的过程中顺利进行。

@Jaime解释了整个查询过程非常好。 但是我希望查询更加灵活。

我不知道这是Rails的方式。 但是我发现这样的东西最适合我。

因为SpellElement.spells,SpellRing.spells,SpellTag.spells都返回一个数组。 我的想法是只比较它们,结果只返回匹配的元素。

所以

spell_element_ring_and_tag = some_spell_element.spells & some_spell_ring.spells & some_spell_tag.spells

将仅返回所有三个数组共享的咒语对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM