3

基本的に、次の構造が必要です。

class Group < ActiveRecord::Base

end

class Person < ActiveRecord::Base

end

Group_1 (parent)
  Group_2 (child)
    Person_1 (grandchild)
    Person_2 (grandchild)
  Person_3 (child)
  Group_3 (child)
    Person_4 (grandchild)
    Group_4 (grandchild)
      Person_5 (great grandchild)

私は次のgemを試して調査を行いました:acts_as_tree、ancestry、nested_sets、closure_tree。

彼らは私が持っている挑戦の半分である木を保つことができます。ただし、子が同じモデルであることを常に期待しているため、ツリー構造に別のモデルを追加することはできません。[例:ActiveRecord :: AssociationTypeMismatch:Group(#2179078840)が期待され、closure_tree gemからPerson(#2171128160)を取得しました]

とにかく、ツリー内の2つの異なるモデルで機能するように、上記で定義された構造を持つことは可能ですか?

4

6 に答える 6

0

ツリーに付属する機能が必要ですか。そうでなければ、あなたは簡単なことをすることができます...

各オブジェクトにgroup_idを配置します。nil group_idは、ルートに属していることを意味します。

class Group < ActiveRecord::Base
  belongs_to :group  # The parent

  has_many :groups
  has_many :people
end

class Person < ActiveRecord::Base
  belongs_to :group

end
于 2012-10-17T23:51:09.113 に答える
0

「ツリー ノード」に使用されるモデルを定義できます。各ノードは、それが葉であるかどうかを示すブール フィールドと、そのノードによって「保持される」グループ/個人を指す別のフィールド (または複数のフィールド) を持つことができます。(グループ/個人を指すために 1 つのフィールドのみを使用する場合は、多態的な関連付けを使用するか、"リーフ」フィールド)。

于 2012-10-17T18:53:53.527 に答える
0

habtmメソッドを使用してこれにアプローチします。ただし、データベース テーブルをどのように設計するかについては注意が必要な場合があります。Railsコードは次のようになります

class Group < ActiveRecord::Base
  has_and_belongs_to_many :people, class: Person
end

class Person < ActiveRecord::Base
  has_and_belongs_to_many :groups
end
于 2012-10-17T21:18:17.277 に答える
0

基本的に、Person は Group から継承する必要があります。グループと個人は同じタイプのものではないため、なぜこの構造が必要なのかわかりません。

共有しようとしている機能について詳しく説明したい場合があります。2 つの非常に異なるオブジェクト間で機能を共有するより「ルビー」な方法は、継承ではなくモジュールを使用することです。

于 2012-10-17T18:57:56.150 に答える
0

完全 に機能していますこれは改善できますが、私はあなたが望むことだけをしました


gem 'ancestry'

group.rb


class Group < ActiveRecord::Base
  attr_accessible :parent_id, :name
  has_many :people
  attr_accessor :relationship
  has_ancestry

  def people_group_children
    (people + children).sort_by(&:created_at)
  end

  RELATIONSHIP = ['parent', 'child', 'grandchild']
  def relationship_by_depth(depth_diff)
    @relationship = RELATIONSHIP[depth_diff] || (depth_diff-2) * 'great ' + RELATIONSHIP[2]
  end

  def arrange_as_desired(ancestor_depth = 0, parent_depth = 0)
    output = '<ul>'.html_safe
    output.safe_concat name + '(' + relationship_by_depth(depth - ancestor_depth) + ')'
    people_group_children.map do |child|
      output.safe_concat '<li>'
      output.safe_concat child.arrange_as_desired(ancestor_depth, depth)
      output.safe_concat '</li>'
    end
    output.safe_concat '</ul>'
    output
  end
end

person.rb


class Person < ActiveRecord::Base
  attr_accessible :group_id, :name
  belongs_to :group
  attr_accessor :relationship, :depth
  def parent; group; end

  def people_group_children; []; end

  RELATIONSHIP = ['parent', 'child', 'grandchild']
  def relationship_by_depth(depth_diff)
    @relationship = RELATIONSHIP[depth_diff] || 'great ' * (depth_diff-2) + RELATIONSHIP[2]
  end

  def arrange_as_desired(ancestor_depth = 0, parent_depth = 0)
    output = '<ul>'.html_safe
    @depth = parent_depth + 1
    output.safe_concat name + "(#{relationship_by_depth(depth - ancestor_depth)})"
    people_group_children.map do |child|
      output.safe_concat '<li>'
      output.safe_concat child.arrange_as_desired(ancestor_depth, depth)
      output.safe_concat '</li>'
    end
    output.safe_concat '</ul>'
    output
  end
end

グループ\show.html.erb


<ul>
  <%= raw @group.arrange_as_desired %>
</ul>


移行

create_groups.rb


class CreateGroups < ActiveRecord::Migration
  def change
    create_table :groups do |t|
      t.string :name
      t.string :ancestry

      t.timestamps
    end
  end
end

create_people.rb


class CreatePeople < ActiveRecord::Migration
  def change
    create_table :people do |t|
      t.integer :group_id
      t.string :name

      t.timestamps
    end
  end
end
于 2013-03-20T09:58:56.827 に答える
0

STI、または単一テーブルの継承を使用するclosure_tree テストの例があります。これは、使用したいもののようです。ただし、STI を読んでください。「グループ」は「グループ」と同じ種類のフィールドや動作を持っているようには見えないため、これは正しい解決策ではない可能性があります。

ただし、そうであると仮定して、モデルに String 型の列を追加する db migration を作成します。テーブルには「ノード」などの一般的な名前を付けます。

class AddTypeToNode < ActiveRecord::Migration
  def change
    add_column :nodes, :type, :string
  end
end

次に、基本クラスとサブクラスを作成します。

class Node < ActiveRecord::Base
  abstract_class = true
  acts_as_tree
end

class Group < Node
end

class Person < Node
end

その後、これを行うことができます:

g1 = Group.create(:name => "Group_1")
g2 = g1.add_child(Group.create(:name => "Group_2"))
p1 = g2.add_child(Person.create(:name => "Person_1"))
p2 = g2.add_child(Person.create(:name => "Person_2"))
…
于 2013-02-26T05:27:02.057 に答える