0

I was finally able to come up with some sort of structure for my advanced search. The idea is to have a search that pulls data from the User model. So I built a search model which will be a kind of wrapper around the user model. For example: when I say Search.search_for(options), in the search_for method it will use the options to search on the User model and return the results, which you can display on the page. I came up with this method as I was told I have to duplicate the values, but I figured I just need to make Search call the underlying (already existing) User model.

So I have a view from where users can search. I have to collect all the options they have specified that they want to search on (gender, age, zip code, do they have kids, religion and ethnicity). Collect the options and submit the form to SearchController.

I have the concept down, but am struggling with the execution since I am new to Rails. The code below is essentially what I have (minus User model as it's filled with other parts from app). I'm not sure how to finish the rest of the coding to pull this off.

Searches_controller:

  def new
    @search = Search.new
  end

  def create
    @search = Search.new(params[:search])
    if @search.save
      redirect_to @search
    else
      render 'new'
    end
  end

  def show
    @search = Search.find(params[:id])
    @users = Users.search(params)
  end
end

search model:

 attr_accessible :age, :children, :ethnicity, :gender, :religion, :zip_code

  def users
    @users ||= find_users
  end

  def self.search(params)

  end

private

def find_users
  users = User.order(:id)
  users = users.where(gender: gender) if gender
  users = users.where(:ethnicity => ethnicity) if ethnicity
end

new.html (advanced search page):

<%= form_for @search do |f| %>
<div class="field">
  <%= f.label :gender %><br />
  <%= f.select :gender, ['man', 'woman'], :include_blank => true %>
</div>

  <div class="field">
    <%= f.label :zip_code %><br />
    <%= f.text_field :zip_code %>
  </div>
  <div class="field">
    <%= f.label :children %><br />
    <%= f.select :children, ['Yes, they live with me', 'I want kids now', "I want one someday", "Not for me"], :include_blank => true %>
  </div>
  <div class="field">
    <%= f.label :religion %><br />
    <%= f.select :religion, ["Agnostic", "Atheist", "Christian", "Catholic", "Buddhist", "Hindu", "Jewish", "Muslim", "Spiritual without affiliation", "Other", "None", "Prefer not to say"], :include_blank => true %>
  </div>
  <div class="field">
    <%= f.label :ethnicity %><br />
    <%= f.select :ethnicity, ["Asian", "Biracial", "Indian", "Hispanic/Latin", "Middle Eastern", "Native American", "Pacific Islander", "White", "Other"], :include_blank => true %>
  </div>
  <div class="actions"><%= f.submit "Search" %></div>
<% end %>

show.html (view to show results):

<%= render @search.users %>

development log:

Started POST "/searches" for 127.0.0.1 at 2013-05-06 14:00:54 -0400
Processing by SearchesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"Pher65dG6gRU9NGgv2q1ot0cfjq+MELgXE6dOtvcrY0=", "search"=>{"gender"=>"", "zip_code"=>"", "children"=>"", "religion"=>"", "ethnicity"=>"Asian"}, "commit"=>"Search"}
  [1m[36m (0.2ms)[0m  [1mBEGIN[0m
  [1m[35mSQL (107.5ms)[0m  INSERT INTO `searches` (`age`, `children`, `created_at`, `ethnicity`, `gender`, `religion`, `updated_at`, `zip_code`) VALUES (NULL, NULL, '2013-05-06 18:00:54', 0, NULL, NULL, '2013-05-06 18:00:54', '')
  [1m[36m (60.1ms)[0m  [1mCOMMIT[0m
Redirected to http://localhost:3000/searches/25
Completed 302 Found in 276ms (ActiveRecord: 167.7ms)


Started GET "/searches/25" for 127.0.0.1 at 2013-05-06 14:00:54 -0400
Processing by SearchesController#show as HTML
  Parameters: {"id"=>"25"}
  [1m[35mSearch Load (0.5ms)[0m  SELECT `searches`.* FROM `searches` WHERE `searches`.`id` = 25 LIMIT 1
  [1m[36mUser Load (73.2ms)[0m  [1mSELECT `users`.* FROM `users` WHERE `users`.`zip_code` = '' AND `users`.`ethnicity` = '0' ORDER BY id[0m
  Rendered collection (0.0ms)
  Rendered searches/show.html.erb within layouts/application (81.4ms)
  [1m[35mUser Load (0.6ms)[0m  SELECT `users`.* FROM `users` WHERE `users`.`auth_token` = 'LTzif2q6921TM4pQzfmEGg' LIMIT 1
Completed 200 OK in 309ms (Views: 224.6ms | ActiveRecord: 74.3ms)
pwz2000
  • 1,385
  • 2
  • 16
  • 50
  • Are you getting any errors? Which part isn't working? Please add this information to your question. – mind.blank Apr 29 '13 at 13:52
  • That's the thing. I don't know where to go after what I have done above. That's as far as I was able to get so no there are no errors to come across as I haven't reach that stage yet. I am new to this and it took quite some time to come up with that game plan. So I need help with finishing it out so I can learn. – pwz2000 Apr 29 '13 at 13:54
  • At the end of your `find_users` add `users` to return the array, that might fix it. Also if you defined `@users` in your show action then just use `<%= render @users %>`, this will work if you have a `/users/_user.html.erb` partial. To see if the search has returned anything just dump it to the show view `<%= @users %>` – mind.blank May 02 '13 at 23:47
  • Since I had find_users in the model I decided to pass params in the controller as I figured that should help do the trick. So I added @users = Users.search(params) in def show. Then in model I think I should do def self.search(params). Then add code to it but I'm not sure what. I'm not even sure if I'm on the right track. Updated code with the latest. – pwz2000 May 03 '13 at 16:33
  • But you're saving those params to a model. If you're going to be passing params around then there's no reason to create a separate model! You could simply use a `GET` request with params in the URL for the search. – mind.blank May 03 '13 at 16:43
  • Well I'm just trying to think of ways to get the search results to display. I'm not a experience coder so I have just been brainstorming ways to finally get it showing. I can't seem to complete the coding though. What would the best method be? Scratch the entire params philosophy I came up with? – pwz2000 May 03 '13 at 16:45
  • 1
    Ok, here's what you should do: revert the code back to where it was with my answer, make sure there is `users` at the end of `find_users`. Create a search object through the form, go to your `rails console` and check that it saved correctly with all the attributes - then run the method `@search.users` on it in the console and see if it returns the users correctly. – mind.blank May 03 '13 at 16:48
  • That gives NoMethodError: undefined method `users' for nil:NilClass. – pwz2000 May 03 '13 at 19:39
  • I've updated my whole answer, if you still get errors please tell me. – mind.blank May 04 '13 at 02:54
  • 1
    ah ok was not doing console right. I'm still very new with the console and it's something I definitely need to get more comfortable with. Now it shows me what is going on with my code. My search was 'Asian' for ethnicity, and in the console it reads ethnicity` = '0'. Now I feel I can start making progress and get it to search properly. – pwz2000 May 04 '13 at 03:13

1 Answers1

1

Ok, first of all make sure that the User model and the Search model have exactly the same attributes, so gender, zip_code, children, religion and ethnicity.

The only time you would need to have differing column names is if you want to do something a bit more "complex", such as searching a range, for example if the users table has age, then the searches table might have min_age and max_age.

Searches controller:

def new
  @search = Search.new
end

def create
  @search = Search.new(params[:search])
  if @search.save
    redirect_to @search
  else
    render 'new'
  end
end

def show
  @search = Search.find(params[:id])
  @users = @search.users
end

Searches model:

def users
  users = User.order(:id)
  users = users.where(gender: gender) if gender
  users = users.where(zip_code: zip_code) if zip_code
  users = users.where(children: children) if children
  users = users.where(religion: religion) if religion
  users = users.where(ethnicity: ethnicity) if ethnicity
  users
end

In app/views/searches/show.html.erb:

<h1>Search results</h1>
<%= render @users %>

And make sure that you have the partial app/views/users/_user.html.erb with something like:

<p><%= user.name %> - <%= user.email %></p> # or whatever

Now go to the search form and create a new search object, get the ID from the URL (lets say it's 34). Then go into rails console and do:

@search = Search.find(34)
# should return something like: gender: "male", zip_code: nil, children: "Yes"..

# then try the users method:
@search.users

Not sure why your view isn't working. Make sure you have @users = @search.users in your searches controller under the show action, then go to views/searches/show.html.erb and do:

<% @users.each do |user| %>
  <p><%= user.name %></p>
<% end %>

And see if that works.

mind.blank
  • 4,820
  • 3
  • 22
  • 49
  • The search is for multiple fields. For example. Gender (woman, man), ages (18-79), child preference (kids, no kids, want kids), faith (christian, catholic, muslim, etc), ethnicity (asian, middle eastern, indian, etc). The searches will have a drop down box so you can choose which to search. Also the rails cast is not of assistance as it doesn't show how to fetch search results from another model which is what I am attempting to do (it only pulls search results from information directly on the search page). I need mines to go inside the user model. I'm still trying to work your method out above – pwz2000 Apr 29 '13 at 14:53
  • Ok so when I do users = users.where(ethnicity: ethnicity) if ethnicity. I should also list all the options for ethnicity correct? Or does doing ethnicity: automatically pull all of it? Your code does make sense to me. Also I added my User form as it should've been included the first time so people can see what he form fields are and how it was done. – pwz2000 Apr 29 '13 at 15:19
  • Search results return blank. I will post my updated code. Check edit – pwz2000 May 02 '13 at 19:34
  • I was able to remove nil from search options. Easy fix, when I created search model I did integer when all options were suppose to be strings as is in the User model. So now if I perform a search in console it will display the search results correctly. Though the search results from app still shows blank. So something is incorrect with the show.html page with rendering results. When I view page source it shows nothing under search results too. – pwz2000 May 06 '13 at 18:59
  • Actually `nil` is good for the search, that's how the code in `Search#users` works. `nil` evaluates to `false` in an `if` statement. Try the following in your console: `puts "hi" if nil`, then swap `nil` for `false`, `true`, `""`, `" "`, `0`, `" ".blank?` and `" ".present?` - then you'll see how it works. – mind.blank May 07 '13 at 01:29
  • Well for this situation I had to get nil removed as it was not pulling data since I had integers created as oppose to the correct method which were strings. I get what you're saying that as I have come across that previously. Any ideas how to get search results page to show the results as oppose to a blank page? since now we know I have the correct code for fetching results. – pwz2000 May 07 '13 at 03:08
  • It would be easier to update your table columns to work correctly than changing the output every time: http://stackoverflow.com/questions/2799774/rails-migration-for-change-column - so for example `change_column :searches, :ethnicity, :string, default: nil`. It's weird since if you copy pasted the code from my answer then it should work... I'll update my answer with something you can try. – mind.blank May 07 '13 at 03:14
  • That does not work. I tried something similar prior to seeing your code also which was, <% render @search.users.each do |user| %> <%= user.email %> <% end %>. Perhaps it's my /views/users/_user.html that is the problem. – pwz2000 May 07 '13 at 13:45
  • `<% render @search.users.each do |user| %>` wouldn't work, get rid of the `render`. – mind.blank May 07 '13 at 14:00
  • Still wouldn't show without render. I tried to debug the view with <%= debug @search.users %> in the show. I also added logger.info "SEARCH: #{@search.inspect} USERS: #{@search.users.inspect}" to the controller. I just edited posting with the development log. It's outputting 0 for ethnicity in the view, but not in the console. – pwz2000 May 07 '13 at 14:18