为什么 Rails 在使用具有关联的范围时会生成重复的 SQL 条件?

发布于 2024-10-05 13:02:05 字数 1935 浏览 0 评论 0原文

我设置了一个模型结构,允许不同的模型通过 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故事与诗 2024-10-12 13:02:05

请注意,在 Rails 3.0 中“named_scope”
已被弃用,有利于简单地
“范围”

我不知道为什么 Rails 将条件加倍,这可能是一个错误或边缘情况。

您是否尝试过第二个 has_many 关联,如下所示:

class Resource < ActiveRecord::Base
  has_many :file_associations, :as => :association
  has_many :files, :through => :file_associations
  has_many :images, :through => :file_associations,
                    :source => :file,
                    :include => :attachment,
                    :conditions => "attachments.type = 'AttachmentImage'"
  ...
end

Note that in rails 3.0 'named_scope'
is deprecated in favor of simply
'scope'

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:

class Resource < ActiveRecord::Base
  has_many :file_associations, :as => :association
  has_many :files, :through => :file_associations
  has_many :images, :through => :file_associations,
                    :source => :file,
                    :include => :attachment,
                    :conditions => "attachments.type = 'AttachmentImage'"
  ...
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文