Rails 3 multi-part search - ruby-on-rails

I've spent a few days on this and just haven't been able to get my head around how to apply a scope or other method to this. I've also tried some search gems but because I'm at such a basic level, wanted to keep things as simple as possible. The effort below is loosely based on rails casts #37 "simple search" tutorial. Its the only one that's been marginally successful.
My problem; I want to run a search on year, make, model, engine(if any), drilling down to the desired vehicle(s). To make things easy on me, I did one search per page. Currently I'm not able to carry the previous search params over to the current search. I'm sure there are better ways of doing this than the one below, and I'm open to suggestions. I just haven't been able to successfully adapt examples I've found online.
The Database:
I have a postgres database table named "carinfo", that table has columns "id, caryear, carmake, carmodel, carengine, submodel, website1, website2, website3". I've populated it with some test data with a dozen or so vehicles.
controllers/listing_controller.rb
To simplify things I haven't used a model yet so its all in the controller:
class ListingController < ApplicationController
include ListingHelper
def year
#searchyr = Carinfo.find(:all)
end
def make
#searchmk = Carinfo.find(:all, :conditions => ['caryear LIKE ?', "%#{params[:year]}%"])
end
def model
#searchmdl = Carinfo.find(:all, :conditions => ['caryear LIKE ? AND carmake LIKE ?', "%#{params[:year]}%", "%#{params[:make]}%"] )
# '%2009%' static values work ok
end
def engine
#searcheng = Carinfo.find(:all, :conditions => ['caryear LIKE ? AND carmake LIKE ? AND carmodel LIKE ?', "%#{params[:year]}%", "%#{params[:make]}%", "%#{params[:model]}%"])
end
def selectedcar
#searchres = Carinfo.find(:all, :conditions => ['caryear LIKE ? AND carmake LIKE ? AND carmodel LIKE ? AND carengine LIKE ?', "%#{params[:year]}%", "%#{params[:make]}%", "%#{params[:model]}%","%#{params[:engine]}%"])
end
end
views/listing/year.html.erb
<% provide(:title, "Year") %>
<h1>Year Search - Under: Listing</h1>
<%= form_tag(make_path, :method => "get") do %>
<%= select_tag :year, options_for_select(#searchyr.collect{|y| [y.caryear, y.caryear]}.uniq), {:onchange => 'this.form.submit()'} %>
<% end %>
<!-- this can be deleted once everything is working it just helps see what's filtered -->
<ul>
<% for search in #searchyr %>
<li>
<%= search.caryear %>
<%= search.carmake %>
<%= search.carmodel %>
</li>
<% end %>
</ul>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
views/listing/make.html.erb
<% provide(:title, "Make Search") %>
<h1>Make Search - Under: Listing</h1>
<%= form_tag(model_path, :method => "get") do %>
<%= select_tag :make, options_for_select(#searchmk.collect{|y| [y.carmake, y.carmake]}.uniq), {:onchange => 'this.form.submit()'} %>
<% end %>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
views/listing/model.html.erb
<% provide(:title, "Model Search") %>
<h1>Model Search - Under: Listing</h1>
<%= form_tag(engine_path, :method => "get") do %>
<%= select_tag :model, options_for_select(#searchmdl.collect{|y| [y.carmodel, y.carmodel]}.uniq), {:onchange => 'this.form.submit()'} %>
<% end %>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
views/listing/model.html.erb
<% provide(:title, "Engine Search") %>
<h1>Engine Search - Under: Listing</h1>
<%= form_tag(selectedcar_path, :method => "get") do %>
<%= select_tag :engine, options_for_select(#searcheng.collect{|y| [y.carengine, y.carengine]}.uniq), {:onchange => 'this.form.submit()'} %>
<% end %>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
views/listing/selectedcar.html.erb
<% provide(:title, "Selected Car") %>
<h1>Selected Car - Under: Listing</h1>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
<ul>
<% for search in #searchres %>
<li>
<%= search.caryear %>
<%= search.carmake %>
<%= link_to search.carmodel, search_path(search) %>
</li>
<% end %>
</ul>
config/routes.rb
Just the section dealing with this problem:
match '/year', to: 'listing#year'
match '/make', to: 'listing#make'
match '/model', to: 'listing#model'
match '/engine', to: 'listing#engine'
match '/selectedcar', to: 'listing#selectedcar'
As always, help is greatly appreciated.
Thanks
Mike

First off, you're controller doesn't need all of those methods, do something like this:
class ListingController < ApplicationController
include ListingHelper
def search
#search = Carinfo.where('caryear LIKE ?', params[:year]) unless params[:year].blank?
#search = #search.where('carmake LIKE ?', params[:make]) unless params[:make].blank?
etc etc...
end
end
Then just have one form that has all of the inputs that you'd like to search

Related

Missing params when using a partial

let me start that I am new to rails, so far I have been able to solve all the issue I have had until now. I can confirm that my database is set and the relationships are working. Here is my issue, the app is similar to a project management tool. I have users that can create ski swaps and then search for vendors, then I render the results with javascript( ajax) so I dont have to reload the page. I added a badge so that I can use this to add the user as a vendor. As of right now I can get the user params no problem but the skiswap params I can't seem to get them to comeover I have tried. if I hardcode it it will work so I'm close but can not figure this out
Inside my
skiswap#index I have this for the search Above this I use #skiswap
<%= form_tag search_vendors_path, remote: true, method: :get do %>
<div class='form-group row'>
<div class ="input-group col-sm-3">
<%= text_field_tag :search, params[:search], placeholder: "Shop name, email, or contact...", autofocus: true, class: "form-control form-control-sm"%>
<div class="input-group-prepend">
<%= button_tag type: :submit, class: "btn btn-info btn-sm", id: "small-serach" do %>
<i class="fas fa-search" id = "search-icon"></i>
<% end %>
</div>
</div>
</div>
<% end %>
My search is working and this is what I have in the VendorController
def search
#users = User.where(["concat_ws(' ' , first_name, last_name, email, company ) ILIKE ?", "%#{params[:search]}%"])
respond_to do |format|
format.js{ render partial: 'skiswaps/result'}
end
end
My results are here and this is the badge I use to add new vendor, currently I have it hard coded because I cant figure it out. I am using j render for my results... I have tried skiswap_vendors_path(vendor: user, skiswap_id: #skiswap.id) also skiswap_vendors_path(vendor: user, skiswap: #skiswap) #skiswap is showing up as nil. Wasnt sure if it because my results are part of a partail, they dont seem to have the params that should be in show page.
<% #users.each do |user| %>
<tr>
<td><%= link_to "Add", skiswap_vendors_path(vendor: user, skiswap_id: 4),
class: "badge badge-success", method: :post %></td>
<td> <strong>Shop: </strong><%= user.company %> </td>
<td> <strong>Contact: </strong><%= user.first_name %> <%= user.last_name %>, <%= user.email%></td>
</tr>
<% end %>
Then in my VendorController I have this to create, which only works if I hardcode it
def create
vendor = User.find(params[:vendor])
skiswap = Skiswap.find(params[:skiswap_id])
skiswap.vendors.build(user_id: vendor.id)
if skiswap.save
flash[:notice] = "You add #{vendor.company} as a vendor"
else
flash[:notice] = "Sorry something went wrong, try again later"
end
end
This is what I have for routes
get 'search_vendors', to: 'vendors#search'
resources :skiswaps do
resources :vendors
end
I had to add in a hidden field tag to get the #skiswap.id through
<%= form_tag search_vendors_path, remote: true, method: :get do %>
....
<%= hidden_field_tag :skiswap_id, #skiswap.id %>
<% end %>

using acts_as votabable gem for likes and want to change the heart color to red permanently after user has liked

I am using the acts_as votable gem and I manage to change the heart color to red after a user has clicked on the heart by using javascript. However, once the server refreshes the heart goes gray again and there is no indication whether a user has liked the current post or not. How can I change the color permanently after a user has liked. My idea is to set a boolean to true in the vote table and then check that somehow in the view. But I am not sure how to implement it exactly. Any help would be much appreciated.
lists_controller.rb
def vote
if !current_user.liked? #list
#list.liked_by current_user
elsif current_user.liked? #list
#list.unliked_by current_user
end
vote.js.erb
<% if current_user.liked? #list %>
$('.fa-heart').addClass('liked');
<% else %>
$('.fa-heart').removeClass('liked');
<% end %>
$('.likes-count').html("<%= #list.get_upvotes.size %>")
show.html.erb
<div class="like">
<%= link_to like_list_path(#list), :class => "like-btn", method: :put, remote: :true do %>
<i class="fa fa-heart"></i>
<% end %>
<%= link_to "", "data-toggle" => "modal", "data-target" => "#likeModalLong" do %>
<span class="likes-count"><%= #list.get_upvotes.size %></span>
<% end %>
</div>
You can create a helper to make the liked css class persistent in you view:
application_helper
def liked_list(list)
liked = current_user.liked?(list) ? 'liked' : ''
content_tag(:i, '', class: "fa fa-heart #{liked}")
end
show.html.erb
<%= link_to like_list_path(#list), :class => "like-btn", method: :put, remote: :true do %>
<%= liked_list(#list) %>
<% end %>

ROR + Ransack: Filter with button or link_to

I have referenced these 2 stackoverflow posts, but i can't seem to get q[categories_name_cont] to be populated with "CategoryName" in my url: /articles/browse?utf8=✓&q[categories_name_cont]=&commit=CategoryName after i click the button named "CategoryName" for example.
1) Rails filter with button or link_to using Ransack
2) How to construct a clickable link with a scope using Ransack and Rails
browse.html.erb
<% #categories.each do |category| %>
<%= search_form_for #q, url: browse_articles_path, method: :get do |f| %>
<%= f.hidden_field :categories_name_cont %>
<%= f.submit category.name, :class => 'btn btn-primary', :onclick => "document.getElementById('q_categories_name_cont').value = '#{category.name}'" %>
<% end %>
<% end %>
articles_controller.rb
def browse
#q = Article.ransack(params[:q])
#articles = #q.result.includes(:categories, :users)
#categories = Category.with_articles.order('name ASC').all
end
UPDATE:
1) Hardcoding document.getElementById('q_categories_name_cont').value = "CategoryName" didn't result in this url either..
/articles/browse?utf8=✓&q[categories_name_cont]=CategoryName after i click the button named "CategoryName"
2) I ended up using the below method to pass parameters to the url:
<% #categories.each do |category| %>
<a class="btn btn-large btn-primary" href="/articles/browse?utf8=✓&q[categories_name_cont]=<%= category.name %>">
</a>
<% end %>
You need to manually fill that in.
<%= f.hidden_field :categories_name_cont, params[:q].try(:[], :categories_name_cont) %>
It can get quite annoying though. For this reason I have actually written a small gem for doing this automatically together with SimpleForm. If you want to take a look, then you can find it here:
https://github.com/kaspernj/simple_form_ransack

Error nested link in Rails

I have a little problem of link.
I have 2 models nested, one Faqcategoryand Faq.
The route is
resources :faqcategories, :path => 'faqs' do
resources :faqs, :path => 'question'
end
I can display all the "faqcategories" at http://localhost:3000/faqs/
and all the faqcategory as "questions" at http://localhost:3000/faqs/8
But when I want to go on the show of the question at http://localhost:3000/faqs/8/question/1 , it sends me at http://localhost:3000/faqs/1/question/8
I have set up the view like that:
<% #faqs.each do |question| %>
<%= link_to question.title, faqcategory_faq_path(question), class: "btn btn-rose btn-round" %>
<% end %>
In the FaqcateroriesController the "show" is set up like that:
def show
#faqs = #faqcategory.faqs
end
How do you think I can solve that?
I have found the solution.
<% #faqcategory.faqs.each do |question| %>
<%= link_to question.title, faqcategory_faq_path(question.faqcategory_id, question), class: "btn btn-rose btn-round" %>
<% end %>
It was missing "question.faqcategory_id"

Rails multiple form_tag paths/implement global search

I have a similar question to this but still can't figure it out.
I am creating a rails app linked to a Neo4j database and have a number of models I want to search across with one search form. I am using elastic search.
My current code for searching within one model (works fine):
#/app/views/symptoms/index.html
<%=form_tag symptoms_path, class: "form-inline", method: :get do %>
<div class="form-group">
<%= text_field_tag :query, params[:query], class: "form-control" %>
<%= submit_tag "Search", class: "btn btn-primary" %>
<% if params[:query].present? %>
<%= link_to "clear" %>
<% end %>
</div>
<% end %>
#/app/controllers/symptoms_controller.rb
def index
if params[:query].present?
#symptoms = Symptom.search(params[:query], show: params[:show])
else
#symptoms = Symptom.all
end
end
Currently this will only search within the symptoms model. I want to to create a 'global search' field that will search within the symptoms_path, allergies_path, and drugs_path.
Potential 'Global Search' code:
#/app/views/global_search/index.html
<%=form_tag [symptoms_path, allergies_path, drugs_path], class: "form-inline", method: :get do %>
<div class="form-group">
<%= text_field_tag :query, params[:query], class: "form-control" %>
<%= submit_tag "Search", class: "btn btn-primary" %>
<% if params[:query].present? %>
<%= link_to "clear" %>
<% end %>
</div>
<% end %>
#/app/controllers/symptoms_controller.rb
def index
if params[:query].present?
#allergies = Allergy.search(params[:query], show: params[:show])
#drugs = Drug.search(params[:query])
#symptoms = Symptom.search(params[:query])
else
#allergies = Allergy.all
#drugs = Drug.all
#symptoms = Symptom.all
end
end
Any ideas for how I could implement this? Thanks in advance!
I'd probably suggest that you create something like a "search_controller" (rails generate controller search should help you do that). In there you can have an index action (or whatever you want to call your action) and then you just set up a route to point a URL to it such as this:
# config/routes.rb
# Link the URL to the search controller's `index` action
post '/search/:query' => 'search#index'
# app/controllers/search_controller.rb
def index
if params[:query].present?
#allergies = Allergy.search(params[:query], show: params[:show])
#drugs = Drug.search(params[:query])
#symptoms = Symptom.search(params[:query])
else
#allergies = Allergy.all
#drugs = Drug.all
#symptoms = Symptom.all
end
end
Sorry if I'm misunderstanding, I'm not sure how much you've worked with Rails before

Resources