Revising named_scope semantics in associated classes


#1

Suppose I have the following models:

class Post < ActiveRecord::Base
has_and_belongs_to_many :categories
named_scope :active, :conditions => {:active => true}
end

class Category < ActiveRecord::Base
has_and_belongs_to_many :posts
end

I can call Post.active to get the set of all active Post objects. And
I can call some_category.posts.active to get all active Post objects
associated with some_category.

But what if I want slightly different semantics for the active posts
within a category? Perhaps there is an additional condition that
should apply in this case, as suggested by the new method shown here:

class Category < ActiveRecord::Base
has_and_belongs_to_many :posts

def self.active_posts
  channels.active.all :conditions => {:show_in_category => true}
end

end

Instead of introducing a new active_posts method, is there any way to
define conditions that should be merged into the named_scope when it
is reference from the associated class?

-Sven


#2

I’m a little confused by your example. Do you mean posts instead of
channels? :show_in_category is on Post, correct?

Assuming posts and :show_in_category on Post, couldn’t you just add a
second
named_scope to Post, show_in_category (for lack of a better name)?

class Post < ActiveRecord::Base
named_scope :active, :conditions => { :active => true }
named_scope :show_in_category, :conditions => { :show_in_category =>
true
}

end

Then you could do some_category.posts.active or
some_category.posts.active.show_in_category as you see fit.

Thoughts?

Regards,
Craig


#3

Sorry, I made some mistakes when I tried to simplify my project code.
I’m trying to amend the semantics of an existing named_scope when it’s
called from an association, not add an additional one. Here’s a more
complete example (which I hope I’ve gotten right):

class Post < ActiveRecord::Base
has_many :category_assignments
has_many :categories, :through => :category_assignments
named_scope :active, :conditions => {:active => true}
end

class Category < ActiveRecord::Base
has_many :category_assignments
has_many :posts, :through => :category_assignments
end

class CategoryAssignment < ActiveRecord::Base
belongs_to :post
belongs_to :category
# has attribute show_in_category which allows
# showing/hiding posts on a per-category basis
end

I want to be able to do this

some_category.posts.active

And get the semantics of the active_posts method below:

class Category < ActiveRecord::Base
has_many :category_assignments
has_many :posts, :through => :category_assignment

def active_posts
  posts.active.all :conditions =>

[‘category_assignment.show_in_category = ?’, true]
end
end

So when I call

Post.active

I get the set of all active posts. But when I call

some_category.posts.active

I get the set of all active posts in some_category where
show_in_category is true (like calling my active_posts method, but
using a named_scope instead).

One possibility is to do something like this:

class Category < ActiveRecord::Base
has_many :category_assignments
has_many :posts, :through => :category_assignment
has_many :visible_posts, :class_name => ‘Post’, :through
=> :category_assignment,
:conditions => [‘category_assignment.show_in_category
= ?’, true]
end

And then remember to call

some_category.visible_posts.active

This lets me use the named scope instead of a method but the semantics
aren’t right. I’m trying to express the notion that active
category.posts are subject to an additional restriction relative to
active posts. I’m not trying to divide posts into two groups. I’m
just trying to restrict active posts within a category.

-Sven


#4

On Wed, Oct 22, 2008 at 1:43 PM, Sven removed_email_address@domain.invalid wrote:


This lets me use the named scope instead of a method but the semantics
aren’t right. I’m trying to express the notion that active
category.posts are subject to an additional restriction relative to
active posts. I’m not trying to divide posts into two groups. I’m
just trying to restrict active posts within a category.

Restricting is dividing your set into those items you want and those you
don’t. Since you have attributes across two models, Post#active and
CategoryAssignment#show_in_category, though, I don’t think you can
combine
them into one named_scope. I think you’ll have to do something like you
suggested at the end of your last message, or you’ll have to wrap
everything
in a class method to have the semantics that you want.

Regards,
Craig