RoR搜索基于标签之类的多对多关联

时间:2011-08-11 22:51:33

标签: ruby-on-rails has-many-through

我已经构建了一个包含多个不同模型的RoR数据库。每个“记录”都有许多标记,并且还通过“cat_id”放入类别中。我已经构建了所有模型,但我需要过滤帮助。现在,我可以从带有节点的树视图中选择一个类别,并显示该类别和子类别中的所有记录。我还可以使用搜索功能(SQL中的LIKE运算符)进行简单的文本搜索。我想添加一个额外的标签过滤器,以便能够选择类别和标签并显示结果。

这是我到目前为止所得到的:

记录模型

class AuctionRecord < ActiveRecord::Base

  #comments
  has_many :comments, :dependent => :destroy

  #tags
  has_many :auction_records_tags
  has_many :tags, :through => :auction_records_tags 

标签模型

class Tag < ActiveRecord::Base
  attr_accessible :name
  has_many :auction_records_tags
  has_many :auction_records, :through => :auction_records_tags
end

AUCTIONS_RECORDS_TAGS模型

class AuctionRecordsTag < ActiveRecord::Base
  attr_accessible :auction_record_id, :tag_id

  belongs_to :tag
  belongs_to :auction_record

end

正如您所看到的,记录和标签具有多对多的关系,因此可以选择多个标签并返回许多拍卖记录。

记录控制器

@auction_records = AuctionRecord.filter(session[:search], @cat_sql).order(sort_column + " " + sort_direction).paginate(:per_page => 20, :page => session[:page] )

过滤功能

 #this is the main search engine
        def self.filter(search, cat_sql)   

        search_sql = "" 

        if search != ""  
          search_sql = "title LIKE '%#{search}%' OR itemnumber LIKE '%#{search}%' OR buyer LIKE '%#{search}%' OR seller LIKE '%#{search}%'"
          end

        if cat_sql != "" && search == ""
          search_sql = cat_sql
        end    

        if cat_sql != "" && search != ""
          search_sql = search_sql + " AND " + cat_sql
        end

        if search_sql !=""      
          where(search_sql)
        else 
          scoped
        end

      end

我通过循环遍历所有节点和子节点手动生成类别sql语句。如你所见,我几乎所有“手动”(不是最好的方式)。某些过滤器也可能未定义的事实很麻烦(例如类别选择,但没有搜索词)。我认为所有三个过滤器都可以在一行代码中完成,但我不确定它是如何完成的。也许像tags.auction_records这样的东西?如果我需要发布表的模式,我也可以这样做,但是现在所有的分类和标记都是用整数/ id关系完成的。

提前感谢您的任何帮助/评论

祝你好运

添加了信息#1

NODE MODEL(用于分类/类别)

class Node < ActiveRecord::Base
  has_many :nodes
  belongs_to :node
end

SCHEMA

 create_table "auction_records", :force => true do |t|
    t.string   "title"    
    t.string   "categorization"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

 create_table "auction_records_tags", :force => true do |t|
    t.integer  "auction_record_id"
    t.integer  "tag_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "nodes", :force => true do |t|
    t.integer  "node_id"
    t.string   "text"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "tags", :force => true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

对于“auction_records”,字段分类包含node_id整数,以指向它在树视图中属于哪个节点。如果单击单个节点(类别),则会显示许多auction_records。 auction_records_tags还会在auction_records和tags之间创建关联。我找到了一些仅适用于一个tag_id的东西,但我必须为多个标签工作。

现在我有了这个代码,它返回错误“未命名的关联”节点“找不到”

       search_term = session[:search]
        term = "%#{search_term}%"
        @auction_records = AuctionRecord.scoped
        @auction_records = @auction_records.where('title LIKE ?', term).where('description LIKE ?',term)  if search_term
        @auction_records = @auction_records.joins(:nodes).where('node.node_id IN ?', session[:cat_id])  if session[:cat_id]
            @auction_records = @auction_records.joins(:tags).where('tags.id = ?', session[:tag_ids])  if session[:tag_ids]
        @auction_records = @auction_records.order(sort_column + " " + sort_direction).paginate(:per_page => 20, :page => session[:page] )

1 个答案:

答案 0 :(得分:1)

请记住,在Rails 3中,您可以执行链接查询,这些查询比串联更不容易出错,也最好使用通配符来防止SQL注入。您可以重构代码,使其看起来与此类似:

def self.filter(search_term, categories, tags)
  term = "%#{search_term}%"
  auction_records = AuctionRecord.scoped
  auction_records = auction_records.where('title LIKE ?', term).where('other_field LIKE ?',term)  if search_term
  auction_records = auction_records.joins(:categories).where('categories.name IN ?', categories)  if categories
  auction_records = auction_records.joins(:tags).where('tags.name IN ?' tags)  if tags
end