【问题标题】:Creating has_many :through records 2x times创建 has_many :through 记录 2 次
【发布时间】:2011-02-20 16:43:15
【问题描述】:

我有模型

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

在 testing_questions 中创建了 6 个 SQL 查询和 6 条记录。为什么?

【问题讨论】:

  • 你的模型TestingQuestion看起来如何?

标签: ruby-on-rails has-many-through


【解决方案1】:

第一个问题可能是连接表的命名

testing_questions

Rails 期望连接表的名称是按字母顺序连接的两个表名称

question_testings

【讨论】:

  • 我知道,但是有has_many :testing_questions, :dependent => :destroy 和 has_many :questions, :through => :testing_questions 我觉得确定中间表就够了。
  • 我认为您必须使用 set_table_name 才能使用旧表命名
  • 这不是真的:表名是从模型名派生的。如果模型名是 TestingQuestion,那么表名就是 testing_questions。使用:through,您可以明确指定连接表模型的名称。
【解决方案2】:

查看表结构,它是表之间的 has_and_belongs_to_many 关系,这里不需要使用 has_many 和 through 选项,因为您的连接表将没有模型(除了 ids 之外没有额外的列)。无需为连接表创建模型。

所以,我建议像这样改变你的模型


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

请将您的表名更改为 question_testings。

请查看此链接以获取更多信息http://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many

【讨论】:

  • 我不想使用过时的 has_and_belongs_to_many,我想使用 has_many :through。改变方案或类似的东西可能是一个问题的解决方案,但问题已经解决了,现在我想知道为什么 Rails 会这样做。
  • 您能告诉我您使用哪个 gem 或插件在控制台中显示 sql 查询吗?您也可以分享您的解决方案吗?
  • 我记不太清了,但尝试将此文件添加到您的主目录:gist.github.com/405733
  • @antiarchitect:可以通过将此代码添加到 ~/.irbrc 文件来完成控制台登录。所有项目都会有它。 (格式不能在 cmets 中控制,所以我添加分号)如果 ENV.include?('RAILS_ENV') && !Object.const_defined? ; ('RAILS_DEFAULT_LOGGER') ;需要'记录器'; RAILS_DEFAULT_LOGGER = Logger.new(STDOUT) ;结束;
【解决方案3】:

不查看 Rails 源代码或四处尝试,我建议尝试从 Question 类中删除 "has_many :testing_questions" 或添加 has_many ... :through 那里。刚才 Rails 只是与连接表有关系,但与那一侧的“真实”目标没有关系。

连接表的名称在这里应该不会造成任何问题。

【讨论】:

    【解决方案4】:

    我创建了一个非常简单的示例来处理您的示例:

    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(您没有显示)。这有帮助吗?

    【讨论】:

    • 我看到在您的示例中一切正常。 TestingQuestion 模型与您的模型完全相同...但是我将关联记录绑定到测试的方式不同。我尝试在创建测试时绑定它们
    • 是的,但这不应该有所作为,只有在保存时才会创建 TestingQuestion。我假设在您的示例中您编写了Testing.create,您仍然必须显式调用保存。正确的?我需要。我正在针对 Rails 2.3.5 进行测试。另外:我看到我的 TestingQuestion 有一个 id,应该不需要它。
    【解决方案5】:

    您的 questions 数组包含 3 个项目。当您创建一个Testing 实例并指定使用:questions =&gt; questions 创建它时,它会将它们添加到questions 关系中,但是由于这种关系是通过另一个关系,所以必须先将它们添加到另一个关系中,从而导致在他们被插入两次。通常,您将有一些其他模型表示连接表,因此您将 3 条记录插入到 Questions 表中,并将 3 条记录插入到 TestingQuestions 连接表中(has_many :through)。

    在我看来,这是您如何定义 TestingQuestions 模型的问题,但您没有展示。例如,它是否指向与 Questions 模型相同的表?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-23
      • 2010-12-03
      • 1970-01-01
      • 2014-02-27
      • 2015-05-16
      • 1970-01-01
      • 2014-06-03
      • 2011-10-01
      相关资源
      最近更新 更多