2

I am using rails cast video http://railscasts.com/episodes/240-search-sort-paginate-with-ajax . I have to use two conditions to search in my database.

# 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>

For one condition, this works fine:

# 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)

Now I have to search with another parameter, role. I have role field in my product Model. role is 1,2,3. If role is given then it should search string with given input role, else only search with name.

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

Also, what changes should I do in my products_controller.rb? And in my above search form?

Andrew Haines
  • 6,574
  • 21
  • 34
regmiprem
  • 735
  • 2
  • 14
  • 41

3 Answers3

2

Not sure if role is part of your Product model or not, but if so:

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
jbnunn
  • 6,161
  • 4
  • 40
  • 65
  • 1
    You can use `Regexp.new(name, true)` rather than the interpolated form, which is a bit cleaner. – Chris Heald Jan 01 '13 at 19:37
  • It gives me error can't convert nil into String.. Also i want this in my previous model formate like if search where(name:...) and yes role is the part of my modle. I have role field in my product collection. In my controller @products = Product.search(params[:search]) Here also i have to add params role also. How can i add role also in search. For example i want to find data whose role is 1 and have string a..... – regmiprem Jan 02 '13 at 05:23
2

Add the field to your form:

<%= 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 %>

Use the new :role parameter in your controller:

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

Use the new role parameter in your Product model:

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
Andrew Haines
  • 6,574
  • 21
  • 34
Ross Allen
  • 43,772
  • 14
  • 97
  • 95
  • @regmiprem There was a slight mistake, it should have been `Product.search` in the controller, not `Product.where`. Does that fix it? It would be easier to help if you gave a bit more detail than "it is not working". – Andrew Haines Jan 04 '13 at 08:40
  • Also I think it should be `scoped` not `all` in the model - `all` returns an array, so you can't chain scopes onto it. – Andrew Haines Jan 04 '13 at 09:05
  • @AndyH IT is not working .. It does not give me error also. Here I want to search role which has option(1,2,3) with name field starts from string in params search. It will ne by day if u provide me working example – regmiprem Jan 04 '13 at 11:46
2

I didn't test it, but looking at your problem, it seems that you need to better separate the responsibilities. With that in mind, it may be easier for your to isolate those search filters on a separate class.

I came up with this:

    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

Maybe some stuff are not correct, but I think you can get the idea.

So in your controller, you just need to use that as:

    SearchService.perform_search(params, Product)

It's still not very nice abstracted, but I think it's an easier and better approach to go into that line of thought.

Hope this helps.

Nicholas Pufal
  • 2,175
  • 20
  • 23
  • You need to test it. I just wrote it without trying that code. Just so you could have the idea. It should be easy to make that work, though. Check if the params are the expected ones. Maybe you need to deal with those params. Just realized that I wrote params[:name] inside - maybe that should be params[:search]? – Nicholas Pufal Jan 10 '13 at 12:01