2013-04-21 29 views
2

我需要用戶獲得5篇最受關注的文章。爲此,我實現了「印象」功能,並且文章和印象模型之間具有多態關係。使用此功能,我無法獲得每篇文章從用戶處獲得的意見。但現在我需要從db中獲取5個最常見的文章。我知道這是一個愚蠢的問題,但我試過了,找不到答案。如何在紅寶石軌道上獲得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 

articles_controller.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 

article.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 

impression.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: <%[email protected]_count %> times 

我這是怎麼計算沒有意見,從用戶。現在我想獲得用戶最喜歡的5篇文章。 任何幫助將升值。欲瞭解更多信息,我已經使用(simple hit counter for page views in rails)獲取用戶視圖。

回答

3

我認爲最好的方式去這裏,以避免Ruby對象的映射,是使用counter cache

# 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列在r相關模型正在更新。所以,那麼你可以簡單排序的展示次數來獲取最大的5個頂級:

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

分別

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

當然,你可以做@article.impressions_count以及...

+0

嗨吸血鬼,感謝您的建議。我需要更多的信息。如果我實施了您的建議,我是否需要更改現有的展示次數設置。有什麼建議麼。 – 2013-04-21 10:58:56

+0

不是我所見......計數器緩存將在您的控制器中通過「@ article.impressions.create」調用進行更新。但是,您可以/應該溝通的是您的「Article」和「Comment」模型中的「impression_count」方法 - 因爲您將使用計數器緩存列。我也認爲這將有利於性能,因爲你可以簡單地把訂單留給數據庫,不需要在ruby中做... – Vapire 2013-04-21 11:06:02

+0

ps:你真的應該在導軌指南中讀到這種可能性,儘管.. – Vapire 2013-04-21 11:07:09

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)}) 
+0

喜rorra,感謝您的答覆。將這個連接查詢寫在articles_controller.rb或其他地方。如果是在articles_controller.rb中,那麼如何在視圖中訪問。我需要把它放在impression.rb(模型)中。任何建議。 – 2013-04-21 10:36:25

+0

\ @articles = Article.joins(:impressions).where(impressions:{impresionable_id:impressions.map(&:impressionable_id)}) 只要您有任何零件,控制器,視圖等,您都可以編寫它訪問模型。 – rorra 2013-04-21 10:38:36

+0

hi rorra,當我試圖在articles_controller.rb/show動作中實現您的建議時,出現以下錯誤: - ArticlesController中的ActiveRecord :: StatementInvalid#顯示 SQLite3 :: SQLException:no such column:impresionable_id:SELECT impressionable_id,count (*)as qty FROM「impressions」WHERE(impressionable_type ='Article')GROUP BY impressionable_type, impresionable_id ORDER BY qty desc LIMIT 5。它說「StatementController#show中的StatementInvalid」。任何建議。 – 2013-04-21 10:55:51