有没有更好的方法来编写这个named_scope? [导轨]

发布于 2024-09-17 06:32:55 字数 1572 浏览 5 评论 0原文

我正在使用此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_ 语法将两个范围连接在一起。 :keywordsscope_procedure 查找与 product.descriptionproduct.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 %>

I am using this named_scope to search for products that have a description matching any word the user inputs.

E.g., Product.description_like_any("choc pret")

Will return products with names like

  • "Chocolate Bar"
  • "Chocolate Covered Pretzels"
  • "Miniature Chocolate Ponies"

Here's the named_scope I've written (which works)

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)

Is there a better way to write this? Perhaps I'm missing a Rubyism/Railism or two?

Solution

Using scope_procedure in conjunction with Searchlogic, this can be done in an even easier way. Note, the solution before even leverages Searchlogic's _or_ syntax for connecting two scopes together. The :keywords scope_procedure finds products matching product.description, or product.vendor.name; All with one text field!

Model

# 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

Controller

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

Views

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

药祭#氼 2024-09-24 06:32:55

最Railsy 要做的事情就是不要自己写这个。 :-) 使用优秀的 Searchlogic gem 它将创建 description_like_any 范围你。

编辑:如果您希望用户能够在这样的自由文本字段中输入搜索词,您可以定义自己的范围:

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

The most Railsy thing to do is to not write this yourself. :-) Use the excellent Searchlogic gem which will create the description_like_any scope for you.

Edit: If you want your user to be able to enter search terms in a free text field like this, you can define your own scope:

class Product < ActiveRecord::Base
   # ...
   scope_procedure :description_like_any_term, lambda { |terms| 
     name_like_any(terms.split(/\s+/))
   }
   # ...
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文