has_many: par, association d'auto référentiel
-
20-09-2019 - |
Question
J'ai du mal avec l'association d'auto-référentiel, les modèles devraient donner ma un éventail de modèles pour les left_chunks et right_chunks méthodes, mais je reçois à chaque fois un tableau vide
La source
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
Sortie de ./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
=> []
Pourquoi les morceaux pas liés ensemble?
Base de données après l'exécution de code
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 |
+----+---------------+----------------+---------------------+---------------------+
Toutes les idées?
La solution
Vous ne dites pas quelle version de MySQL, Ruby ou Rails vous êtes. Je viens d'essayer cela avec une petite application de test et cela a fonctionné correctement. J'utilise PostgreSQL 8.4.1 sur Mac OS X 10.6. Je viens de créer une application vide on Rails 2.3.5 / Ruby 1.8.7 (2009-06-12 patchlevel 174) avec "rails testapp", puis a ajouté deux modèles 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
... et 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
... ainsi que deux migrations pour ajouter les tables, sans horodatages par souci de concision:
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
... et:
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
J'ai alors couru "rake db: créer", "rake db: migrate" et vos commandes de la console a fonctionné pour moi comme suit:
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
=> []
Le contenu de base de données après ce qui précède sont:
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)
Compte tenu de ceci:
... et ceci:
... Je ne vois vraiment rien de mal avec votre code d'origine. Peut-être que les migrations ne sont pas ce que vous attendez, peut-être il y a d'autres parties de votre code que vous ne l'avez pas affichées qui interfèrent (par exemple, les filtres, les autres pierres précieuses) ou peut-être l'adaptateur de base de données MySQL pour ActiveRecord ne fait pas les bonnes choses dans ce cas et / ou MySQL ne fonctionne pas correctement. Il est un peu longue haleine pour installer PostgreSQL et utiliser à la place de MySQL pour des tests, mais je pense qu'il serait utile.
Juste au cas où il se révèle utile du tout, je l'ai téléchargé les données d'application de test ici:
Si vous trouvez ce qui est mal passé et réussi à le corriger, s'il vous plaît poster un suivi ici. Cela sera utile si quelqu'un rencontre des problèmes similaires à l'avenir et lit ce fil lors de la recherche d'une solution.
Autres conseils
Est-ce un problème de .reload? Une fois que vous faites cela dans la console:
right.left_chunks << left
do
right.reload
essayez
right.left_chunks
.