Создание has_many: через записи 2 раза - PullRequest
4 голосов
/ 18 мая 2010

У меня есть модели

class Question < ActiveRecord::Base
  WEIGHTS = %w(medium hard easy)

  belongs_to :test
  has_many :answers, :dependent => :destroy
  has_many :testing_questions
end

class Testing < ActiveRecord::Base
  belongs_to :student, :foreign_key => 'user_id'
  belongs_to :subtest
  has_many :testing_questions, :dependent => :destroy
  has_many :questions, :through => :testing_questions
end

Итак, когда я пытаюсь связать вопросы с тестированием по его созданию:

>> questions = Question.all
...
>> questions.count
=> 3
>> testing = Testing.create(:user_id => 3, :subtest_id => 1, :questions => questions)
  Testing Columns (0.9ms)   SHOW FIELDS FROM `testings`                              
  SQL (0.1ms)   BEGIN                                                                
  SQL (0.1ms)   COMMIT                                                               
  SQL (0.1ms)   BEGIN                                                                
  Testing Create (0.3ms)   INSERT INTO `testings` (`created_at`, `updated_at`, `user_id`, `subtest_id`) VALUES('2010-05-18 00:53:05', '2010-05-18 00:53:05', 3, 1)                                                                                                                                                        
  TestingQuestion Columns (0.9ms)   SHOW FIELDS FROM `testing_questions`                                                                                     
  TestingQuestion Create (0.3ms)   INSERT INTO `testing_questions` (`question_id`, `created_at`, `updated_at`, `testing_id`) VALUES(1, '2010-05-18 00:53:05', '2010-05-18 00:53:05', 31)                                                                                                                                  
  TestingQuestion Create (0.4ms)   INSERT INTO `testing_questions` (`question_id`, `created_at`, `updated_at`, `testing_id`) VALUES(2, '2010-05-18 00:53:05', '2010-05-18 00:53:05', 31)                                                                                                                                  
  TestingQuestion Create (0.3ms)   INSERT INTO `testing_questions` (`question_id`, `created_at`, `updated_at`, `testing_id`) VALUES(3, '2010-05-18 00:53:05', '2010-05-18 00:53:05', 31)                                                                                                                                  
  TestingQuestion Create (0.3ms)   INSERT INTO `testing_questions` (`question_id`, `created_at`, `updated_at`, `testing_id`) VALUES(1, '2010-05-18 00:53:05', '2010-05-18 00:53:05', 31)                                                                                                                                  
  TestingQuestion Create (0.3ms)   INSERT INTO `testing_questions` (`question_id`, `created_at`, `updated_at`, `testing_id`) VALUES(2, '2010-05-18 00:53:05', '2010-05-18 00:53:05', 31)                                                                                                                                  
  TestingQuestion Create (0.3ms)   INSERT INTO `testing_questions` (`question_id`, `created_at`, `updated_at`, `testing_id`) VALUES(3, '2010-05-18 00:53:05', '2010-05-18 00:53:05', 31)                                                                                                                                  
  SQL (90.2ms)   COMMIT                                                                                                                                      
=> #<Testing id: 31, subtest_id: 1, user_id: 3, created_at: "2010-05-18 00:53:05", updated_at: "2010-05-18 00:53:05">

Существует 6 запросов SQL и создано 6 записей в testing_questions. Зачем?

Ответы [ 5 ]

2 голосов
/ 18 мая 2010

Я создал очень простой пример, который обрабатывает ваш пример:

class Question < ActiveRecord::Base
  has_many :testing_questions
end

class Testing < ActiveRecord::Base
  has_many :testing_questions
  has_many :questions, :through => :testing_questions
end

class TestingQuestion < ActiveRecord::Base
  belongs_to :question
  belongs_to :testing
end

.. и тогда я могу просто сделать следующее, и дубликаты записей не создаются:

