我尝试优化一些查询(Rails 2.3.18)
这是我的测试用例:
class Post
belongs_to :category
belongs_to :user
named_scope :public, :conditions => ["#{Post.table_name}.public = ?", true]
named_scope :of_user, lambda {|u|
{ :conditions => ["#{Post.table_name}.user_id = ?", u] }
}
end
class Category
has_many :posts
end
class User
has_many :posts
end
我的查询很简单:获取所有具有用户公开信息的类别。
def categories
Post.of_user(u).public.map(&:category)
end
SELECT * FROM posts WHERE posts.user_id = 123 AND posts.public = 1
SELECT * FROM categories WHERE category_id = 4
SELECT * FROM categories WHERE category_id = 5
SELECT * FROM categories WHERE category_id = 6
我们现在有1个帖子查询,每个类别有n个查询。
使用:include
:
def categories
Post.of_user(u).public.find(:all, :include => :category).map(&:category)
end
SELECT * FROM posts WHERE posts.user_id = 123 AND posts.public = 1
SELECT * FROM categories WHERE category_id IN (4,5,6)
现在,我们只有2个查询:一个用于帖子,一个用于类别。
使用proxy_options
:
def categories
proxy_options = Post.of_user(u).public.proxy_options
# Returns { :conditions => "posts.user_id = 123 AND posts.public = 1" }
proxy_options[:joins] = "INNER JOIN #{Post.table_name}
ON #{Post.table_name}.category_id = #{Category.table_name}.id"
return Category.find(:all, proxy_options)
end
SELECT * FROM categories INNER JOIN posts ON posts.category_id = category.id
WHERE posts.user_id = 123 AND posts.public = 1
它有效,我只有1个查询,但我发现这个方法“难看”。
你有“通过关联使用named_scope”的任何其他方法吗?
答案 0 :(得分:0)
在这种情况下,我可能会使用
class User
has_many :posts
has_many :categories, :through => :posts
end
并且您不需要任何named_scope来获取用户的类别。
答案 1 :(得分:0)
您可以创建另一个关联,让Rails为您处理SQL查询。
class User < ActiveRecord::Base
has_many :posts
has_many :public_posts, :class_name => 'Post', :conditions => { :public => true }
has_many :public_post_categories, :through => :public_posts, :source => :category
end
使用此功能,您只需拨打User.public_post_categories
。