has_many: через, самореферентную ассоциацию
-
20-09-2019 - |
Вопрос
У меня проблемы с самореферентной ассоциацией, модели должны предоставить массив моделей для методов left_chunks и right_chunks, но я каждый раз получаю пустой массив.
Источник
class Chunk < ActiveRecord::Base
has_many :left_bindings, :foreign_key => "left_chunk_id",
:class_name => "ChunkChunk",
:dependent => :destroy
has_many :right_chunks, :through => :left_bindings
has_many :right_bindings, :foreign_key => "right_chunk_id",
:class_name => "ChunkChunk",
:dependent => :destroy
has_many :left_chunks, :through => :right_bindings
end
class ChunkChunk < ActiveRecord::Base
belongs_to :left_chunk, :class_name => "Chunk", :foreign_key => "left_chunk_id"
belongs_to :right_chunk, :class_name => "Chunk", :foreign_key => "right_chunk_id"
end
Вывод из ./script/console
>> #first case
?>
?> left = Chunk.new({:content => "chunk_one"}); left.save
=> true
>> right = Chunk.new({:content => "chunk_two"}); right.save
=> true
>> left.right_chunks << right
=> []
>> left.right_chunks
=> []
>> left.left_chunks
=> []
>>
?> #second case
?>
?> left = Chunk.new({:content => "chunk_three"}); left.save
=> true
>> right = Chunk.new({:content => "chunk_four"}); right.save
=> true
>> right.left_chunks << left
=> []
>> right.left_chunks
=> []
>> right.right_chunks
=> []
Почему куски не связаны между собой?
База данных после выполнения кода
mysql> select * from chunks;
+----+-------------+---------------------+---------------------+
| id | content | created_at | updated_at |
+----+-------------+---------------------+---------------------+
| 1 | chunk_one | 2010-02-14 12:11:22 | 2010-02-14 12:11:22 |
| 2 | chunk_two | 2010-02-14 12:11:22 | 2010-02-14 12:11:22 |
| 3 | chunk_three | 2010-02-14 12:11:22 | 2010-02-14 12:11:22 |
| 4 | chunk_four | 2010-02-14 12:11:22 | 2010-02-14 12:11:22 |
+----+-------------+---------------------+---------------------+
mysql> select * from chunk_chunks;
+----+---------------+----------------+---------------------+---------------------+
| id | left_chunk_id | right_chunk_id | created_at | updated_at |
+----+---------------+----------------+---------------------+---------------------+
| 1 | NULL | 2 | 2010-02-14 12:11:22 | 2010-02-14 12:11:22 |
| 2 | 3 | NULL | 2010-02-14 12:11:22 | 2010-02-14 12:11:22 |
+----+---------------+----------------+---------------------+---------------------+
Есть идеи ?
Решение
Вы не говорите, какую версию MySQL, Ruby или Rails вы используете.Я только что попробовал это с небольшим тестовым приложением, и оно сработало правильно.Я использую PostgreSQL 8.4.1 в OS X 10.6.Я только что создал пустое приложение на Rails 2.3.5/Ruby 1.8.7 (уровень исправления 174 12 июня 2009 г.) с "rails testapp", затем добавил две модели в chunk.rb:
class Chunk < ActiveRecord::Base
has_many :left_bindings, :foreign_key => "left_chunk_id",
:class_name => "ChunkChunk",
:dependent => :destroy
has_many :right_chunks, :through => :left_bindings
has_many :right_bindings, :foreign_key => "right_chunk_id",
:class_name => "ChunkChunk",
:dependent => :destroy
has_many :left_chunks, :through => :right_bindings
end
... и chunk_chunks.rb:
class ChunkChunk < ActiveRecord::Base
belongs_to :left_chunk, :class_name => "Chunk", :foreign_key => "left_chunk_id"
belongs_to :right_chunk, :class_name => "Chunk", :foreign_key => "right_chunk_id"
end
... плюс две миграции для добавления таблиц без временных меток для краткости:
class AddChunks < ActiveRecord::Migration
def self.up
create_table 'chunks' do | t |
t.string :content
end
end
def self.down
drop_table 'chunk'
end
end
...и:
class AddChunkChunks < ActiveRecord::Migration
def self.up
create_table 'chunk_chunks' do | t |
t.belongs_to :left_chunk
t.belongs_to :right_chunk
end
end
def self.down
end
end
Затем я запустил «rake db:create», «rake db:migrate», и ваши консольные команды сработали для меня следующим образом:
PondPro:testapp adh1003$ script/console
Loading development environment (Rails 2.3.5)
>> left = Chunk.new({:content => "chunk_one"}); left.save
=> true
>> right = Chunk.new({:content => "chunk_two"}); right.save
=> true
>> left.right_chunks << right
=> [#<Chunk id: 2, content: "chunk_two">]
>> left.right_chunks
=> [#<Chunk id: 2, content: "chunk_two">]
>> left.left_chunks
=> []
>> left = Chunk.new({:content => "chunk_three"}); left.save
=> true
>> right = Chunk.new({:content => "chunk_four"}); right.save
=> true
>> right.left_chunks << left
=> [#<Chunk id: 3, content: "chunk_three">]
>> right.left_chunks
=> [#<Chunk id: 3, content: "chunk_three">]
>> right.right_chunks
=> []
Содержимое базы данных после вышеизложенного было:
chunk-devel=# SELECT * FROM chunks;
id | content
----+-------------
1 | chunk_one
2 | chunk_two
3 | chunk_three
4 | chunk_four
(4 rows)
chunk-devel=# SELECT * FROM chunk_chunks;
id | left_chunk_id | right_chunk_id
----+---------------+----------------
1 | 1 | 2
2 | 3 | 4
(2 rows)
Учитывая это:
...и это:
...Я не вижу ничего плохого в вашем исходном коде.Возможно, миграции не такие, как вы ожидаете, возможно, есть другие части вашего кода, которые вы не опубликовали и которые мешают (например,фильтры, другие драгоценные камни) или, возможно, адаптер базы данных ActiveRecord для MySQL в этом случае не делает правильных действий и/или MySQL не работает должным образом.Устанавливать PostgreSQL и использовать его вместо MySQL для дальнейших тестов немного затруднительно, но я думаю, что это того стоит.
На всякий случай я загрузил сюда данные тестового приложения:
Если вы обнаружите, что пошло не так, и сможете это исправить, пожалуйста, напишите здесь продолжение.Это будет полезно, если кто-нибудь столкнется с подобной проблемой в будущем и прочитает эту ветку в поисках решения.
Другие советы
Это проблема .reload?После того, как вы сделаете это в консоли:
right.left_chunks << left
делать
right.reload
тогда попробуй
right.left_chunks
.