Отображение самых популярных сообщений в моем блоге - Ruby on Rails - PullRequest
0 голосов
/ 16 апреля 2010

Я создал простое приложение для блога, используя Ruby on Rails, оба из которых я новичок. Я пытаюсь отобразить мои наиболее «проголосовавшие» посты в моем /views/posts/index.html.erb представлении. Вот основы.

Я создал таблицу голосов и успешно разрешил пользователю «голосовать» за сообщение на странице /views/posts/show.html.erb. VotesController передает post_id в столбец таблицы Votes post_id и возвращает количество голосов для этого сообщения через ajax на ту же страницу показа.

class Vote
  belongs_to :post`
end

и

class Post
  has_many :votes
end

Я хотел бы отобразить в /views/posts/index.html.erb заголовок и количество голосов, за которые он был проголосован, упорядоченный по сообщениям с наибольшим количеством голосов.

EDIT С помощью приведенного ниже кода я смог отобразить (на странице /views/posts/show.html.erb) post_id из таблицы Votes и voice_count для этого post_id. то есть '55 (7) '. Интересно, могу ли я как-то передать post_title в таблицу голосов (в столбец post_title), а затем просто отобразить это вместо post_id. Вот код, который выполняет это.

class PostsController < ApplicationController

     def index
        @tag_counts = Tag.count(:group => :tag_name, 
           :order => 'count_all DESC', :limit => 20)
        @vote_counts = Vote.count(:group => :post_id, :limit => 5)

        conditions, joins = {}, nil
        unless(params[:tag_name] || "").empty?
          conditions = ["tags.tag_name = ? ", params[:tag_name]]
          joins = :tags
        end
        @posts=Post.all(:joins => joins, :conditions=> conditions, :order => 'created_at DESC').paginate :page => params[:page], :per_page => 5

        respond_to do |format|
          format.html # index.html.erb
          format.xml  { render :xml => @posts }
          format.json { render :json => @posts }
          format.atom
        end
      end

VotesController

class VotesController < ApplicationController

  def create
    @post = Post.find(params[:post_id])
    @vote = @post.votes.create!(params[:vote])

       respond_to do |format|
       format.html { redirect_to @post}
       format.js
     end
  end
end

/ просмотров / сообщений / index.html.erb

Most Liked Posts<hr/>
        <% @vote_counts.each do |post_id, vote_count| %>    
                <div id="tag-wrapper">
                    <%= link_to(post_id, posts_path(:post_id => post_id)) %>
                    (<%=vote_count%>)</div>
        <% end %>

Ответы [ 2 ]

7 голосов
/ 16 апреля 2010

Для этого вы можете использовать плагин voice_fu (используйте kandadaboggu-voice_fu версия)

class User
 acts_as_voter
end

Добавить vote_total столбец (целое число) к posts таблице.

class Post
 acts_as_voteable :vote_counter => true
end

Теперь вы можете делать следующее:

user.vote_for(post)       # vote up
user.vote_against(post)   # vote down
post.vote_total           # sum of +ve and -ve votes
post.vote_count           # count of votes

Если вы используете директиву vote_counter, общее количество голосов сохраняется в таблице posts. Для вычисления vote_total дополнительный SQL не требуется.

Чтобы отсортировать посты по voice_total, выполните следующие действия:

Posts.all(:order => "vote_total DESC")

Раскрытие

Я поддерживаю kandadaboggu-vote_fu драгоценный камень.

Редактировать

Чтобы реализовать это в вашей текущей схеме, вы можете сделать следующее:

Post.all(:joins => :votes, :select => "posts.*, count(*) as vote_total",
  :group => "votes.post_id", :order => "vote_total DESC", :limit => 10)

Редактировать 2

Вы можете использовать следующий код для реализации этой функции для работы с текущей логикой. Обратите внимание, что Rails использует соединения INNER, поэтому сообщение не будет выбрано, если у него нет голосования. Вы можете обойти это, всегда голосуя один раз при создании сообщения.

Я исправил ваш paginate звонок. Нынешняя логика крайне неэффективна. Разбивка на страницы применяется к массиву, возвращенному из БД, поэтому весь набор результатов загружается перед выполнением разбивки на страницы. Как правило, обрабатывайте paginate как метод all с двумя дополнительными параметрами.

Обратите внимание, что приведенный ниже SQL будет сильно напрягать ресурсы вашей системы. Возможно, вам придется оптимизировать, сохранив vote_total в таблице posts.

conditions, joins = {}, :votes 

unless(params[:tag_name] || "").empty?
  conditions = ["tags.tag_name = ? ", params[:tag_name]]
  joins = [:tags, :votes]
end
@posts=Post.paginate(
          :select => "posts.*, count(*) as vote_total", 
          :joins => joins, 
          :conditions=> conditions, 
          :group => "votes.post_id", 
          :order => "vote_total DESC",
          :page => params[:page], :per_page => 5)

Редактировать 3

Логика для голосования при создании поста.

class Vote
  belongs_to :user
  belongs_to :post
end

class Post
  belongs_to :user
  after_create :self_vote

  def self_vote
   # I am assuming you have a user_id field in `posts` and `votes` table.
   self.votes.create(:user => self.user)
  end
end

Код итерации для сообщений:

<% @posts.each do |post| %>
 <p><%= link_to(post.title, post_path(post)) %></p>
 <p>
     Created <%=  time_ago_in_words(post.created_at) %>. 
     Votes <%=  post.vote_total %>
 </p> 
<% end %>
0 голосов
/ 16 апреля 2010

используйте запрос mysql. Что-то вроде следующего скажем

@posts=Post.find_by_sql("select p.post, count(v.vote) as vote from posts p, votes v where v.post_id=p.id group by p.id order by vote DESC")

на rhtml

for post in @posts 
  post.post
  post.vote
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...