pwz2000
pwz2000

Reputation: 1395

setting up search model to wrap around user model

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)

Upvotes: 0

Views: 215

Answers (1)

mind.blank
mind.blank

Reputation: 4880

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.

Upvotes: 1

Related Questions