модель рельсов has_many сама по себе

У меня есть событийная модель. События могут иметь родительские события, установленные из столбца в модели (parent_event_id). Мне нужно сделать has_many :event на модели, поэтому я могу просто сделать, например, event.child_event или event.parent_event. Но мое гугление не сработало так хорошо.

Моя модель:

class Event < ActiveRecord::Base
    attr_accessible :days_before, :event_name, :event_date, :list_id, :recipient_email, :recipient_name, :parent_event_id, :is_deleted, :user_id

    belongs_to :user
    has_many :event_email
    has_many :event
end

Моя схема:

create_table "events", :force => true do |t|
    t.datetime "event_date"
    t.integer  "days_before"
    t.string   "recipient_email"
    t.integer  "list_id"
    t.string   "recipient_name"
    t.datetime "created_at",                         :null => false
    t.datetime "updated_at",                         :null => false
    t.integer  "user_id"
    t.string   "event_name"
    t.integer  "parent_event_id"
    t.boolean  "is_deleted",      :default => false
end

person Alexander Forbes-Reed    schedule 13.09.2013    source источник


Ответы (6)


Это самореферентная модель, вы можете попробовать что-то вроде этого:

class Event < ActiveRecord::Base
  belongs_to :parent, :class_name => "Event", :foreign_key => "parent_event_id"
  has_many :child_events, :class_name => "Event", :foreign_key => "child_event_id"
end

Таким образом, вы можете вызвать @event.parent, чтобы получить объект Event ActiveRecord, и @event.child_events, чтобы получить коллекцию ActiveRecord объектов Event.

person derekyau    schedule 13.09.2013
comment
нам нужно foreign_key и в belongs_to и в has_many ? - person r3b00t; 12.07.2017
comment
Можем ли мы использовать accepts_nested_attributes_for :child_events, allow_destroy: true? - person Tashi Dendup; 22.02.2020
comment
Это решение устанавливает родительский идентификатор в поле child_event_id. Это работает, как и ожидалось, если я использую parent_event_id в качестве внешнего ключа для обоих отношений. - person Cbas; 24.04.2020

Вы захотите изменить свой has_many на что-то вроде этого:

has_many :parent_events, class_name: 'Event'
has_many :child_events, ->(event) { where parent_event_id: event.id }, class_name: 'Event'

Это из документации по рельсам 4 по ссылке: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

В частности, раздел «Настройка запроса». Это должно позволить вам делать то, что вы ищете. Не пробовал это локально, но это похоже на то, что мне пришлось сделать, чтобы реализовать приложение для игры в футбол, которое я сделал некоторое время назад.

Надеюсь это поможет.

person Mike Waldrup    schedule 13.09.2013

Попробуйте Шаблон вложенного набора

Для этого: отличный вложенный набор

person Oleg Haidul    schedule 13.09.2013

В Rails уже есть гем для предоставления вложенной древовидной структуры ancestry. Лучше всего будет в таких сценариях:

https://github.com/stefankroes/ancestry

Вы сможете получить доступ к следующим методам:

event.parent
event.children
event.siblings
person Aman Garg    schedule 13.09.2013

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

class Event < ActiveRecord::Base
  belongs_to :parent, :class_name => "Event", :foreign_key => "parent_event_id", optional: true
  has_many :child_events, :class_name => "Event", :foreign_key => "parent_event_id"
end
person Phil    schedule 18.11.2017

Я не уверен, что это ново для Rails 6, но Руководство Rails по ассоциациям Active Record есть раздел о самообъединениях, предлагающий более аккуратное решение:

class Event < ApplicationRecord
  has_many :children, class_name: "Event", foreign_key: "parent_id"
 
  belongs_to :parent, class_name: "Event", optional: true
end

Обратите внимание, что только дочерние события нуждаются в parent_id. Необязательный необязательный параметр в ассоциации exists_to позволяет вам сохранять ваши модели, так как в Rails 5 обязательный параметр own_to.

person klovae    schedule 20.08.2020