GeniyZ GeniyZ

А почему бы и не помочь хорошему человеку ул…

11.06.2010 10:16 ⚗нет
У многих кто реализует на сайтах теговость, рано или поздно встаёт вопрос о том, как же сделать выборку по нескольким тегам, ну и возможность отсеивать в выдаче, допустим, посты с нежелательными тегами.
У меня тут есть такая возможность. Например вам надо отфильтровать по тегам: просто geniyz.ru, или geniyz.ru но без тега развитие, или не просто развитие, а развитие + июнь, ну или вообще так: таро+развитие+июнь+тег-гадание-папесса.
Реализовать это довольно просто и можно множеством способов.
Вот моё решение в части логики:
  def show
@tags_plus = []; @tags_minus = [];
params[:id].gsub('_dot_','.').split('+').each do |tag|
j = tag.split('-')
if j.size==1
@tags_plus << j
else
@tags_plus << j[0]
@tags_minus << j[1..-1]
end
end
@tags_plus = Tag.find_all_by_name @tags_plus.flatten
@tags_minus = Tag.find_all_by_name @tags_minus.flatten
wheres = []
wheres << "POSTS_TAGS.TAG_ID IN ( #{@tags_plus.map{|t| "'#{t.id}'"}.join(',')} )" unless @tags_plus.empty?
wheres << "NOT EXISTS ( SELECT 1 FROM POSTS_TAGS WHERE POSTS_TAGS.POST_ID = POSTS.ID AND POSTS_TAGS.TAG_ID IN ( #{@tags_minus.map{|t| "'#{t.id}'"}.join(',')} ) )" unless @tags_minus.empty?
@posts = (Post.find_by_sql("SELECT POSTS.* FROM POSTS INNER JOIN POSTS_TAGS ON POSTS.ID = POSTS_TAGS.POST_ID #{ "WHERE #{wheres.join(' AND ')}" if wheres.size>0} ")).paginate :page => params[:page], :per_page => 13
end

Я решил не использовать возможности AR с целью увеличения скорости и ухода от лишних телодвижений при работе с массивом — я хочу получать сразу правильный результат.
Над визуализацией этого процесса пока думаю, и не исключено, что оставлю такую фичу для «избранных», не выводя функционал в нормальный вид, доступный для всех.