2011-10-28 5 views
2

純粋なルビースクリプトにあるナビゲーションレールのオブジェクトのレール動作を実装する良い方法を見つけることができません。Rubyでそれらの間のオブジェクトを接続するベストプラクティス

私はクラスChildのオブジェクトの配列へのアクセサーを使ってParentクラスのオブジェクトを持っていますが、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 

私が興味を持っている部分は、もちろん、その子の1つから「親」オブジェクトを取得しようとする最後の行です。

どうすれば簡単かつきれいに実装できますか?

子オブジェクトにアクセサを追加しようとしていましたが、子オブジェクトを親オブジェクトに添付するたびにこの値が設定されていることを確認する方法がわかりません。

ルビーで簡単かつクリーンな方法がありますか?

ありがとうございます。

答えて

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 

と親に子を追加するには、いくつかのコード例:あなたがremoveeachのようないくつかの他の有用な方法でスローすることをお勧めします

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}" 

(あなたがChildCollectionEnumerableモジュールを含めることができますし、それに伴うすべてのクールなものを手に入れてください)しかし、これはあなたを始めさせるのに十分であるはずです。

+0

'Parent'クラスでは、コンテナに適切な親オブジェクトへの参照が含まれていることを確認する必要があるため、' attr_accessor'ではなく 'attr_reader:children'を使用しました。私たちはまだコレクションに子供を追加したり、コレクションから子どもを削除することは自由です。 –

+0

ああ、それは私が探していたようだ。私はプロジェクトで月曜日にそれを実装しようとします。ありがとう、イアン。 – Baramin

1

配列に追加された各子に親属性を設定したクラスParentの子オブジェクトのアクセサを作成します。アレイから子を削除するときは逆の操作を行います。これが私のやり方です。

+0

[OK]をクリックします。私はそれを実際に行うことができる、add_childとdelete_childを親オブジェクトに追加する。 これを今のところこの方法で実装していきます。他に誰もより良い解決策がない場合は、あなたの答えを検証します。 new_child = parent.children.new()のようなものを許可する方法が好きです。 – Baramin

+0

これも可能です。配列からクラスを派生し、メソッドnew_child()を実装します。このメソッドは、 'parent'プロパティを設定し、その後に' self << new_child'を呼び出します。 – ckruse

2

あなたが知っている限り、あなたのデータへのアクセスを完全に制御することに何も問題はありません。

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 
+0

ckruseさんの答えがうまくアップグレードされましたが、私が探していたものよりもIanが好きです。 あなたの助けをたくさんありがとう、mu(あまりにも短いです)、hehe、私はあなたの名前が好きです。 – Baramin

+0

@Baramin:いくつかの選択肢があることを心配する必要はありません。 –

関連する問題