开发者

Best way to override named_scope for has_many associations in Rails?

开发者 https://www.devze.com 2023-01-16 03:46 出处:网络
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

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.


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


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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号