自我加入正确的关联以用于口袋妖怪及其进化吗?
Is a self join the correct association to use for a pokemon and its evolutions?
我正在努力研究口袋妖怪与其进化之间的正确关联。我认为我接近正确答案,但我在尝试对此建模以完成时遇到问题。这是我努力实现的目标。
bulbasaur = Pokemon.find(1)
bulbasaur.evolved_forms ---> [ivysaur, venasaur]
ivysaur = Pokemon.find(2)
ivysaur.evolved_forms ----> [venusaur]
ivysaur.pre-evolved_forms ---> [bulbasaur]
venusaur = Pokemon.find(3)
venusaur.evolved_forms ----> []
venusaur.pre-evolved_forms ---> [ivysaur, bulbasaur]
我有以下型号。
class Pokemon < ApplicationRecord
has_many :evolved_forms, class_name: "Pokemon", foreign_key: "pre-evolved_form_id"
belongs_to :pre-evolved_form, class_name: "Pokemon", optional: true
has_many :pre-evolved_forms, class_name: "Pokemon", foreign_key: "evolved_form_id"
belongs_to :evolved_form, class_name: "Pokemon", optional: true
end
这似乎是可行的,但我觉得好像缺少了一些东西,好像应该有某种有很多通过关联。如果有人有更好的建模,我将不胜感激。谢谢。
我会说你走在正确的道路上,但还不完全正确。
对您的 objective 有用的是树结构(a.k.a。层次结构)。因此,口袋妖怪将具有许多进化形式,并且只有一种它所属的预进化形式(或相反)。仅基于这一关系,整个逻辑就可以工作,您可以访问任何单个口袋妖怪的所有进化形式和所有进化前形式。
class Pokemon < ApplicationRecord
belongs_to :pre_evolved_form, class_name: 'Pokemon', foreign_key: 'pre_evolved_form_id', optional: true
end
通过自己实现,您将需要编写辅助方法来访问进化形式(后代对象)和预进化形式(上升对象)。
不过,我建议您查看一个名为 ancestry
的 gem,这应该会让事情变得更容易一些。他们的自述文件看起来写得很好,所以我不会试图比他们更好地解释它。
同时查看分层对象结构。
可能有更好的东西,但我会像下面那样(嵌套地)做。它也适用于 Eevie 和其他可以有多个进化线的口袋妖怪。
class Pokemon < ApplicationRecord
belongs_to :previous_evolved_form, class_name: 'Pokemon', optional: true
has_many :next_evolved_forms, class_name: 'Pokeomn', foreign_key: :previous_evolved_form_id
def ancestor_evolved_forms
forms = {}
if previous_evolved_form.present?
forms[previous_evolved_form] = previous_evolved_form.ancestor_evolved_forms
end
end
def descendant_evolved_forms
forms = {}
next_evolved_forms.each do |next_evolved_form|
forms[next_evolved_form] = next_evolved_form.descendant_evolved_forms
end
end
end
用法示例
oddish = Pokemon.find(1)
# => <Pokemon id: 1, name: "Oddish">
oddish.next_evolved_forms
# => [ <Pokemon id: 2, name: "Gloom"> ]
gloom = oddish.next_evolved_forms.first
# => <Pokemon id: 2, name: "Gloom">
gloom.next_evolved_forms
# => [ <Pokemon id: 3, name: "Vileplume">, <Pokemon id: 4, name: "Bellossom"> ]
vileplume = gloom.next_evolved_forms.first
# => <Pokemon id: 3, name: "Vileplume">
bellossom = gloom.next_evolved_forms.second
# => <Pokemon id: 4, name: "Bellossom">
# testing the nested methods:
oddish.ancestor_evolved_forms
=begin
{}
=end
oddish.descendant_evolved_forms
=begin
{
<Pokemon id: 2, name: "Gloom"> => {
<Pokemon id: 3, name: "Vileplume"> => {},
<Pokemon id: 4, name: "Bellossom"> => {}
}
}
=end
gloom.ancestor_evolved_forms
=begin
{
<Pokemon id: 1, name: "Oddish"> => {}
}
=end
gloom.descendant_evolved_forms
=begin
{
<Pokemon id: 3, name: "Vileplume"> => {},
<Pokemon id: 4, name: "Bellossom"> => {}
}
=end
vileplume.ancestor_evolved_forms
=begin
{
<Pokemon id: 2, name: "Gloom"> => {
<Pokemon id: 1, name: "Oddish"> => {}
}
}
=end
vileplume.descendant_evolved_forms
=begin
{}
=end
bellossom.ancestor_evolved_forms
=begin
{
<Pokemon id: 2, name: "Gloom"> => {
<Pokemon id: 1, name: "Oddish"> => {}
}
}
=end
bellossom.descendant_evolved_forms
=begin
{}
=end
待办事项:
如果“进化”以某种方式循环回到起点(这永远不会发生),请向口袋妖怪添加模型验证以防止“StackLevel 错误”。
尽可能避免重新发明轮子总是好的。
您可能会在祖先 gem 中找到一些好处,它用于将模型组织成树结构,这正是您的目标。
我正在努力研究口袋妖怪与其进化之间的正确关联。我认为我接近正确答案,但我在尝试对此建模以完成时遇到问题。这是我努力实现的目标。
bulbasaur = Pokemon.find(1)
bulbasaur.evolved_forms ---> [ivysaur, venasaur]
ivysaur = Pokemon.find(2)
ivysaur.evolved_forms ----> [venusaur]
ivysaur.pre-evolved_forms ---> [bulbasaur]
venusaur = Pokemon.find(3)
venusaur.evolved_forms ----> []
venusaur.pre-evolved_forms ---> [ivysaur, bulbasaur]
我有以下型号。
class Pokemon < ApplicationRecord
has_many :evolved_forms, class_name: "Pokemon", foreign_key: "pre-evolved_form_id"
belongs_to :pre-evolved_form, class_name: "Pokemon", optional: true
has_many :pre-evolved_forms, class_name: "Pokemon", foreign_key: "evolved_form_id"
belongs_to :evolved_form, class_name: "Pokemon", optional: true
end
这似乎是可行的,但我觉得好像缺少了一些东西,好像应该有某种有很多通过关联。如果有人有更好的建模,我将不胜感激。谢谢。
我会说你走在正确的道路上,但还不完全正确。 对您的 objective 有用的是树结构(a.k.a。层次结构)。因此,口袋妖怪将具有许多进化形式,并且只有一种它所属的预进化形式(或相反)。仅基于这一关系,整个逻辑就可以工作,您可以访问任何单个口袋妖怪的所有进化形式和所有进化前形式。
class Pokemon < ApplicationRecord
belongs_to :pre_evolved_form, class_name: 'Pokemon', foreign_key: 'pre_evolved_form_id', optional: true
end
通过自己实现,您将需要编写辅助方法来访问进化形式(后代对象)和预进化形式(上升对象)。
不过,我建议您查看一个名为 ancestry
的 gem,这应该会让事情变得更容易一些。他们的自述文件看起来写得很好,所以我不会试图比他们更好地解释它。
同时查看分层对象结构。
可能有更好的东西,但我会像下面那样(嵌套地)做。它也适用于 Eevie 和其他可以有多个进化线的口袋妖怪。
class Pokemon < ApplicationRecord
belongs_to :previous_evolved_form, class_name: 'Pokemon', optional: true
has_many :next_evolved_forms, class_name: 'Pokeomn', foreign_key: :previous_evolved_form_id
def ancestor_evolved_forms
forms = {}
if previous_evolved_form.present?
forms[previous_evolved_form] = previous_evolved_form.ancestor_evolved_forms
end
end
def descendant_evolved_forms
forms = {}
next_evolved_forms.each do |next_evolved_form|
forms[next_evolved_form] = next_evolved_form.descendant_evolved_forms
end
end
end
用法示例
oddish = Pokemon.find(1)
# => <Pokemon id: 1, name: "Oddish">
oddish.next_evolved_forms
# => [ <Pokemon id: 2, name: "Gloom"> ]
gloom = oddish.next_evolved_forms.first
# => <Pokemon id: 2, name: "Gloom">
gloom.next_evolved_forms
# => [ <Pokemon id: 3, name: "Vileplume">, <Pokemon id: 4, name: "Bellossom"> ]
vileplume = gloom.next_evolved_forms.first
# => <Pokemon id: 3, name: "Vileplume">
bellossom = gloom.next_evolved_forms.second
# => <Pokemon id: 4, name: "Bellossom">
# testing the nested methods:
oddish.ancestor_evolved_forms
=begin
{}
=end
oddish.descendant_evolved_forms
=begin
{
<Pokemon id: 2, name: "Gloom"> => {
<Pokemon id: 3, name: "Vileplume"> => {},
<Pokemon id: 4, name: "Bellossom"> => {}
}
}
=end
gloom.ancestor_evolved_forms
=begin
{
<Pokemon id: 1, name: "Oddish"> => {}
}
=end
gloom.descendant_evolved_forms
=begin
{
<Pokemon id: 3, name: "Vileplume"> => {},
<Pokemon id: 4, name: "Bellossom"> => {}
}
=end
vileplume.ancestor_evolved_forms
=begin
{
<Pokemon id: 2, name: "Gloom"> => {
<Pokemon id: 1, name: "Oddish"> => {}
}
}
=end
vileplume.descendant_evolved_forms
=begin
{}
=end
bellossom.ancestor_evolved_forms
=begin
{
<Pokemon id: 2, name: "Gloom"> => {
<Pokemon id: 1, name: "Oddish"> => {}
}
}
=end
bellossom.descendant_evolved_forms
=begin
{}
=end
待办事项:
如果“进化”以某种方式循环回到起点(这永远不会发生),请向口袋妖怪添加模型验证以防止“StackLevel 错误”。
尽可能避免重新发明轮子总是好的。
您可能会在祖先 gem 中找到一些好处,它用于将模型组织成树结构,这正是您的目标。