how to do two search in the same page with meta_search? - ruby-on-rails

I have two list in a page, one for a model_1 and another for a model_2. When I click the sort_link of a column meta_search send the param "search[meta_sort]=column_name.asc". The problem is in the controller because the two models get filtered with the same search parameters:
#in the controller
#search_for_model_1 = Model1.search(params[:search])
#model_1s = #search_for_model_1.all
#search_for_model_2 = Model2.search(params[:search])
#model_2s = #search_for_model_2.all
#in the view
<%= sort_link #search_for_model_1, :name %>
<%= sort_link #search_for_model_2, :name %>
the sort_links are in different html tables, one showing model_1 fields and the another showing model_2 fields, when I click in any column name link, the param I get in the controller is params[:search], I have no way to know if the column link was clicked from model_1 or model_2 html table.
I want change the param name "search" for something like "search_for_model_name" then in the controller:
#in the controller
#search_for_model_1 = Model1.search(params[:search_for_model_1])
#model_1s = #search_for_model_1.all
#search_for_model_2 = Model2.search(params[:search_for_model_2])
#model_2s = #search_for_model_2.all
I could not find the way to change the param name using the helper method sort_link that meta_search provide. Or is there a different manner to do this?

sort_link uses the :as option just like form_for
<%= form_for #search, :as => :q do |f| %>
<%= sort_link #search, :field, :as => :q
#search = Model.metasearch(params[:q])
So do that with different names for each model.

most likely you just do something like this
:search_for_model_2 => :search_field
but I can't say for sure without seeing your view.

graywh's answer is not working for sort_link, this is the correct solution:
#in the controller
#search_for_model_1 = Model1.search(params[:model_1], :search_key => :model_1)
#search_for_model_2 = Model2.search(params[:model_2], :search_key => :model_2)

Related

Simple rails filters

I have simplest rails app, with scaffold Tent
here my controller#index for
def index
#tents = Tent
#tents = #tents.where(:brand => params[:brand]) if params[:brand]
#tents = #tents.where(:season => params[:season]) if params[:season]
end
view also standart, generated by scaffold
and here search witch should filter data
= form_tag tents_path, method: :get do
= label_tag "manufacturer"
= select_tag :brand, options_for_select(...), include_blank: true
= label_tag "seasons"
- Tent.pluck(:season).each do |season|
=check_box_tag 'season', season
=h season
= submit_tag 'Submit'
Problem 1:
When i submit from, and params are unselected(select or checl_boxes) i don't want to send this params but they are sent with empty
GET /tents?utf8=...&brand=&season=&commit=Submit
Problem 2:
When i check multiple checkboxes get request is somthing like
GET /tents?utf8=...&brand=Brand&season=4&season=3&commit=Submit
after this i expect that data will be selected for both values, but controller expected that both values is in the field, and returns zero results
any suggestuions?
UPDATE
probably my question solved in railscasts-111 (advanced search form)
About problem 2:
You need to specify season checkbox like below:
=check_box_tag 'season[]', season
But i didnt test it
Problem 2:
You need to write javascript wrapper for form to serialize and send data on submit

Ruby on Rails - How to use a select box to change an attribute of the selected items?

