views:

58

answers:

4

Hi,

Here is the code of a "simple search form" (thanks to jordinl) which I try to improve. I would like to add the case if there is no match found.

So, there is the view (views/users/index.html.erb)

<% form_tag users_path, :method => 'get' do %>
  <%= text_field_tag :search, params[:search] %>
  <%= submit_tag "Search", :name => nil %>
<% end %>

<% @users.each do |user| %>  
  <p><%= link_to "#{user.name}", user %></p>
.
.
.
<% end %>

The controller ( users_controller.rb)

def index
  @users = User.search(params[:search])
end

and the method in user model:

def self.search(search)
  search.blank? ? [] : all(:conditions => ['name LIKE ?', "%#{search.strip}%"])
end

I tried the following:

def self.search(search)
  if search.to_s.size < 1
    []
  else
    if  @users.size > 0
      all(:conditions => ['name LIKE ?', "%#{search.strip}%"])
    else
      render :text => "No result found"
    end
  end
end

reporting the following error: "You have a nil object when you didn't expect it!..." (no instance in the array). Then, I tried to add

<% if @users? %>
  <% @users.each do |user| %>
.
.
.

In the view. But it doesn't work either.

I would be pleased to understand why I'm wrong on this. Thank you!

+1  A: 

Hi,

you can't render in your model.

In your view:

<% form_tag users_path, :method => 'get' do %>
  <%= text_field_tag :search, params[:search] %>
  <%= submit_tag "Search", :name => nil %>
<% end %>

<% if @users.empty? %>
  No records found!
<% else %>
  <% @users.each do |user| %>  
    <p><%= link_to "#{user.name}", user %></p>
  <% end %>
<% end %>

In your model:

def self.search(search)
  search.blank? ? [] : all(:conditions => ['name LIKE ?', "%#{search.strip}%"])
end
sled
Thank you, but there is a slight problem, if the user doesn't use the search, the view render "No records found!". It's for that I tried to use if search.to_s.size < 1 and if @users.size > 0 and tried to implement it in the model. Can I use a param (search) in the view?Thanks you
benoitr
Using `unless` with an `else` is bad scene. Why not just flip them and use an `if`? Double-negatives are confusing. The second condition is "unless unless users array is empty".
tadman
+1  A: 

You are close with your check on @users? but it should be:

<% if [email protected]? %>
  <% @users.each do |user| %>
    ...
  <% end %>
<% else %>
  No users found.
<% end %>

This will work with your original self.search implementation which, correctly, is used just to find users and does not need to worry about reporting if none are found.

Shadwell
Thanks for your answer which is very similar to the first one. However, there is still a minor problem I address to Sled. I would be pleased to have your point of view. Thank you!
benoitr
A: 

Your self.search method should return an array, either full or empty. Try:

in you model

def self.search
  self.all(:conditions => ['name LIKE ?', "%#{search.strip}%"])
end

and in your view

  <% if @users? %>
    <% @users.each do |user| %>
      …
    <% end %>
  <% else %>
    No result
  <% end %>
Yannis
I don't think `@users?` will work as you intend.
tadman
Indeed! It should have been <% if [email protected]? %> :-(
Yannis
+1  A: 

You're on the right track. Try this:

<% if (@users) %>
  <% if (@users.empty?) %>
    <p>No users found.</p>
  <% else %>
    <% @users.each do |user| %>  
      <p><%= link_to "#{user.name}", user %></p>
    <% end %>
  <% end %>
<% else %>
   <p>Use the search form to search for stuff.</p>
<% end %>

Change your search method to only return something if searching was used:

def self.search(search)
  search.present? and all(:conditions => [ 'name LIKE ?', "%#{search.strip}%" ])
end
tadman
Thanks for your kind help! Regards
benoitr
This is such a common pattern you could always make a helper for it if you're a fan of such things.
tadman