Я создал базу данных RoR с несколькими разными моделями. Каждая «запись» имеет много тегов и также помещается в категорию с помощью «cat_id». Я построил все модели, но мне нужна помощь с фильтрацией. Прямо сейчас у меня есть возможность выбрать категорию в виде дерева с узлами, и она показывает все записи в этой категории и дочерние категории. Я также могу выполнить простой текстовый поиск с помощью функции поиска (оператор LIKE в SQL). Я хочу добавить дополнительный фильтр тегов, чтобы иметь возможность выбрать категорию и тег и показать результаты.
Вот что у меня так далеко:
МОДЕЛЬ ЗАПИСИ
class AuctionRecord < ActiveRecord::Base
#comments
has_many :comments, :dependent => :destroy
#tags
has_many :auction_records_tags
has_many :tags, :through => :auction_records_tags
МОДЕЛЬ TAG
class Tag < ActiveRecord::Base
attr_accessible :name
has_many :auction_records_tags
has_many :auction_records, :through => :auction_records_tags
end
AUCTIONS_RECORDS_TAGS MODEL
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? Если мне нужно опубликовать схему таблиц, я тоже могу это сделать, но на данный момент все категоризация и тегирование выполняются с помощью целочисленных / идентичных отношений.
Заранее спасибо за любую помощь / комментарии
С уважением
Добавлена информация # 1
NODE MODEL (используется для категоризации / категорий)
class Node < ActiveRecord::Base
has_many :nodes
belongs_to :node
end
1035 * 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_tags также создает связь между auction_records и тегами. Я нашел что-то, что работает только для одного 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] )