2016-10-24 6 views
0

У меня есть две модели Классификация и классификацияRelationships. Я хочу создать иерархию классификаций с использованием суперкласса и подкласса, чтобы каждая классификация могла иметь много подклассов, но только один суперкласс.Rails Ассоциации: с автомоделью через вторую модель

моих Миграций выглядеть следующим образом

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 

до сих пор с моей моделью у меня есть

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 

я прочитал довольно много других должностей, но я до сих пор не знает, как закончить ассоциации. Я уверен, что мне нужно указать внешние ключи, но я не понимаю, как это сделать. Спасибо за помощь!

ответ

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

Первоначально я думал о чем-то подобном, но я думал, что вопросы будут более естественными со второй моделью отношений между ними. Мысли? – mkrinblk

+0

Я предложил способ получить именно то, что вы просили, с меньшими таблицами базы данных. Модель используется базой данных. Таблица соединений предназначена для отношений «многие-ко-многим». Если вы объясните, возможно, с примерами кода, что означает «более естественный», то я могу пересмотреть. – z5h

+0

Я думаю, что я просто неправильно читал некоторые из рельсов. Это будет деформировать работу. Существует раздел [railsguides] (http://edgeguides.rubyonrails.org/association_basics.html#the-has-many-through-association), который помог мне разобраться в ассоциациях объединения (2.10 для справки) , Кроме того, хотя они добавляют ассоциацию has_many, которая, я думаю, может заменить метод children. – mkrinblk

Смежные вопросы