Есть ли лучший способ написать этот named_scope?[Rails] - PullRequest
0 голосов
/ 06 сентября 2010

Я использую этот named_scope для поиска продуктов, описание которых соответствует любому слову, введенному пользователем.

Например, Product.description_like_any("choc pret")

Вернет продукты с именами, такими как

  • «Шоколадный батончик»
  • «Шоколадные крендели»
  • «Миниатюрные шоколадные пони»

Вот я написал named_scope (который работает)

named_scope :description_like_any, (lambda do |query|
  return {} unless query
  conditions = []
  values = []
  for q in query.split(/\s+/)
    conditions << "(`products`.description LIKE ?)"
    values << "%#{q}%"
  end
  { :conditions => [conditions.join(' AND '), *values] }
end)

Есть ли лучший способ написать это?Возможно, мне не хватает Rubyism / Railism или двух?

Решение

Используя scope_procedure в сочетании с Searchlogic, это можно сделать еще проще.Обратите внимание, что решение до этого даже использует синтаксис Searchlogic _or_ для соединения двух областей.:keywords scope_procedure находит продукты, соответствующие product.description или product.vendor.name;Все с одним текстовым полем!

Модель

# app/models/product.rb
class Product < ActiveRecord::Base
  scope_procedure :keywords, lambda |query|
    description_like_any_or_vendor_name_like_any(query.split(/\s+/))
  end
end

Контроллер

# app/controllers/products_controller.rb
class ProductsController < ApplicationController
  def index
    @search = Product.search(params[:search])
    @products = @search.all
  end
end

Просмотры

# app/views/products/index.html.erb
<% form_for @search do |f| %>
  <%= f.label :keywords, "Quick Search" %>
  <%= f.input :keywords %>
  <%= f.submit, "Go" %>
<% end %>

1 Ответ

3 голосов
/ 06 сентября 2010

Самое крутое, что нужно сделать - это не писать это самостоятельно. :-) Используйте превосходный камень Searchlogic , который создаст для вас область description_like_any.

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

class Product < ActiveRecord::Base
   # ...
   scope_procedure :description_like_any_term, lambda { |terms| 
     name_like_any(terms.split(/\s+/))
   }
   # ...
end
...