在Ruby on Rails中搜索MongoDB中的两个条件

时间:2012-12-31 10:49:21

标签: ruby-on-rails ruby mongodb mongoid

我正在使用rails cast video http://railscasts.com/episodes/240-search-sort-paginate-with-ajax。 我必须使用两个条件来搜索我的数据库。

# In my form for search 
<%= form_tag products_path, :method => 'get', :id => "products_search" do %>
  <p>
    <%= text_field_tag :search, params[:search] %>
    <%= submit_tag "Search", :name => nil%>
  </p>

对于一个条件,这很好用:

# In my model product.rb
def self.search(search)
  if search
    where(name: /#{Regexp.escape(search)}/i) 
  else
    scoped
  end
end

# In my controller products_controller.rb
@products = Product.search(params[:search]).page(params[:page]).per(5)

现在我必须使用另一个参数role进行搜索。我在我的产品模型中有角色字段。角色是1,2,3。如果给出了角色,那么它应该搜索具有给定输入角色的字符串,否则只搜索名称。

def self.search(search,role)
            if search
where(name: /#{Regexp.escape(search)}/i)(and role: should be equal to value of role)

另外,我应该在products_controller.rb中做些什么更改?在我上面的搜索表单中?

3 个答案:

答案 0 :(得分:2)

不确定role是否属于您的产品型号,但如果是,

def self.search(paramsname, role = nil) 
  if role
    @products = Product.where(:name => Regexp.new(name, true), :role => role)
  else
    @products = Product.where(:name => Regexp.new(name, true))
  end
end

答案 1 :(得分:2)

将字段添加到表单中:

<%= form_tag products_path, :method => 'get', :id => 'products_search' do %>
  <p>
    <%= text_field_tag :search, params[:search] %>
    <%= select_tag :role, options_for_select([1, 2, 3]) %>
    <%= submit_tag 'Search', :name => nil %>
  </p>
<% end %>

在控制器中使用新的:role参数:

@products = Product.search(params[:search], params[:role])
                   .page(params[:page]).per(5)

在产品型号中使用新的role参数:

def self.search(search, role)
  q = scoped
  if search
    q = q.where(:name => Regexp.new(name, true))
  end

  if role
    q = q.where(:role => role)
  end
  q
end

答案 2 :(得分:2)

我没有测试它,但看着你的问题,似乎你需要更好地分开责任。考虑到这一点,您可能更容易将这些搜索过滤器隔离在单独的类上。

我想出了这个:

    class SearchService
        def self.perform_search(params, klass)
            search = klass.scoped
            search = search.where(:name => Regexp.new(params[:name], true)) if params[:search]
            search = search.where(:role => params[:role]) if params[:role]
            search      
        end
    end

也许有些东西不正确,但我认为你可以理解。

因此,在您的控制器中,您只需将其用作:

    SearchService.perform_search(params, Product)

它仍然不是很好抽象,但我认为这是一种更容易和更好的方法来进入这一思路。

希望这有帮助。