Reputation: 1395
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
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