为什么 Rails 在使用具有关联的范围时会生成重复的 SQL 条件?
我设置了一个模型结构,允许不同的模型通过 has_many ... :through ... 关联与文件模型关联,该关联也是多态的,以便文件可以属于许多不同的模型,不同的资源可以有许多文件。
然后,文件模型属于附件模型,这是实际的文件,但我使用文件模型来跟踪不同版本等。 Attachment 模型知道该文件是否是图像。
下面是基本模型结构:
class Resource < ActiveRecord::Base
has_many :file_associations, :as => :association
has_many :files, :through => :file_associations
...
end
class FileAssociation < ActiveRecord::Base
belongs_to :r_file
belongs_to :association, :polymorphic => true
...
end
class File < ActiveRecord::Base
has_many :file_associations
belongs_to :attachment
named_scope :images, lambda { { :include => :attachment,
:conditions => "attachments.type = 'AttachmentImage'" } }
...
end
然后,我使用此设置从具有图像附件的特定资源中检索所有文件,如下所示:
@resource.files.images
当我检查由此生成的 SQL 查询时,它已包含加入资源的条件使用 FileAssociation 两次:
SELECT ....
FROM `files`
LEFT OUTER JOIN `attachments` ON `attachments`.id = `files`.attachment_id
INNER JOIN `file_associations` ON `files`.id = `file_associations`.file_id
WHERE
(
( `file_associations`.association_id = 1 ) AND
( `file_associations`.association_type = 'Resource' )
)
AND
(
( attachments.type = 'AttachmentImage' ) AND
(
( `file_associations`.association_id = 1 ) AND
( `file_associations`.association_type = 'Resource' )
)
)
如果我尝试仅调用 @resource.files,则条件不会重复。
当然,这按预期工作,但从查询来看,我似乎做了一些可以改进的事情,并且我尝试尽可能多地考虑性能。那么为什么会发生这种奇怪的事情以及我可以做些什么来改善它呢?
根据记录,使用 Rails 2.3.5 和 mysql。
更新
我最近做了一个与上面描述的类似的设置,唯一的区别是没有多态关联,但是当我查看查询时,仍然重复条件。所以这不是问题的原因。
然后我还尝试从上面描述的named_scope中删除lambda。我意识到这有点不必要,因为我没有提供任何论据。所以范围最终看起来像:
named_scope :images, :include => :attachment, :conditions => "attachments.type = 'AttachmentImage'"
仍然重复...
可能是时候开票了,但我正在考虑很快迁移到 Rails 3,所以我想我可以等待,看看接下来会发生什么。
I have setup a model structure which allows different models to associate with a File model through a has_many ... :through ... association which is also polymorphic so that a File can belong to many different models and different Resources can have many Files.
The File model then belongs_to an Attachment model which is the actual file but I use the File model to keep track of different versions amongst other things. The Attachment model knows whether the file is an image or not.
Here is the basic model structure:
class Resource < ActiveRecord::Base
has_many :file_associations, :as => :association
has_many :files, :through => :file_associations
...
end
class FileAssociation < ActiveRecord::Base
belongs_to :r_file
belongs_to :association, :polymorphic => true
...
end
class File < ActiveRecord::Base
has_many :file_associations
belongs_to :attachment
named_scope :images, lambda { { :include => :attachment,
:conditions => "attachments.type = 'AttachmentImage'" } }
...
end
I then use this setup to retrieve all Files from a specific Resource that has an Attachment that is an image, like this:
@resource.files.images
When I check the SQL query generated from this it has included that condition to join the Resource with the FileAssociation twice:
SELECT ....
FROM `files`
LEFT OUTER JOIN `attachments` ON `attachments`.id = `files`.attachment_id
INNER JOIN `file_associations` ON `files`.id = `file_associations`.file_id
WHERE
(
( `file_associations`.association_id = 1 ) AND
( `file_associations`.association_type = 'Resource' )
)
AND
(
( attachments.type = 'AttachmentImage' ) AND
(
( `file_associations`.association_id = 1 ) AND
( `file_associations`.association_type = 'Resource' )
)
)
If I try only calling @resource.files then the condition is not duplicated.
This works as intended of course, but judging by the query, it seems like I have done something that could be improved and I try to think about performance as much as I can. So why does this strange thing happen and what can I do to improve it?
For the record, rails 2.3.5 and mysql is used.
Update
I recently did a similar setup like the one described above, the only difference being that there was no polymorphic association, but when I looked at the query, still duplicate conditions. so that was not the cause of the problem.
Then I also tried removing lambda from the named_scope described above. I realized it was kinda unnecessary since I did not supply any argument. So the scope ended up looking like:
named_scope :images, :include => :attachment, :conditions => "attachments.type = 'AttachmentImage'"
Still duplicate...
It might be time to open a ticket but I'm considering migrating to Rails 3 soon so I figured I can wait and see what will happen then.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不知道为什么 Rails 将条件加倍,这可能是一个错误或边缘情况。
您是否尝试过第二个 has_many 关联,如下所示:
I don't know why Rails doubles the condition, it may be a bug or an edge case.
Have you tried a second has_many association, something like this: