Ransack search for integer and string values from single search field - ruby-on-rails

I am using Rails 4 with Ransack.
I cant make to work searching for integer and string values.
So far I tried this code.
In view:
<%= search_form_for #search do |f| %>
<div class="field">
<%= f.label :name_cont, "Nepieciešama meklēšāna pēc ID, vārda un telefona nr" %>
<%= f.text_field :name_or_phone_number_cont_or_id_eq, :placeholder => 'Meklēt pēc ID,vārda vai tel.nr.' %>
</div>
<div class="actions"><%= f.submit "Search" %></div>
<% end %>
In controller :
def index
#search = Advertisement.search(params[:q])
#advertisements = #search.result
respond_with(#advertisements)
end
This gives me error:
undefined method `name_or_phone_number_cont_or_id_eq' for
Is there any workaround to this problem?
Or I need to convert id to string for search purposes ?
Thanks in advance.

you need to add the code to your model, for you to be able to search for string and integer.
ransacker :id do
Arel.sql("to_char(\"#{table_name}\".\"folio\", '99999999')")
end

Related

I'd like to add radio buttons to the Rails search function to allow narrowing the search

What I want to come true
I want to implement a search function using radio buttons. I want to be able to narrow down the search using radio buttons and search words.
I've gotten as far as how to implement search, but I can't figure out how to narrow it down with radio buttons. I would like to know how to do this.
code
View
<div class="form">
<%= form_with url: search_path, method: 'get' do |form| %>
<div class="search">
<%= form.text_field :search %>
<%= form.submit "Search" %>
</div>
#I don't know how to send the value of a radio button.
<div class="radio">
<%= form.label :search_check_box,"all", {value: :all} %>
<%= form.radio_button :search_check_box, :all %>
<%= form.label :search_check_box,"public", {value: : public} %>
<%= form.radio_button :search_check_box, :public %>
<%= form.label :search_check_box,"not_ public", {value: :not_ public} %>
<%= form.radio_button :search_check_box, :not_publick %>
</div>
<% end %>
</div>
controller
def search
#movies = Movie.search(params[:search])
end
model
class Movie < ApplicationRecord
def self.search(search)
if search
Movie.where('name LIKE ?', "%#{search}%")
else
Movie.all
end
end
end
You're falling to the classic trap of using a single class (Movie) to do way too much. Create a separate model to use to wrap the logic for searching:
class MovieQuery
include ActiveModel::Model
include ActiveModel::Attributes
VISIBILITY_OPTIONS = ["all", "public", "private"]
attribute :name
attritute :visiblity
def to_scope(base: Movie.all)
base.tap do |b|
b = base.where('name LIKE ?', "%#{ name }%") if name.present?
b = base.where(visiblity: visiblity) if ["public", "private"].include?(visiblity)
end
end
end
This model is not saved to the database - it simply serves to bind the user input to an object and apply the search filters. Its also the local place to add stuff like validations.
Then bind the form to your model:
<%= form_with model: #movie_query || MovieQuery.new, url: search_path, method: 'get' do |form| %>
<div class="search">
<%= form.label :name, 'Search by name' %>
<%= form.text_field :name %>
</div>
<div class="radio">
<%= form.label :visiblity %>
<%= form.collection_radio_buttons :visiblity,
MovieQuery::VISIBILITY_OPTIONS,
:itself,
:humanize
%>
</div>
<div class="actions">
<%= form.submit 'Search' %>
</div>
<% end %>
collection_radio_buttons is really meant to be used with objects (models) and the third and forth arguments are the text and label methods called on each object in the collection. By using itself and humanize you can use it with a simple array.
Then setup your controller to bind the inputs back to the model:
class MoviesController
def search
#movie_query = MovieQuery.new(search_parameters)
#movies = #movie_query.to_scope
end
private
def search_parameters
params.fetch(:movie_query) # its an optional parameter
.permit(:name, :visibility)
end
end

Retain checkbox value on page reload in form_with in Rails 5

I have a form created using form_with. What I need is to retain the values submitted using that form after page reload. I am able to save the value of text_field but not the value of check_box. What should I change in my code so that I can achieve the same?
html.erb
<%= form_with url: search_path,
id: :search_by_filter,
method: :get, local: true do |f| %>
<div>
<p><strong>Search by Name</strong></p>
<%= f.label 'Name' %>
<%= f.text_field :name, value: params[:name] %>
</div>
<br>
<div>
<%= label_tag do %>
<%= f.check_box :only_students, checked: params[:only_students] %>
Show only students
<% end %>
</div>
<br/>
<div class="submit_button">
<%= f.submit :Search %>
</div>
<% end %>
controller.rb
def get_desired_people(params)
people = Person.includes(:country, :state, :university).order(id: :desc)
people = people.where(is_student: params[:only_students]) if params[:only_students]
people = people.where(name: params[:name]) if params[:name].present?
people
end
Here I am able to retain the value of params[:name] but not the value of params[:only_students]. It always remains unchecked after form submission. How can I retain the checked and unchecked value?
f.check_box check_box_tag is expecting checked to by boolean value, and every param is a string (string is always evaluated to true if exists) so you should do:
checked: params[:only_students].present?
you don't have to worry about a value of param, as unchecked params are not send while posting.
EDIT:
above works for check_box_tag.
f.check_box is tricky, you should carefully read description: https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-check_box
The behaviour you described seems pretty correct, you can deal with it or switch to check_box_tag as a better option when not updating model attributes
All the solutions above did not work for me. Try this:
<%= check_box_tag :only_students, true, params[:only_students] %>

Ransack Rails - One parameter in Array

I'm a total beginner in Rails and I try to use Ransack to filter results.
I have a model called 'adventures' which has many parameters, of which 'main_activity'. I try to implement a form in my homepage, where you can type the kind of activities you are looking for (later I will implement a dropdown so it will be limited to existing activities).
Here is what I have in my pages_controller:
def search
if params[:search].present? && params[:search].strip != ""
session[:bourse_aventuriers_search] = params[:search]
end
arrResult = Array.new
if session[:bourse_aventuriers_search] && session[:bourse_aventuriers_search] != ""
#adventures_main_activity = Adventure.where(active: true).all
else
#adventures_main_activity = Adventure.where(active: true).all
end
#search = #adventures_main_activity.ransack(params[:q])
#adventures = #search.result
#arrAdventures = #adventures.to_a
end
And in my home.html.erb
<%= form_tag search_path, method: :get do %>
<div class="row">
<div class="col-md-6">
<%= text_field_tag :search, params[:search], placeholder: "Quelle activité ?",
class:"form-control" %>
</div>
For the moment, whatever I type in the form, I get all the 'adventures' in the data base ; I find it logical because I did not change the 1st #adventures_main_activity = Adventure.where(active: true).all.
I don't know how to change it so that It will give me only the adventures whose main_activity is the keyword that I type in the form. Can anyone help me ? Thanks :)
I think you have a lot of surplus code in your search. Your controller should only need the #q parameter as follows:
#q = Adventure.ransack(params[:q])
#adventures = #q.result
The #adventures will then return any matches as an active record.
If you pass no parameters then the query will return all records (same as doing an Adventure.all).
When you submit the form the ransack search will pass a "q" param which will contain all the form items. Your's may look something like this:
"utf8"=>"✓", "q"=>{"search_cont"=>"rock climbing"}, "commit"=>"Search", "controller"=>"adventures", "action"=>"index"
If you use a debugger you can see this information by typing "params" in the command line. It will also appear in the server output.
Using an example of one I did in my application here is the exact code I used:
View:
<%= search_form_for #q do |f| %>
<div class="form-group col-sm-6">
<%= f.label :email_cont, "Email:" %>
<%= f.search_field :email_cont, :placeholder => "Please enter and email to search for", :class => "form-control" %>
</div>
<div class="form-group col-sm-3">
<%= f.submit 'Search', :class => 'btn btn-primary' %>
<%= link_to 'Reset', users_path, :class => 'btn btn-default' %>
</div>
<% end %>
Controller
def index
#q = User.ransack(params[:q])
#users = #q.result(distinct: true).order(:email).page params[:page]
end
The classes are just Bootstrap CSS which you won't need if you are not using bootstrap.
EDIT
The search_form_for #q has to exactly that and the #q has to be set in the params for it to work. Ransack is very specific about them. So your #search in
#search = #adventures_main_activity.ransack(params[:q])
should be #q. In your view change your form_tag to search_form_for and it should work. Good luck.

Rails 5: search by keyword and sort by distance

I have a search form on my app:
<%= form_for search_path, method: :get do |f| %>
<p>
<%= f.label "Search for" %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "search", name: nil %>
</p>
<% end %>
that searches by distance:
def search
if params[:search].present?
#las = La.near(action,10).reorder('distance')
else
#las = []
end
end
The results are sorted by distance and all works well up to here!! The only issue here is that the results do not appear according to the keyword typed as well. Thus whatever keyword I type, all results appear and sorted by distance.
Any idea what I might be doing wrong here??
You could try passing the content of params[:search] within the near scope:
#items = Item.near(params[:search], 10).reorder('distance')

Ruby on rails drop down box Beginner lvl

So I am a beginner in ROR, like I know it for a month (school assignment and we don't get a cursus we need to use 'google')
So I want a dropdown box with a list of all my cities. Then if I pick a city I need to save the city_id in my database together with the date. The code I have so far seem to work except when I click on save it says that city is empty (and it can't be empty because of the failsave)
this is my code
<div class="field">
<%= f.label :stad_id %><br />
<% cities_array = Stad.all.map { |stad| [stad.naam, stad.land] } %>
<%= select_tag(Stad, options_for_select(cities_array)) %>
</div>
<div class="field">
<%= f.label :datum %><br />
<% datum = Time.now.to_s(:db) %>
<%= f.text_field :datum, :value => datum.inspect, :readonly => true %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I don't really know what I am doing wrong except I have an eery feeling I don't actually give the command to save it.
help is much thanked
sincerely
Robin
There are a few things I notice here that are wrong.
1) Put the creation of the cities_array into your controller, not in your view:
def edit
#something = Something.find(params[:id])
#cities_array = ... whatever ...
end
2) When creating your cities_array, you need to specify the ID of the city as the second parameter, like this:
#cities_array = Stad.all.map { |stad| [stad.naam, stad.id] }
3) The select_tag call isn't for Stad, it's for the model you're trying to save. For example, your form might look like this:
<%= form_for #something %>
<%= f.label :city %>
<%= f.select :city_id, #cities_array %>
# or!
<%= select :something, :city_id, #cities_array %>
<% end %>
I hoep this clears things up for you.

Resources