开发者

Creating has_many :through records 2x times

I have models

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

So when I try to bind questions to testing on it's creation:

>> 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">

There are 6 SQL queries and 6 records in testing_questions are created. Why?


I have created a very simple example that handles your example:

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

.. and then i can just do the following, and no duplicate records are created:

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">]
>>

Actually that is completely the same as you have, except for the TestingQuestion (which you didn't show). Does that help?


A first issue could be the naming of your join table

testing_questions

Rails expects the join table’s name to be a concatenation of the two table names in alphabetical order

question_testings


Looking at the table structure it is a has_and_belongs_to_many relations between the tables, there is no need to use has_many and through option here as your join table will not be having a model( no extra columns other than ids are present). No need to create a model for join table.

So, I suggest to change your models like this


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

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

and please change your table name as question_testings.

Please have a look at this link for more info http://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many


Without looking at the Rails source or trying around, I'd suggest to try either removing the "has_many :testing_questions" from the Question class or add a has_many ... :through there. Just now Rails just has a relation to the join table, but not to the "real" target from that side.

The name of the join table shouldn't cause any problems here.


Your questions array contains 3 items. When you create a Testing instance and specify to create it with :questions => questions it is going to add them to the questions relationship, but because this relationship is through another one, they must be added to the other one first, resulting in them being inserted twice. Typically, you would have some other model representing the join table, so that you have 3 records inserted into the Questions table and also 3 into the TestingQuestions join table (has_many :through).

Looks to me like its an issue in how you have defined your TestingQuestions model, which you have not shown. For example, is it pointing to the same table as the Questions model?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