has_many :through 、自己参照関連付け
-
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 のどのバージョンを使用しているかは明らかにしません。小さなテスト アプリケーションでこれを試してみたところ、正しく動作しました。OS X 10.6 で PostgreSQL 8.4.1 を使用しています。Rails 2.3.5 / Ruby 1.8.7 (2009-06-12 patchlevel 174) で「rails testapp」を使用して空のアプリを作成し、chunk.rb に 2 つのモデルを追加しました。
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
...さらにテーブルを追加するための 2 つの移行 (簡潔にするためにタイムスタンプは省略):
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:merge」を実行すると、コンソール コマンドが次のように機能しました。
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)
これを考慮すると:
...この:
...元のコードには特に問題があるようには見えません。おそらく、移行が期待どおりではない可能性があります。おそらく、投稿していないコードの他の部分が干渉している可能性があります (例:フィルター、その他の gem)、あるいはこの場合、MySQL 用の ActiveRecord データベース アダプターが適切に動作していないか、MySQL が適切に実行されていない可能性があります。PostgreSQL をインストールし、その後のテストに MySQL の代わりにそれを使用するのは少し時間がかかりますが、価値があると思います。
少しでも役立つことが判明した場合に備えて、テスト アプリケーション データをここにアップロードしました。
何が問題だったのかを見つけて修正できた場合は、ここにフォローアップを投稿してください。これは、誰かが今後同様の問題に遭遇し、解決策を探しているときにこのスレッドを読んだ場合に役立ちます。
他のヒント
これは.reloadの問題ですか?コンソールでこれを実行した後:
right.left_chunks << left
DO
right.reload
その後、試してください。
right.left_chunks
ます。