Есть ли способ гарантировать, что обе стороны ассоциации belongs_to
+ has_many
будут автоматически гидратироваться в соответствии с изменениями, сделанными на другой стороне ассоциации, без перезагрузки другой стороны?
У меня есть реализация самообъединения, к которой принадлежит has_many +, например:
class Activity < ApplicationRecord
belongs_to :combined_activity_parent, class_name: 'Activity',
inverse_of: :combined_activity_children, optional: true
has_many :combined_activity_children, class_name: 'Activity',
inverse_of: :combined_activity_parent, foreign_key: 'combined_activity_parent_id'
end
( См. Полный код модели здесь .)
После настройки inverse_of
на обеих сторонах ассоциации, я ожидал, что, как только я назначу родителя дочернему элементу, этот дочерний элемент автоматически появится на родительской стороне под children
без перезагрузки родительского элемента ,и наоборот.
Однако на практике мне кажется, что мне нужно перезагрузить родительский элемент, чтобы увидеть обратную сторону гидрата ассоциации:
irb(main):006:0> parent = Activity.create(friend: Friend.first, region: Region.first, activity_type: ActivityType.first, occur_at: 1.day.from_now)
=> #<Activity id: 63, event: nil, location_id: nil, friend_id: 1, judge_id: nil, occur_at: "2019-10-11 12:31:01", notes: nil, created_at: "2019-10-10 12:31:01", updated_at: "2019-10-10 12:31:01", region_id: 1, confirmed: nil, public_notes: nil, activity_type_id: 1, combined_activity_parent_id: nil>
irb(main):007:0> child = Activity.create(friend: Friend.first, region: Region.first, activity_type: ActivityType.first, occur_at: parent.occur_at + 1.hour)
=> #<Activity id: 64, event: nil, location_id: nil, friend_id: 1, judge_id: nil, occur_at: "2019-10-11 13:31:01", notes: nil, created_at: "2019-10-10 12:31:45", updated_at: "2019-10-10 12:31:45", region_id: 1, confirmed: nil, public_notes: nil, activity_type_id: 1, combined_activity_parent_id: nil>
irb(main):009:0> child.combined_activity_parent = parent
=> #<Activity id: 63, event: nil, location_id: nil, friend_id: 1, judge_id: nil, occur_at: "2019-10-11 12:31:01", notes: nil, created_at: "2019-10-10 12:31:01", updated_at: "2019-10-10 12:31:01", region_id: 1, confirmed: nil, public_notes: nil, activity_type_id: 1, combined_activity_parent_id: nil>
irb(main):011:0> parent.combined_activity_children
=> #<ActiveRecord::Associations::CollectionProxy []>
irb(main):012:0> child.save!
=> true
irb(main):013:0> parent.combined_activity_children
=> #<ActiveRecord::Associations::CollectionProxy []>
irb(main):014:0> parent.reload
=> #<Activity id: 63, event: nil, location_id: nil, friend_id: 1, judge_id: nil, occur_at: "2019-10-11 12:31:01", notes: nil, created_at: "2019-10-10 12:31:01", updated_at: "2019-10-10 12:31:01", region_id: 1, confirmed: nil, public_notes: nil, activity_type_id: 1, combined_activity_parent_id: nil>
irb(main):015:0> parent.combined_activity_children
=> #<ActiveRecord::Associations::CollectionProxy [#<Activity id: 64, event: nil, location_id: nil, friend_id: 1, judge_id: nil, occur_at: "2019-10-11 13:31:01", notes: nil, created_at: "2019-10-10 12:31:45", updated_at: "2019-10-10 12:32:35", region_id: 1, confirmed: nil, public_notes: nil, activity_type_id: 1, combined_activity_parent_id: 63>]>
Как ни странно, второй тест, приведенный ниже, проходит успешно (belongs_to
автоматически гидратируется в памяти, когда изменяется сторона has_many
), но первый сбой. Это заставляет меня задуматься о том, правильно ли настроена ассоциация.
context 'associations' do
it 'should automatically hydrate the other side of a belongs_to' do
equivalent_time = 1.day.from_now - 1.hour
activity_1 = create(:activity, occur_at: equivalent_time, public_notes: 'parent activity')
activity_2 = create(:activity, occur_at: equivalent_time, public_notes: 'child activity',
combined_activity_parent: activity_1)
expect(activity_1.combined_activity_children.first).to eq activity_2
end
it 'should automatically hydrate the other side of a has_many' do
equivalent_time = 1.day.from_now - 1.hour
activity_1 = create(:activity, occur_at: equivalent_time, public_notes: 'child activity')
activity_2 = create(:activity, occur_at: equivalent_time, public_notes: 'parent activity',
combined_activity_children: [activity_1])
expect(activity_1.combined_activity_parent).to eq activity_2
end
end
(см. Полные тесты здесь .)