Loading development environment (Rails 2.3.5)
>> q1 = Question.new
=> #<Question id: nil, title: nil, ask: nil, created_at: nil, updated_at: nil>
>> q1.title = "Dit is de eerste vraag"
=> "Dit is de eerste vraag"
>> q2 = Question.new
=> #<Question id: nil, title: nil, ask: nil, created_at: nil, updated_at: nil>
>> q2.title = "Dit is de tweede vraag"
=> "Dit is de tweede vraag"
>> q1.save
=> true
>> q2.save
=> true
>> tt = Testing.new
=> #<Testing id: nil, name: nil, description: nil, action: nil, created_at: nil, updated_at: nil>
>> tt.questions
=> []
>> tt.name = "Test1"
=> "Test1"
>> tt.questions << q1
=> [#<Question id: 1, title: "Dit is de eerste vraag", ask: nil, created_at:   "2010-05-18 19:40:54", updated_at: "2010-05-18 19:40:54">]
>> tt.questions << q2
=> [#<Question id: 1, title: "Dit is de eerste vraag", ask: nil, created_at: "2010-05-18 19:40:54", updated_at: "2010-05-18 19:40:54">, #<Question id: 2, title: "Dit is de tweede vraag", ask: nil, created_at: "2010-05-18 19:40:59", updated_at: "2010-05-18 19:40:59">]
>> tt.testing_questions
=> []
>> tt.save
=> true
>> tt.testing_questions
=> [#<TestingQuestion id: 1, question_id: 1, testing_id: 1, extra_info: nil, created_at: "2010-05-18 19:41:43", updated_at: "2010-05-18 19:41:43">, #<TestingQuestion id: 2, question_id: 2, testing_id: 1, extra_info: nil, created_at: "2010-05-18 19:41:43", updated_at: "2010-05-18 19:41:43">]
>>

На самом деле это полностью то же самое, что и вы, за исключением TestingQuestion (который вы не показывали). Это помогает?

0 голосов
/ 18 сентября 2012

Ваш массив questions содержит 3 элемента. Когда вы создаете экземпляр Testing и указываете, что создаете его с помощью :questions => questions, он добавит их к отношению questions, но поскольку это отношение относится к другому, они должны быть сначала добавлены к другому, в результате в них вставляется дважды. Как правило, у вас есть какая-то другая модель, представляющая таблицу соединения, так что у вас есть 3 записи, вставленные в таблицу вопросов, а также 3 в таблицу соединения TestingQuestions (has_many: through).

Похоже, проблема в том, как вы определили модель TestingQuestions, которую вы не показали. Например, указывает ли она на ту же таблицу, что и модель вопросов?

0 голосов
/ 18 мая 2010

Глядя на структуру таблицы, это отношения has_and_belongs_to_many между таблицами, здесь нет необходимости использовать has_many и опцию through, так как ваша таблица соединения не будет иметь модель (никаких дополнительных столбцов кроме идентификаторов нет). Нет необходимости создавать модель для таблицы соединений.

Итак, я предлагаю изменить ваши модели следующим образом

<code><br>
class Question < ActiveRecord::Base<br>
  WEIGHTS = %w(medium hard easy)
  belongs_to :test<br>
  has_many :answers, :dependent => :destroy<br>
  has_and_belongs_to_many :question_testings 
end</p>

<p>class Testing < ActiveRecord::Base<br>
  belongs_to :student, :foreign_key => 'user_id'
  belongs_to :subtest
  has_and_belongs_to_many :question_testings 
end

и, пожалуйста, измените имя таблицы на вопросо-тесты.

Пожалуйста, нажмите на эту ссылку для получения дополнительной информации http://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many

0 голосов
/ 18 мая 2010

Не глядя на исходный код Rails и не пытаясь его обойти, я бы предложил попробовать либо удалить has_many: testing_questions из класса Question, либо добавить туда has_many ...: Сейчас Rails просто имеет отношение к таблице соединений, но не к «реальной» цели с этой стороны.

Имя таблицы соединения не должно вызывать проблем.

0 голосов
/ 18 мая 2010

Первой проблемой может быть наименование вашей таблицы соединений

testing_questions

Rails ожидает, что имя объединяемой таблицы будет объединением двух имен таблиц в алфавитном порядке

question_testings
...