2016-10-24 3 views
0

私は2つのモデル分類と分類の関係を持っています。私は各分類が多くのサブクラスを持つことができるようにsupperclassとsubclassを使用して分類の階層を作成したいが、ただ1つのスーパークラスしか持たない。Rails Associations:2番目のモデルを使って自己

私の移行は、私が

class ClassificationRelationship < ApplicationRecord 
    belongs_to :superclass, :class_name => "Classification" 
    belongs_to :subclass, :class_name => "Classification" 
end 

class Classification < ApplicationRecord 
    has_many :classification_relationships 
    has_many :subclasses, through => :classification_relationships 
    has_one :superclass, through => :classification_relationships 
end 

を持って私のモデルではこれまでのところ、この

class CreateClassifications < ActiveRecord::Migration[5.0] 
    def change 
    create_table :classifications do |t| 
     t.string :symbol 
     t.string :title 
     t.integer :level 

     t.timestamps 
    end 
    add_index :classifications, :symbol 
    add_index :classifications, :level 
    end 
end 

class CreateClassificationRelationships < ActiveRecord::Migration[5.0] 
    def change 
    create_table :classification_relationships do |t| 
     t.integer :superclass_id 
     t.integer :subclass_id 

     t.timestamps 
    end 
    add_index :classification_relationships, :superclass_id 
    add_index :classification_relationships, :subclass_id 
    add_index :classification_relationships, [:superclass_id, :subclass_id], unique: true, name: 'unique_relationship' 
    end 
end 

のように見える私はかなりの数の他の記事を読んで、まだ関連付けを終えることが方法がわからないと思います。私は外来キーを指定する必要があるとはかなり確信していますが、どうやってそれを行うべきかについては明確ではありません。助けてくれてありがとう!

答えて

1

ClassificationRelationshipを取り除く。
Classificationにはparent_idが必要です。ルートインスタンスではnullにすることができます。

追加:

belongs_to :parent, class_name: 'Classification', foreign_key: :parent_id 
def children 
    Classification.where(:parent_id => self.id) 
end 

を一部の操作が最適ではないでしょう。例えばすべての子孫を見つける。これは、子供や子供などを見つけるために繰り返しクエリが必要となるためです。
これはあなたにとって問題ではないかもしれません。
もしそうであれば、私のようなpathを格納お勧めします。

after_create :set_path 
def set_path 
    path = parent ? "#{parent.path}#{self.id}/" : "#{self.id}/" 
    self.update_attributes!(:path => path) 
end 

次にあなたがのようなものを行うことができます。もちろん

def descendants 
    Classification.where("classifications.path LIKE '#{self.path}%' AND classifications.path <> '#{self.path}'") 
end 

は、あなたがクエリを実行することがあります場合は、パスがインデックス付きであることを確認してくださいそうですね。

+0

最初はこのようなことを考えましたが、クエリはそれらの間の第2の関係モデルにより自然なものになると思いました。思考? – mkrinblk

+0

データベーステーブルを少なくして、求めていたことを正確に得る方法を提供しました。モデルはデータベースによって強制されます。結合表は多対多の関係のためのものです。おそらくコード例を使って説明すれば、「もっと自然な」ということを意味しているのですが、私は再考することができます。 – z5h

+0

私はレールガイドの一部を誤って読んでいたと思う。これはひどくうまくいくでしょう。セルフ・ジョイン・アソシエーションについての私のことを明確にするのに役立つ[railsguides]セクション(http://edgeguides.rubyonrails.org/association_basics.html#the-has-manythroughthrough-association)があります(2.10参照) 。加えて、has_manyという関連付けを追加していますが、childrenメソッドの代わりになると思います。 – mkrinblk

関連する問題