I'll start off with a bit of context to my question. I have a group of offices which each have reviewers associated with them. A reviewer can only be associated with one office. I want to create two select boxes. One lists all of the reviewers that are associated with the office I am viewing, the other lists all of the reviewers that are available (which is basically all of the reviewers that aren't already assigned to this office).
The goal of the current reviewer's listbox is to set their office to nil when they are selected. The goal of the available reviewers listbox is to set their office to this office's id when they are selected. I'm not sure how to change only the reviewers' office_id when using a select box.
Code-wise, what I have so far is this:
office_controller.rb
def edit
#office = Group.find params[:id] if params[:id]
#current_reviewers = Reviewer.find_all_by_group_id(#office.id)
#available_reviewers = Reviewer.where('group_id <> ?',[#office.id])
end
def update
?
end
office/edit.html.erb
<% form_for(#office, :url => {:controller => :office, :action => :update, :id => #office.id}, :html => {}) do |f| %>
...
<%= select_tag 'removedReviewers', options_from_collection_for_select(#current_reviewers, "id", "display_name"), :multiple => true %>
<%= select_tag 'chosenReviewers', options_from_collection_for_select(#available_reviewers, "id", "display_name"), :multiple => true %>
...
<% end %>
Any suggestions would be greatly appreciated. Thanks!
I solved this by adding the ability to get a select_tag to get the selected objects as a collection via the [] modifier of the select_tag name. So, in this example it was:
<%= select_tag 'removedReviewers[]', options_from_collection_for_select(#current_reviewers, "id", "display_name"), :multiple => true %>
And for the controller code to handle it, I did this:
#removedReviewers = params[:removedReviewers]
if !#removedReviewers.nil?
#removedReviewers.each do |reviewer|
#reviewer = Reviewer.find(reviewer)
#reviewer.group_id = nil
#reviewer.save
end
end
And the equivalent for the chosen/available reviewers.

Rails undefined method for array

In my controller I am trying to run a query to get all of the id's not referenced in another table like so:
#vlan_numbers = ActiveRecord::Base.connection.execute("SELECT pop_vlans.id, vlan_number FROM pop_vlans WHERE pop_vlans.id NOT IN (SELECT logical_interfaces.vlan_id FROM logical_interfaces) AND pop_id != " + #pop_id.to_s)
Then in my view I am trying to use collection_select to show these in a dropdown menu:
but the error I get is undefined method 'vlan_number' for [2, "2"]:Array where those values are just the first row of results from the query.
This is a diagram of the two tables involved:
logical_interfaces | pop_vlans
-------------------|-----------
vlan_id-------|----->id
.... | vlan_number
and the relationships in the models are:
pop_vlan.rb
belongs_to :logical_interface
logical_interface.rb
# no relationship defined
Update
This is how the form is generated:
<%= form_tag :controller => "circuit", :action => "update" %>
# other inputs
<%= select_tag options_for_select(#vlan_numbers) %>
# other inputs
</form>
You can use select with options_for_select(#vlan_numbers) instead of collection_select
results from ActiveRecord::Base.connection.execute doesn't get loaded into a model
Instead you could try YourModelName.find_by_sql(...) If you want to play with your model
UPDATE
Assuming the name of your attribute you want this select_tag to populate is vlan_id so:
<%= form_tag :controller => "circuit", :action => "update" %>
# other inputs
<%= select_tag 'vlan_id', options_for_select(#vlan_numbers) %>
# other inputs
</form>
ActiveRecord::Base.connection.execute returns Mysql2::Result not array of object as Arel/AR query does.
So it returns array of arrays containing pop_vlans.id, vlan_number. So have to use first or last in your collection_select instead of something.vlan_number
So you have to use options_for_select instead of collection_select like:
options_for_select(#vlan_numbers.collect{|v| v.first})

How do I search for multiple records in a search form?

I am trying to allow the user to be able to choose multiple records in a field on the search form.
Something like this:
<%= f.input_field :neighborhood_id, collection: Neighborhood.order(:name), :url => autocomplete_neighborhood_name_searches_path, :as => :autocomplete, 'data-delimiter' => ',', :multiple => true, :class => "span8" %>
It sends it to my search model like this: #search = Search.create!(params[:search])
This is what the Search.rb model does with it:
key = "%#{keywords}%"
listings = Listing.order(:headline)
listings = listings.includes(:neighborhood).where("listings.headline like ? or neighborhoods.name like ?", key, key) if keywords.present?
listings = listings.where(neighborhood_id: neighborhood_id) if neighborhood_id.present?
listings
The issue is that this is just accepting 1 neighborhood_id, so I am getting this error when I choose multiple objects:
undefined method `to_i' for ["Alley Park, Madison"]:Array
Where Alley Park and Madison are the names of 2 neighborhoods, not the IDs.
So how do I get this working?
Thanks.
Edit 1
The issue seems to not be in the lookup of the params[:search] per se, but rather in the conversion of the form input to an array of entries. I tried changing the search method to be something like:
listings = listings.includes(:neighborhood).where("neighborhoods.name like ?", neighborhood_id) if neighborhood_id.present?
Don't get hung up on the fact that I am looking up neighborhood.name and passing in neighborhood_id. I just did that because I know that the params for the field neighborhood_id were actually the names of the neighborhood. If this had worked, I would have refactored some stuff, but it didn't. So don't get hung up on that.
But that still returns the error undefined method 'to_i'....
Also, I still get that error even if I just pass in 1 option.
listings = listings.where("neighborhood_id in (?) ", neighborhood_id)
You can get the id instead of neighborhood names from the input field like this:
<%= f.input_field :neighborhood_id, collection: Neighborhood.order(:name), :url => autocomplete_neighborhood_name_searches_path, :as => :autocomplete, 'data-delimiter' => ',', :multiple => true, :class => "span8", :input_html => { :id => "neighborhood_id" } %>

Retain Search Form Data Ruby On Rails

Trying to build a search on my homepage with simple_form (Pretty much same as formtastic). The search works fine and im getting my results but after submission I want to retain the vales with what the user submitted.
I am using a namespace for my form so how can I retain the data for the form. Here is some code which may help.
Controller
def index
#results = Property.search(params[:search])
end
View
%h1 Search Form
= simple_form_for(:search) do |f|
= f.input :location, :as => :select, :collection => Location.all.asc(:name)
= f.input :type, :collection => PropertyType.all.asc(:name)
= f.input :bedrooms, :collection => 1..10,
%p.box
= f.button :submit
-if #results
%h1 Search Results
.results
- #results.each do |property|
.result
%h1= property.title
Within the Index controller I have tried all sorts of things ie
#search = params[:search]
But each time I try something the search breaks.
What am I doing wrong ?
Hope you can advise
One approach is to do as Xavier Holt suggested, and pass in values to each input. The simpleform doco suggests:
= f.input :remember_me, :input_html => { :value => '1' }
The other approach is to have simpleform do it for you. SimpleForm will automatically populate the fields with values if you give it something like an activerecord object.
In this case, that means creating a model object:
class PropertySearchCriteria
attr_accessor :location, :type, :bedrooms
def initialize(options)
self.location = options[:location]
self.type = options[:bedrooms]
self.bedrooms = options[:bedrooms]
end
end
Then, change your controller:
def index
#property_search_criteria = PropertySearchCriteria.new(params[:search])
#results = Property.search(#property_search_criteria)
end
(you'll have to change the Property.search method as well)
Then, change your simple_form_for:
= simple_form_for(:search, #property_search_criteria) do |f|
And if you do all that, and get the stars to align just right, then simpleform will pre-populate the form fields all by itself. You may have to add some stuff to PropertySearchCriteria to get simpleform to be properly happy.
This is a lot of stuffing around just to get the values showing up, but it'll keep you sane if you need to add validations.
I'm doing something similar in the app I'm working on (I'm not using formtastic, but this should be at least very close to something that works for you). I got around it by making sure #search was a hash in the controller:
#search = params[:search] || {}
And then using #search[:key] as the :value option in all my search inputs (There's a chance you'll need to set #search.default = '' to get this working):
<%= text_field_tag :name, :value => #search[:name] %>
And that's all it took. As my app is getting more complicated and AJAXy, I've been thinking of moving the search parameters into the session information, which you might want to do now to stay ahead, but if you're just looking for a simple solution, this worked great for me.
Hope this helps!
you can try storing your parameters in session like so:
def index
#results = Property.search(params[:search])
store_search
end
def store_search
session[:search] = params[:search]
end
just be sure when you are done with the parameters that you clean them up
...
clear_search if session[:search]
def clear_search
session[:search] = nil
end

Resources