如何使用acts_as_rateable查找未分级的模型

时间:2009-06-12 09:12:19

标签: sql ruby-on-rails

我有一个使用acts_as_rateable插件的rails应用程序。

我一直在想弄清楚如何使用这个插件检索未评级的模型 - 但这更像是一个常见的rails / SQL问题,而不是特定于这个插件。

作为有价物的行为会将以下内容添加到架构中:

create_table "ratings", :force => true do |t|
    t.integer  "rating",                      :default => 0
    t.string   "rateable_type", :limit => 15, :default => "", :null => false
    t.integer  "rateable_id",                 :default => 0,  :null => false
    t.integer  "user_id",                     :default => 0,  :null => false
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "ratings", ["user_id"], :name => "fk_ratings_user"

我的评级型号也有一个用户ID列。

我希望能够检索未评级的特定模型的所有实例,以及尚未由模型创建者以外的其他人评级的所有实例,例如:这是一个模型:

class Review < ActiveRecord::Base
  acts_as_rateable

  belongs_to :user
  ...
end

所以我想要类似下面的伪代码

Review.find(:all, :conditions=>"not rated by anyone")
Review.find(:all, :conditions=>"not rated by anyone except review.user")

但是我无法弄清楚SQL是如何做到这一点的,也不是用于生成SQL的rails魔法: - )

更新:此查询似乎找到除拥有该模型的用户以外的其他人评定的所有模型。所以我想我只需要以某种方式反转它。

 Review.find(:all, 
  :joins=>'left join ratings on reviews.id=ratings.rateable_id && ratings.rateable_type="Review"', 
  :conditions=>'reviews.user_id <> ratings.user_id', 
  :group=>'reviews.id')

2 个答案:

答案 0 :(得分:1)

命名范围是解决此问题的方法。我会在您的Review模型中添加两​​个命名范围。类似的东西:

class Review < ActiveRecord::Base
  acts_as_rateable

  belongs_to :user

  named_scope :not_rated, :conditions => { :rating => 0 }
  named_scope :not_rated_by_others,
              :conditions => ["user != ? AND rating == 0", self.user]
end

然后你可以这样做:

@not_rated = Review.not_rated
@not_rated_by_others = Review.not_rated_by_others

Railscast that explains named scopes


编辑:第二次尝试

是的,让我们再来吧!其中一个问题是那里有多个acts_as_rateable插件。我一直在RubyForge上使用this one进行测试。

class Review < ActiveRecord::Base
  belongs_to :user

  acts_as_rateable

  named_scope :not_rated, :select => 'reviews.*',
              :joins => 'left join ratings on reviews.id = ratings.rateable_id',
              :conditions => 'ratings.rateable_id is null'

  named_scope :not_rated_by_others, lambda { |user| { :select => 'reviews.*',
              :joins => 'left join ratings on reviews.id = ratings.rateable_id',
              :conditions => ['ratings.user_id != ? and ratings.rateable_id is null',
                 user] }}
end

像这样使用:

frank = User.find_by_name('frank')
@not_rated = Review.not_rated
@not_rated_by_others = Review.not_rated_by_others(frank)

答案 1 :(得分:0)

我有一些方法使用这样的查询:

Review.find(:all, 
 :joins=>'left outer join ratings on reviews.id=ratings.rateable_id && ratings.rateable_type="Review"',
  :conditions=>'ratings.rating is NULL')

这看起来它会返回所有没有评级的评论模型。

我认为这个正在努力查找创建评论的用户未评级的所有评论模型:

Review.find(:all, 
  :joins=>'left outer join ratings on reviews.id=ratings.rateable_id && ratings.rateable_type="Review" && ratings.user_id <> reviews.user_id',
  :conditions=>'ratings.rating is NULL')