Отредактировано 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 часа я нашел несколько вещей, которые, кажется, близки, но еще не дошли до меня:
- Подобная проблема обсуждалась здесь , но я не смог отследить предложенный плагин, и он не помогает в части миграции.
- Я использовал этот плагин , чтобы успешно получить первичный ключ имитации Rails на InterElementLink, так что если есть один, где element1_id = 3 и element2_id = 5, вызов InterElementLink.find (3,5) работает, но, очевидно, InterElementLink.find (5,3) не работает ... и I / ActiveRecord понадобится.
- Я понимаю, что ORM, включая ActiveRecord, не поддерживают внешние ключи, см. Хорошее обсуждение этого (, хотя я понимаю, что вы можете использовать этот плагин в ). Я попытался сделать первичный ключ , но это не удалось.
Большое спасибо!