如何在表中搜索类似记录并显示计数 - Ruby on Rails

时间:2010-04-14 04:52:25

标签: ruby-on-rails

我在我正在构建的Ruby on Rails应用程序中创建了一个名为Tags的表。它是一个博客应用程序,因此我允许用户将标签与帖子关联,并通过以下方式执行此操作:posts,:has_many =>标签和标签belongs_to:发布关联。

现在我有了我的标签表,我试图看看如何渲染视图,以便显示标签和标签计数。 (应该注意的是,我试图在/views/posts/index.html.erb文件中呈现这一点。)

例如,如果Tag表中有10个条目用于tag_name Sports。如何在视图中显示Sports(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 个答案:

答案 0 :(得分:4)

执行以下操作:

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

答案 1 :(得分:0)

首先 - 您的关联似乎有误。标签和帖子是多对多关联,而不是一对多。

我强烈建议您查看其中一个acts_as_taggable实现为您执行此操作。否则,如果您愿意,您可以创建一个has_many :through关联,但这将重新发明轮子。

对于每个页面加载,在集合上调用count()非常糟糕的主意,因为这会让您在每个标记的数据库中点击;大规模的非常昂贵的操作。此外,具有给定标记的帖子数量不是您需要在请求时计算的数字,因此这种方法既昂贵又不必要。

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列。< / p>

在您的视图中,您可以像任何其他列一样在迭代时显示计数:

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

进一步阅读:
ActiveRecord has_many :through associations
ActiveRecord association basics (:counter_cache discussed in section 4.1.2.4)