2

我需要获得用户浏览次数最多的 5 篇文章。为此,我实现了“印象”功能,并且文章和印象模型之间存在多态关系。使用它,我无法获得每篇文章从用户那里获得的视图。但现在我需要从 db 中获取 5 篇浏览次数最多的文章。我知道这是个愚蠢的问题,但我试过但找不到答案。

schema.rb (我没有粘贴完整的文件,但只是相关的)

ActiveRecord::Schema.define(:version => 20130419101017) do

  create_table "articles", :force => true do |t|
    t.string   "title"
    t.text     "body"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
    t.integer  "user_id"
  end

  create_table "comments", :force => true do |t|
    t.text     "content"
    t.integer  "user_id"
    t.string   "article_id"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

  create_table "impressions", :force => true do |t|
    t.string   "impressionable_type"
    t.integer  "impressionable_id"
    t.integer  "user_id"
    t.string   "ip_address"
    t.datetime "created_at",          :null => false
    t.datetime "updated_at",          :null => false
  end

文章控制器.rb

class ArticlesController < ApplicationController
  before_filter :is_user_admin, only: [:new, :create, :edit, :destroy]
  before_filter :log_impression, :only=> [:show]

    def is_user_admin
      redirect_to(action: :index) unless current_user.try(:is_admin?) 
      return false 
    end

   def log_impression
     @article = Article.find(params[:id])
     # this assumes you have a current_user method in your authentication system
      @article.impressions.create(ip_address: request.remote_ip,user_id:current_user.id)
   end

      def index
          @articles = Article.all(:order => "created_at DESC")
      @article_titles = Article.first(10)
      @article_popular = Article. 
      @tags = Tag.all
      end

    def show
       @article = Article.find(params[:id])
       @related_articles = Article.joins(:taggings).
       where('articles.id != ?', @article.id)
       .where(taggings: { tag_id: @article.tag_ids }) 
    end

      def new
      @article = Article.new
      end

    def create
      @article = Article.new(params[:article])
      @article.user_id = current_user.id
      if @article.save
        flash[:success] = "article created!"
        redirect_to article_path(@article)
      else
        render 'new' 
      end 
    end

    def destroy
      @article = Article.find(params[:id])
      @article.destroy
      redirect_to action:  'index'  
    end

    def edit
      @article = Article.find(params[:id])
    end

    def update
      @article = Article.find(params[:id])
      if @article.update_attributes(params[:article])
       flash.notice = "Article '#{@article.title}' Updated!"
       redirect_to article_path(@article)
      else 
        render 'edit'
      end
    end
end

文章.rb

class Article < ActiveRecord::Base
   attr_accessible :title, :body
   attr_accessible :tag_list
   has_many :comments
   belongs_to :user
   has_many :taggings
   has_many :tags, through: :taggings
   has_many :impressions, :as=>:impressionable
   validates :title, :body, :tag_list,  :presence => true

  def impression_count
    impressions.size
  end

  def unique_impression_count
    impressions.group(:ip_address).size #UNTESTED: might not be correct syntax
  end


   def tag_list
     self.tags.collect do |tag|
      tag.name
     end.join(", ")
   end

   def tag_list=(tags_string)
     tag_names = tags_string.split(",").collect{|s| s.strip.downcase}.uniq
     new_or_found_tags = tag_names.collect { |name| Tag.find_or_create_by_name(name) }
     self.tags = new_or_found_tags
   end
end

印象.rb

class Impression < ActiveRecord::Base
  attr_accessible :impressionable_id, :impressionable_type, :ip_address, :user_id
  belongs_to :impressionable, :polymorphic=>true 
end

文章/show.html.erb

Viewed: <%=@article.impression_count %> times

这就是我计算用户观看次数的方式。现在我想获得用户浏览次数最多的 5 篇文章。任何帮助将不胜感激。有关更多信息,我已使用(rails 中页面视图的简单命中计数器)来获取用户视图。

4

2 回答 2

3

我认为最好的方法是避免映射 ruby​​ 对象,是使用计数器缓存

# add the impression count column to your tables
t.integer :articles, :impressions_count
t.integer :comments, :impressions_count

在您的模型中:

class Article < AR
  has_many :impressions, as: :impressionable
  has_many :comments
end

class Comment < AR
  belongs_to :article
  has_many :impressions, as: :impressionable
end

class Impression < AR
  # the counter cache here is the important option
  belongs_to :impressionable, polymorphic: true, counter_cache: :impressions_count
end

使用此设置,每次创建印象impressions_count时,相应模型中的列都会更新。因此,您可以简单地对展示次数进行排序以获得前 5 名:

Article.order('articles.impressions_count DESC').limit(5)

分别

Comment.order('comments.impressions_count DESC').limit(5)

当然你也可以这样做@article.impressions_count...

于 2013-04-21T10:31:54.410 回答
1

您是否尝试过:

impressions = Impression.select("impressionable_id, count(*) as qty").where("impressionable_type = ?", 'Article').group('impressionable_type, impresionable_id').order('qty desc').limit(5)
Article.joins(:impressions).where(impressions: {impresionable_id: impressions.map(&:impressionable_id)})
于 2013-04-21T10:30:27.143 回答