在Rails中覆盖has_many关联的named_scope的最佳方法?

发布于 2024-09-19 01:53:49 字数 1399 浏览 5 评论 0原文

注意:我使用的是 Rails 2.3.8,而不是 3。

我有一个带有 default_scope 的照片模型:

default_scope :conditions => ["published = ?", true], :order => :position

调用 photo_album.photos 会返回按位置排序的所有已发布照片。但是,当在管理面板中循环浏览这些相册以显示每个相册中的照片数量时,结果是错误的:

pluralize(photo_album.photos.count, "photo")

返回 0,因为没有发布任何照片。

我知道已经有人问过类似的问题,并且答复通常是“使用 with_exclusive_scope 类方法”。据我所知,这完全阻止了标准 Rails 关联的使用 - 基本上会导致这样的结果:

pluralize(Photo.all_photos_in_album(photo_album.id).count, "photo")

并且需要一个类方法,例如:

def Photo.all_photos_in_album(album_id)
  self.with_exclusive_scope { find(:all, :conditions => ["photo_album_id = ?", album_id]) }
end

仅显示相册中的照片总数。这看起来很疯狂——覆盖默认值并不需要放弃 Rails 关联约定。 with_exclusive_scope 也不能在实例方法(受保护方法)中使用 - 这将允许我创建一个名为“all_photos”的 PhotoAlbum 实例方法,以至少保留关联的外观(photo_album.all_photos)。但是不,这是不允许的 :(

除了删除 default_scopes(已被证明在整个站点中非常有用)之外,还有人知道重写默认范围并维护 Rails 关联语法的方法吗?

谢谢!

编辑:

我最后添加了一个 PhotoAlbum 实例方法,虽然它不是实际的 default_scope 覆盖,但在我看来确实可以实现更好的语法:

def all_photos_count
  PhotoAlbum.count_by_sql("SELECT COUNT(id) FROM photos WHERE photo_album_id = #{self.id} ORDER BY created_at")
end

pluralize(photo_album.all_photos_count, "photo")

虽然它不完全是 AR has_many 关联并且它依赖于纯 SQL,但这是我最好的妥协到目前为止已经找到了。

Note: I'm using Rails 2.3.8, not 3.

I have a Photo model with a default_scope:

default_scope :conditions => ["published = ?", true], :order => :position

Calling photo_album.photos returns all published photos ordered by position as it should. However, when looping through these photo albums in an admin panel to display the number of photos in each, the results are wrong:

pluralize(photo_album.photos.count, "photo")

returns 0, as none are published.

I know that similar questions have been asked, and the reply typically is along the lines of "use a with_exclusive_scope class method". As far as I can tell, this completely prevents the use of standard Rails associations - basically resulting in something like this:

pluralize(Photo.all_photos_in_album(photo_album.id).count, "photo")

and requiring a class method like:

def Photo.all_photos_in_album(album_id)
  self.with_exclusive_scope { find(:all, :conditions => ["photo_album_id = ?", album_id]) }
end

just to display the total number of photos in an album. This seems insane - overriding the default should not require abandoning Rails association conventions. with_exclusive_scope can not be used in an instance method (protected method) either - this would have allowed me to create a PhotoAlbum instance method called "all_photos" to at least preserve the semblance of associations (photo_album.all_photos). But no, that is not allowed :(

Aside from removing default_scopes, which have proven very useful across the site, does anyone know of a way override default scopes and maintain Rails association syntax?

Thanks!

Edit:

I wound up adding a PhotoAlbum instance method that, while it isn't an actual default_scope override, does at make for much nicer syntax in my views:

def all_photos_count
  PhotoAlbum.count_by_sql("SELECT COUNT(id) FROM photos WHERE photo_album_id = #{self.id} ORDER BY created_at")
end

pluralize(photo_album.all_photos_count, "photo")

While it's not exactly an AR has_many association and it relies on pure SQL, it's the best compromise I've found so far.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

泼猴你往哪里跑 2024-09-26 01:53:49

我不明白你为什么不在专辑中这样做:

has_many :photos
has_many :published_photos, :class_name => 'Photo', :conditions => ["published = ?", true], :order => :position

这样你就可以这样做:

@album.photos.count
@album.published_photos

等等......

I don't understand why you don't do in Album:

has_many :photos
has_many :published_photos, :class_name => 'Photo', :conditions => ["published = ?", true], :order => :position

This way you could do:

@album.photos.count
@album.published_photos

And so on...

Spring初心 2024-09-26 01:53:49

对我来说,这种情况下最好的解决方案是既不使用default_scope也不使用has_many条件,而只使用named_scopes。两个named_scopes完成了我保持观点精简所需的大部分内容:

named_scope :public_list, :conditions => ["published = ?", true], :order => :position
named_scope :private_list, :order => "created_at DESC"

For me, the best solution in this case was to use neither default_scope nor has_many conditions and to just stick with named_scopes. Two named_scopes accomplished most of what I needed to keep my views lean:

named_scope :public_list, :conditions => ["published = ?", true], :order => :position
named_scope :private_list, :order => "created_at DESC"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文