我无法找到一种很好的方法来实现导航rails在纯ruby脚本中的对象的rails行为。
假设我有一个类Parent的对象,它具有类Child对象数组的访问器,我操作Child对象时,我可以轻松地获取Parent,如下所示:
class Parent
attr_accessor :children
def initialize
@children = Array.new
end
end
class Child
end
parent = Parent.new
first_child = Child.new
second_child = Child.new
parent.children << [ first_child, second_child ]
a_child = parent.children.first
get_parent_from_child = a.child.parent
我感兴趣的部分当然是我试图获得父母的最后一行&#34;来自其中一个孩子的对象。
我怎样才能轻松,干净地实施?
我正在考虑为子对象添加一个访问器,但我不确定每次将子对象附加到父对象时如何确保设置此值。
在ruby中有一种简单而干净的方法吗?
提前致谢。
答案 0 :(得分:2)
您无需完全公开您所知道的children
,完全控制对您数据的访问权限没有任何问题。
class Parent
def initialize
@children = [ ]
end
# You get a shallow copy of the children, you can
# change the individual children but not the tree
# structure.
def children
@children.dup
end
# We take ownership of the children when you add them.
def add_children(*kids)
kids.each { |k| k.parent = self }
@children += kids
end
def remove_children(&block)
@children.delete_if(&block)
end
end
# This would probably have some sort of payload and
# a sensible "==" implementation.
class Child
attr_reader :parent
def parent=(p)
raise StandardError => 'Not allowed to change parents!' if @parent
@parent = p
end
end
然后child.parent
工作正常,如果你想删除孩子,你会告诉家长要删除哪些:
# Remove the children with even payloads.
parent.remove_children { |c| c.payload % 2 == 0 }
# Remove the children with odd payloads and copy them.
odds = [ ]
parent.remove_children do |c|
kill_it = c.payload % 2 != 0
odds << Child.new(c.payload) if(kill_it)
kill_it
end
答案 1 :(得分:1)
为类中的子项编写一个自己的访问器Parent,在其中为添加到数组的每个子项设置父属性。从阵列中删除子项时,请执行相反的操作。我就是这样做的。
答案 2 :(得分:1)
您可以使用自定义容器类从Rails实现has_many
行为,就像Rails一样。
class Parent
attr_reader :children
def initialize
@children = ChildCollection.new(self)
end
end
class Child
attr_accessor :parent
end
class ChildCollection
def initialize parent
@children = []
@parent = parent
end
def new
child = Child.new
child.parent = @parent
@children << child
child
end
def << child
child.parent = @parent
@children << child
self
end
end
一些将子项添加到父项的示例代码:
parent = Parent.new
child1 = parent.children.new
child2 = Child.new
child3 = Child.new
parent.children << child2 << child3
puts "Parent is: #{parent.object_id}"
puts "Child1's parent is: #{child1.parent.object_id}"
puts "Child2's parent is: #{child2.parent.object_id}"
puts "Child3's parent is: #{child3.parent.object_id}"
您可能想要使用其他一些有用的方法,例如remove
和each
(这样您就可以ChildCollection
包含Enumerable
模块并获取所有很酷的内容随之而来)但这应该足以让你开始。