I am using metasearch. I want to search for friends using email.
In my users controller:
def index
#search = User.search(params[:search])
#users = #search.all
end
In my view:
<%= form_for #search do |f| %>
<div class="prepend-top field">
<%= f.label("Primary email address") %></br>
<%= f.text_field(:email_matches) %>
</div>
<div class="prepend-top field">
<%= f.label("School email address") %></br>
<%= f.text_field(:school_email_matches) %>
</div>
<div>
<ul>
<% if params[:search].blank? %>
Your search results here.
<% else %>
<% #users.each do |user| %>
<li class="box round">
<%= user.name %></br>
</li>
<% end %>
<% end %>
</ul>
</div>
The way it is now, the results are displayed on an adjacent column on the same page. I am trying to have it so that if the search form is blank then it returns a blank search.
Problems:
When I go to the page initially, the search results side is blank and does say "Your search results here". But, when I just click on the search button without putting anything in the search fields, it returns a list of all the users on the search result column. How do I make it so that a blank search form truly returns a blank page?
How do I go about making it so that it shows "No results for your search criteria"? if there are no matches for the particular search?
Thanks.
Part of your problem is happening because when you search for an empty string, your search function returns all your users.
So, in your controller, you could do:
def index
if params[:search]
empty_search = params[:search].keep_if {|k, val| !val.blank?}.empty?
else
empty_search = true
end
if empty_search
# no search was submitted, or search params are all blank
#search = ""
#users = []
else
# a search was submitted
#search = User.search(params[:search])
#users = #search.all
end
end
(not sure about the exact terminology for the condition, but basically, if you're passing an empty string or nothing, you should run the 'else' piece of the code).
In the view, you could do:
<% if #search.blank? %>
Your search results here.
<% else %>
<% if #users.blank? %>
No results for you
<% else %>
<ul>
<% #users.each do |user| %>
<li class="box round">
<%= user.name %></br>
</li>
<% end %>
</ul>
<% end %>
</ul>
Would that work?
Related
I have a products page that is filterable with pg_search gem. What I would like to do is create a breadcrumb that lists the search params onto the page.
If my search url looks like http://127.0.0.1:3000/products?utf8=%E2%9C%93&query=modern&query=stone&query=limestone&commit=Search I would like to print modern stone limestone to the page.
products_controller.rb
def index
#products = if params[:query]
#albums = Album.where(name: params[:query])
Product.search_for(params[:query])
else
#albums = Album.where(name: 'products')
Product.order(:name)
end
end
index.html.erb
This is what I tried, but realized that it lists ALL the tags, which I only need the tags that are part of the search params
<ul class="product-index-breadcrumb">
<% #products.each do |p| %>
<% p.tags.each do |t| %>
<li><%= t.name %></li>
<% end %>
<% end %>
</ul>
You need to modify your URL e.g array string adding [] if you keep this then it only without [] then it takes only last value like limestone,
after modification URL then it will look like this http://http://127.0.0.1:3000/products?utf8=%E2%9C%93&query[]=modern&query[]=stone&query[]=limestone
then if you write like
<%= params[:query] %>
it will return
["modern", "stone", "limestone"]
now you can run a loop like
<ul>
<% params[:query].each do |query_params| %>
<li><%= query_params %></li>
<% end %>
</ul>
then output is
modern
stone
limestone
In my rails category show controller for categories I have it setup like this
def show
#categories = Category.find_by(params[:name])
end
But when I visit this controller it returns all records of products found in the category instead of single category.
Here is the code in my view controller for category
<div class="grid">
<% #categories.products.each do |product| %>
<%= link_to product_path(id: product.slug, category_name: product.category.name), class: "card" do %>
<div class="product-image">
<%= image_tag product.productpic.url if product.productpic? %>
</div>
<div class="product-text">
<h2 class="product-title"> <%= product.name %></h2>
<h3 class="product-price">£<%= product.price %></h3>
</div>
<% end %>
<% end %>
</div>
What am i doing wrong here?
First of all, for security purposes, you should never trust the params hash to retrieve records. Rails will "make the data safe" if you use a hash as your arguments. Use this code below:
def show
#category = Category.find_by(name: params[:name])
end
Second, usually on a show page, you only want to retrieve one record and therefore the variable should be named as singular. I corrected that above.
Third, it helps if you use proper indenting when posting examples. It makes it easier for us to help you.
Fourth, the line below (I changed #categories to #category) is basically saying: "Now that I have this single category, find all the products associated with it in the products table and put them into the |product| variable for iteration"
<% #category.products.each do |product| %>
I'm not sure what you want to do with the category, but if you keep this line of code, it will always show you all the products. Maybe you only want to show the most recent 3, in which case you could do something like this:
In your controller:
def show
#category = Category.find_by(name: params[:name])
#recent_products = #category.products.order(created_at: :desc).limit(3)
end
In your view:
<div class="grid">
<% #recent_products.each do |product| %>
<%= link_to product_path(id: product.slug, category_name: product.category.name), class: "card" do %>
<div class="product-image">
<%= image_tag product.productpic.url if product.productpic? %>
</div>
<div class="product-text">
<h2 class="product-title"> <%= product.name %></h2>
<h3 class="product-price">£<%= product.price %></h3>
</div>
<% end %>
<% end %>
</div>
You can do this way
in your controller you can write this code
def show
#category = Category.find_by_name(params[:name])
end
and in your view it will work
<div class="grid">
<% #category.products.each do |product|%>
// place your code what you want to display
<% end %>
</div>
I hope it would help you and still if you have any concern please let me know.
I have spent hours on this single problem, I am desperate for help.
The below html displays the correct car name and the car.manufacture_id displays the correct manufacture id, except I need to display manufacture.name and can not figure out how to do that. How do I display car.manufacture.name?
search.html.erb
<% #cars.each do |car| %>
<%= car.manufacture_id %>
<%= link_to car.name, manufacture_path(car.manufacture_id) %>
<% end %>
search_controller.rb
def search
if params[:q].nil?
#cars = []
#manufactures = []
else
#cars = Car.search params[:q]
#manufactures = Manufacture.search params[:q]
end
end
What do your car and manufacture models looks like, can you show the code for them? The schemas would help too. If your models are setup right car.manufacture.name should have worked.
If you do
<% #manufactures.each do |manufacture| %>
<%= manufacture.id %>
<%= manufacture.name %>
<% end %>
Does this work?
Also this might work, if the manufacturers are being found by Manufacture.search params[:q]
<%= #manufactures.find(car.manufacture_id).name %>
or if they are not
<%= Manufacture.find(car.manufacture_id).name %>
I am using Ransack to add a simple search form on my homepage. I would like the results of the search to show on a different page, instead of on the homepage.
The HomeController has an index action with the #search variable set as follows
def index
#search = User.search(params[:q])
#users = #search.result
end
The view contains
<%= search_form_for #search do |f| %>
<fieldset>
<legend>User</legend>
<ul>
<li>
<%= f.label :first_name_or_last_name_cont %>
<%= f.text_field :first_name_or_last_name_cont %>
</li>
<li>
<%= f.label :email_cont %>
<%= f.text_field :email_cont %>
</li>
</ul>
</fieldset>
<fieldset>
<legend>User's Posts</legend>
<ul>
<li>
<%= f.label :posts_title_cont %>
<%= f.text_field :posts_title_cont %>
</li>
</ul>
</fieldset>
<%= f.submit %>
<% end %>
<%= render 'results' %>
How can I set up the controller so that I can use <%= render 'results' %> in a different view for a different action, say a search action? How can I do this so that when I submit the search form I am directed to a new page for the search action which displays the search results?
Great question! To answer your question, you can create a private method with a redirect_to a different page (that has <%=render 'results' %>) IF search params are passed in your HomeController.
class HomeController < ApplicationController
before_action :search
def index
#search = User.search(params[:q])
#users = #search.result
end
private
def search
if params[:q]
search_params = CGI::escapeHTML(params[:q])
redirect_to (url --> see below how to get the url)
end
end
end
However, if you want to start building out your app, you want your search results to display on that dedicated page, no matter where you are at in the app. I am pasting in a full answer from a small rails app. The code is only slightly different (form_tag instead of search_form_for), but I know it works, so hopefully it will help you.
Below, is a nav bar partial that is displayed across the app and then the relevant code for the home page and the ListingController index action. If search params are passed, then index.html.erb renders the #listings partial (_listing.html.erb) and nothing below the <% else %> tag on the home page.
_navigation.html.erb
<%= form_tag search_path, :method => :get do %>
<div class="form-group">
<%= text_field_tag :search, params[:search], class: "form-control", placeholder: "Search" %>
</div>
<%= submit_tag "Submit", :name => nil, :class => "btn btn-primary" %>
<% end %>
index.html.erb
<% if params[:search] %>
<h2>Search Results</h2>
<%= render #listings %>
<% else %>
...what usually shows up on my home page with no search results.
<% end %>
listings_controller
def index
#listings = Listing.search(params[:search])
end
routes.rb
get 'search' => "listings#search"
This works great. However, if I am in a different view/controller, like the one showing all the categories, and try to search, then it basically searches the current page. So, I added the following to the categories controller:
categories_controller
before_action :search
......
private
def search
if params[:search]
search_params = CGI::escapeHTML(params[:search])
redirect_to ("/listings?utf8=%E2%9C%93&search=#{search_params}")
end
end
BUT, for your specific app, to get the search to redirect to the home page and display the search results, first do a search on your home page and see what is generated in the url. Let's say I typed 'cheese' (/listings?utf8=%E2%9C%93&search=cheese). Notice the %E2%9C%93...you may not see this b/c this normally displays as a check in the url on your browser (http://unicode-search.net/unicode-namesearch.pl?term=mark)...so just paste it into text wrangler or stackoverflow text area to get the 'full url' like above. Then at the end of the url, just replace what you typed into the search box with #{search_params}.
This passes whatever was typed into the search box to your dedicated search results page (in my case index.html.erb)!
Here is some documentation on CGI escapeHTML (for security reasons): http://ruby-doc.org/stdlib-2.0/libdoc/cgi/rdoc/CGI.html#method-c-escapeHTML
I want to order users by descending. However, when I add .reverse it reverses the users a page at a time, not all together.
show_followers:
<%= render #users.reverse %>
<%= will_paginate %>
Users/_user:
<%= link_to user.name, user %>
<% unless #user.nil? %>
<% if request.path == "/users/#{#user.id}/listening_to" %>
<br/>
<span id="member_since"><%= "Listening Since" %> <%= #user.relationships.find_by_followed_id(user.id).created_at.strftime("%b. %d, %Y") %></span>
<% end %>
<% if request.path == "/users/#{#user.id}/listeners" %>
<br/>
<span id="member_since"><%= "Listener Since" %> <%= user.relationships.find_by_followed_id(#user.id).created_at.strftime("%b. %d, %Y") %></span>
<% end %>
<% end %>
Controller:
#users = #user.followed_users.paginate(page: params[:page])
It seems Rails intelligently orders by the relationships_create like I wanted but it's in ascending order. I want the most recent follower to show up on the top of the list.
In the controller action, you probably have some code that looks something like this: #users = User.paginate(:page => params[:page]).
You need to put the reverse in that statement, so it looks like this: #users = User.paginate(:page => params[:page]).order('id DESC') (perhaps with id replaced by created_at).
#users = #user.followed_users.reverse.paginate(page: params[:page])
Reverse at the controller level prior to pagination