1

在需要自定义 SQL 行为的情况下,我无法创建正确的 HABTM (has_and_belongs_to_many) 关系。这个想法是让文档可以附加到单个服务或多个服务,以及具有单个或多个文档的相同服务。我创建了一个模型“ResourceDocument”,它包含关系,而不是更传统的双 ID 设置,因为将有更多类型的事物以与服务相同的方式与文档相关。

这是 Document 模型的相关部分:

class Document < ActiveRecord::Base

  # ... etc ...

  has_and_belongs_to_many :services,
                          :foreign_key => 'document_id',
                          :association_foreign_key => 'resource_id',
                          :join_table => 'resource_documents',
                          :insert_sql => proc {"insert into resource_documents (document_id, resource_id, type) values (#{id}, #{record.id}, 'Service')"}

 # ... etc ...

end

其次是服务规范(单元测试文件)的相关部分,它在进行插入时调用 HABTM 关系:

require 'spec_helper'
describe Service do
  before do
    @org = Org.create!(:name => 'org', :asset_code => 'TRNT')
    # ... etc ...
  end

  # ... etc ...

  it "should not allow a document belonging to different org" do
    new_org = Org.create!({:name => 'another test Org'})
    document = FactoryGirl.create(:document, :org => new_org, :services => [@service])
    @service.documents << [document]
    @service.should_not be_valid
  end
end

当我运行时rspec,这个特定的单元测试失败了,特别是文档分配的行(FactoryGirl.create)会吠叫并给出标题中写的错误消息。我在这里做错了什么?我对 ruby​​ 相当陌生,更具体地说,我对必须:insert_sql在 HABTM 关系上执行的整个概念。

谢谢你的帮助!

4

1 回答 1

1

作为参数record传递给:insert_sql,您需要执行以下操作:

:insert_sql => proc {|record| "insert into resource_documents (document_id, resource_id, type) values (#{id}, #{record.id}, 'Service')"}

所以你的代码会是这样的:

class Document < ActiveRecord::Base

  # ... etc ...

  has_and_belongs_to_many :services,
                          :foreign_key => 'document_id',
                          :association_foreign_key => 'resource_id',
                          :join_table => 'resource_documents',
                          :insert_sql => proc {|record| "insert into resource_documents (document_id, resource_id, type) values (#{id}, #{record.id}, 'Service')"}

 # ... etc ...

end

编辑

从 Rails 3.1 发行说明:

以前,has_and_belongs_to_many 关联上的 :insert_sql 和 :delete_sql 允许您调用 'record' 来获取插入或删除的记录。这现在作为参数传递给 proc。

于 2013-03-20T19:33:11.117 回答