Как найти в таблице похожие записи и отобразить счетчик - Ruby on Rails - PullRequest
1 голос
/ 14 апреля 2010

Я создал таблицу в своем приложении Ruby on Rails, которую я создаю, и назвал ее тегами. Это приложение для блогов, поэтому я разрешаю пользователю связывать теги с постом и делать это с помощью тегов: posts,: has_many => и Tag тега assign_to: post.

Теперь, когда у меня есть таблица тегов, я пытаюсь увидеть, как бы я отображал представление так, чтобы оно отображало тег и количество тегов. (следует отметить, что я пытаюсь сделать это в файле /views/posts/index.html.erb).

Например, если в таблице тегов есть 10 записей для имени тега Спорт. Как я могу отобразить Спорт (10) в представлении. Я не собираюсь делать это для определенного тега, а скорее как-то искать в таблице, объединять похожие теги и отображать список всех тегов с количеством отсчетов рядом с ними. (Я действительно хочу, чтобы это была ссылка на список постов, содержащих этот тег, но я рано научился задавать только один вопрос за раз).

Надеюсь, это имеет смысл.

ОБНОВЛЕНИЕ ДЛЯ КОММЕНТАРИЙ

вид

<% @tag_counts.each do |tag_name, tag_count| %>
    <tr>
      <td><%= link_to(tag_name, posts_path(:tag_name => tag_name)) %> </td>
      <td>(<%=tag_count%>)</td>
    </tr>
<% end %>

PostsController:

def index
    @tag_counts = Tag.count(:group => :tag_name)
    @posts = Post.all :order => "created_at DESC"



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

Ответы [ 2 ]

4 голосов
/ 14 апреля 2010

Выполните следующие действия:

Tag.count(:group => :name).each do |tag_name, tag_count|
  puts "tag_name=#{tag_name}, tag_count=#{tag_count}"
end

Вы можете улучшить производительность, если добавите индекс к столбцу name в таблице tags.

Для отображения сообщений, связанных с именем тега, выполните следующие действия:

В методе контроллера задайте хэш подсчета:

Установите @tag_counts в действии контроллера, связанном с представлением, отображающим имена тегов.

@tag_counts = Tag.count(:group => :tag_name)

В представлении показывать каждый тег в виде ссылки:

<% @tag_counts.each do |tag_name, tag_count| %>
  <%= link_to(tag_name, posts_path(:tag_name => tag_name)) %> (<%=tag_count%>)
<% end %>

Ссылка указывает на метод индекса вашего PostsController. Каждая ссылка имеет параметр tag_name.

В методе index PostsController:

class PostsController < ApplicationController
  def index
    @tag_counts = Tag.count(:group => :tag_name)
    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)
  end
end

Редактировать Обновлен код для изменения поля name на tag_name.

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

Во-первых - у вас, похоже, неправильные ассоциации. Теги и сообщения являются ассоциацией «многие ко многим», а не «один ко многим».

Я настоятельно рекомендую взглянуть на одну из реализаций acts_as_taggable , чтобы сделать это для вас. В противном случае вы можете создать has_many :through ассоциацию, если хотите, но это будет заново изобретать колесо.

Вызов count() для коллекции для каждой загрузки страницы - очень плохая идея 1010 *, потому что это заставит вас попасть в базу данных для каждого тега; очень дорогая операция в масштабе. Кроме того, количество постов с данным тегом не является цифрой, которую нужно вычислять во время запроса, поэтому такой подход является дорогостоящим и ненужным.

Rails имеет встроенную функцию под названием counter_cache, которая позаботится об этом за вас, кэшируя количество связанных записей в целочисленном поле и обновляя его при создании новых записей. Вот как вы это настроили:

Создание миграции для таблицы tags:

def up
  add_column :tags, :taggings_count, :integer, :default => 0

  Tag.reset_column_information
  Tag.all.each do |t|
    Tag.update_counters t.id, :taggings_count => t.taggings.length
  end
end

def down
  remove_column :tags, :taggings_count
end

И изменить belongs_to ассоциацию:

class Tagging < ActionRecord::Base
  belongs_to :tag, :counter_cache => true
  belongs_to :post
end

Если вы создаете свою собственную систему тегирования, вы подключите оставшиеся две модели примерно так:

class Post < ActiveRecord::Base
  has_many :taggings
  has_many :tags, :through => :taggings
end

class Tag < ActiveRecord::Base
  has_many :taggings
  has_many :posts, :through => :taggings
end

Но, опять же, было бы намного проще использовать готовое решение.

С этого момента каждый раз, когда вы создаете новую Post ассоциацию для Tag с помощью модели Tagging, он автоматически обновляет для вас столбец taggings_count.

В ваших представлениях вы можете отображать счетчик при выполнении итерации, как и любой другой столбец:

<%= link_to "#{tag.name} (#{tag.taggings_count})", posts_path(:tag_name => tag.name) %>

Дальнейшее чтение:
ActiveRecord has_many: через ассоциации
Основы ассоциации ActiveRecord (: counter_cache обсуждается в разделе 4.1.2.4)

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