【问题标题】:Using named_scope through associations通过关联使用 named_scope
【发布时间】:2013-11-19 08:43:23
【问题描述】:

我尝试优化一些查询(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”还有其他方法吗?

【问题讨论】:

    标签: mysql sql ruby-on-rails ruby ruby-on-rails-2


    【解决方案1】:

    在这种情况下,我可能会使用

    class User
      has_many :posts
      has_many :categories, :through => :posts
    end
    

    而且您不需要任何 named_scope 来获取用户的类别。

    【讨论】:

      【解决方案2】:

      您可以创建另一个关联,让 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多