Rails ORM, может ли он справиться с составным первичным ключом двух внешних ключей, ссылающихся на одну и ту же таблицу? - PullRequest
2 голосов
/ 29 августа 2011

Отредактировано 30-е, 03:16, чтобы показать улучшенную миграцию и модель

У меня есть таблица элементов, каждый из которых может быть связан со многими другими элементами. Возможно ли это сделать в миграциях и моделях Rails? (это реализовано в SQL)

Таблица элементов: имеет поле первичного ключа с целочисленным идентификатором вместе с другими.

Таблица межэлементных связей:

CREATE TABLE inter_element_links
(
  element1_id integer NOT NULL,
  element2_id integer NOT NULL,
  CONSTRAINT inter_element_links_pkey PRIMARY KEY (element1_id, element2_id),
  CONSTRAINT foreign_key_on_id1 FOREIGN KEY (element1_id)
      REFERENCES elements (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT foreign_key_on_id2 FOREIGN KEY (element2_id)
      REFERENCES elements (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

И этот запрос возвращает все элементы, связанные с конкретным элементом по его идентификатору, например, 3:

SELECT *
FROM elements
INNER JOIN inter_element_links ON (elements.id = inter_element_links.element1_id
  OR elements.id = inter_element_links.element2_id)
WHERE (inter_element_links.element1_id = 3 OR inter_element_links.element2_id = 3)
AND elements.id <> 3

Это работает в Postgres, и я хотел бы перевести на Rails, но изо всех сил пытаюсь найти решение для Rails ... это то, что я делаю глупо, или это просто не так часто?

Пока у меня есть миграция (, у которой есть поддельный составной первичный ключ и нет внешних ключей, ссылающихся на elements.id):

class CreateInterElementLinks < ActiveRecord::Migration
  def self.up
    create_table :inter_element_links, :id => false do |t|
      t.integer :element1_id, :null => false
      t.integer :element2_id, :null => false
    end
    add_index :inter_element_links, [:element1_id, :element2_id], :unique => true
  end

  def self.down
    remove_index :inter_element_links, [:element1_id, :element2_id]
    drop_table :inter_element_links
  end
end

И имеют следующие модели:

class Element < ActiveRecord::Base
  belongs_to :user
  has_many :inter_element_links1, :foreign_key => 'element1_id', :class_name => 'InterElementLink', :dependent => :destroy
  has_many :inter_element_links2, :foreign_key => 'element2_id', :class_name => 'InterElementLink', :dependent => :destroy
  has_many :elements1, :through => :inter_element_links1
  has_many :elements2, :through => :inter_element_links2

  def inter_element_links  ## Unless there's a more elegant rails solution, I will try to extend ActiveRecord::HasManyThroughAssociation, so things like:  an_element.destroy, will destroy the entry in the inter_element_links table, and calls to an_element.elements will work.
    inter_element_links1 + inter_element_links2
  end

  def elements
    elements1 + elements2
  end
end

class InterElementLink < ActiveRecord::Base
  set_primary_keys :element1_id, :element2_id   ## I have included the 'composite_primary_keys', '=3.1.0' gem
  belongs_to :element
end

Любые мысли приветствуются!


За последние 24 часа я нашел несколько вещей, которые, кажется, близки, но еще не дошли до меня:

Большое спасибо!

...