Retain Search Form Data Ruby On Rails - 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

Related

ActiveAdmin passing variable in controller

I have a permit and vehicle model. I am trying to update the AA create controller to work how I have it in my rails app. That is taking the vehicle license_number entered and inputting it into the permit table, then also taking the inputted permit_id and inputting it into the permits attribute of the vehicle it is related to in the vehicle table.
admin/permit.rb
permit_params :permit_id, :vehicle, :date_issued, :issued_by, :date_entered, :entered_by
form do |f|
f.inputs do
f.input :permit_id
f.input :vehicle, :collection => Vehicle.all.map{ |vehicle| [vehicle.license_number]}
f.input :date_issued, as: :date_picker
f.input :issued_by
end
f.actions
end
controller do
def new
#permit = Permit.new
#vehicle = #permit.build_vehicle
#vehicle = Vehicle.all
super
end
def create
vehicle = Vehicle.find_by(license_number: permit_params[:vehicle_attributes][:license_number])
#permit = current_user.permit.build(permit_params.merge(date_entered: Date.today,
entered_by: current_user_admin.email))
super
end
end
My errors that I am getting, is that it is inputting the license_number in for the permit_id and then it is also saying the permit_params is not a defined variable. Any help would be great, thanks!
You have an interesting case here: it is confusing because you have a model called Permit, and usually in Rails you name the params method something like permit_params. Turns out, permit_params is the general method signature for ActiveRecord to implement strong params: https://activeadmin.info/2-resource-customization.html
With that, instead of calling permit_params in your create action, you need to call permitted_params[:vehicle_attributes][:license_number]. That’s why it’s considering permit_params as an undefined variable. Again, those two method signatures will be the same for all your ActiveAdmin forms.
Additionally, I’m not sure if this is a typo but you define #vehicle twice in your new method. I’m not sure you need to build a vehicle for the permit form unless you’re doing nested forms. Either way, I think the last line should read #vehicles = Vehicle.all Then you can use that in your form, which also could use an update in the collection part of your form field:
form do |f|
f.inputs do
f.input :permit_id
f.input :vehicle, collection: #vehicles.map { |vehicle| [vehicle.license_number, vehicle.id] }
f.input :date_issued, as: :date_picker
f.input :issued_by
end
f.actions
end
The collection_select form tag will take the first item in the array as the value that appears in the form, and the second value will be the value passed through in the params (https://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select).
Then in your create action, you can find the Vehicle with the id:
Vehicle.find(permitted_params[:vehicle_attributes][:vehicle_id])
I would avoid Permit as a model name, try using VehiclePermit.

has_one relationship without nested_form

I'm trying to implement a has_one relationship through a basic form and am getting completely stuck.
I seem to have tried huge numbers of combinations of things in controllers and forms but don't seem to be getting anywhere.
I have a phone number for which I use an external service populated by an api.
Eventually I would like to have all the phone numbers of this type set up for this, but right now I'd be happy with getting just one working.
parent.rb
has_one :clever_phone
And a phone model
clever_phone.rb
attr_accessible :number, :parent_id, :prefix, :country_iso
belongs_to :parent
Controller
clever_phones_controller
def new
#parent = Parent.find(params[:parent_id])
#clever_phone = #parent.build_clever_phone
def create
#parent = Parent.find(params[:parent_id]
#clever_phone = Parent.create_clever_phone(params[:clever_phone])
View
I really don't want to do a nested form from the parent here as I have some complicated code which generates information used in the creation through an api that sits, correctly I think, in the clever_phones_controller
#simple_form_for #clever_phone do |f|
= f.input :country_iso, as: :country, :iso_codes => true, priority: ["gb"]
= f.input :prefix
= f.submit
Routes
resources :parent do
resource :clever_phone
end
My issue is that the params for #parent don't seem to be being passed to the create method in the controller and thus I get a
'Can't find parent without ID'
error
If I try it as a nested form
I get
NoMethodError undefined method 'parent_clever_phones_path'
When in fact I've not used that, only parent_clever_phone_path (note the absence of plural).
I'm sure this should be really simple but I've stared at it for hours now and am at the end of my tether...
Any ideas?
Okay, there are several issues which you need to contend:
--
Variable
The reason why #parent params are not being passed is because you've not included them in your form. This is where nesting your forms would come in very handy - passing your parent params, and your clever_phone params in a single call
Since you don't want to do this, I would recommend at least populating a hidden field with the parent_id that the clever_phone is associated with:
#app/views/clever_phones/new.html.erb
= simple_form_for #clever_phone do |f|
= f.input :parent_id, as: :hidden, value: params[:parent_id]
= f.input :country_iso, as: :country, :iso_codes => true, priority: ["gb"]
= f.input :prefix
= f.submit
--
Route
Alternatively, you have to make sure you're able to create the correct route for your form (as I think the #parent = Parent.find params[:parent_id] is not being called on your create method:
#app/views/clever_phones/new.html.erb
= simple_form_for [#parent, #clever_phone] do |f|
This will give you the ability to point your create action to the nested version of your route; hence providing the parent_id param for you
--
Having written, this I don't think it will address the core of your issue. If you need more information, please write a comment & I'll happily work to create a more appropriate answer!
Right: Worth putting in the solution that finally worked.
Thanks to Rich Peck for getting me halfway there...
model
parent.rb
has_one :clever_phone
clever_phone.rb
belongs_to :parent
view
simple_form_for #clever_phone, url: parent_clever_phone_path(#parent) do |f|
-----
f.input :parent_id, :value: #parent.id
-----
routes
resources :parent do
resource :clever_phone
controller
def new
....
#parent = Parent.find(params[:parent_id])
#clever_phone = #parent.build_clever_phone
def create
#parent = Parent.find(params[:parent_id]
#clever_phone = CleverPhone.new(params[:clever_phone]
Unless you do build_clever_phone the parent_id won't populate. I couldn't get #parent.create_clever_phone to work, but this seemed to do the trick...
Hope that saves somebody a days work...

Rails nested form with accepts_nested_attributes_for with an unfortunate model name

I have a Parent model named "Controller" (Mature app, and not my decision)
belongs_to :controller
accepts_nested_attributes_for :controller
Form:
= f.fields_for :controller do |c|
= c.hidden_field :id, :value => #controller.id
= c.text_field :slw_type
which doesn't get displayed.
= f.fields_for :literally_anything_else do |c|
= c.hidden_field :id, :value => #controller.id
= c.text_field :slw_type
if change the variable name to anything else, the form builds. I have a hunch that it's a rails specific reserved name.
Question:
What's the problem? and how can I make this work?
SOLVED:
The issue was that the parent model wasn't associated with the child model yet. My mistake for not providing all the information necessary.
This worked.
def new
#controller = Controller.find(params[:controller_id])
#inspection = Inspection.new(:controller => #controller)
Therefore my fields_for form builder also worked.
Pick some innocuous variable name. not_really_a_controller or whatever. Use that for your variable and your form. Then, in your actual controller (e.g. ActionController::Base descendent), rename the incoming param so the model doesn't know any different, like so:
before_filter :filter_params
private
def filter_params
if params[:not_really_a_controller]
params[:controller] = params.delete(:not_really_a_controller)
end
end
I've used this strategy for similar reasons in the past, though not specifically for controller. Worth a try though!

Rails Parse Form Input

I'm using a form to transfer some data from one part of a controller to another (new to create), but I'm having some trouble with it. When I try to get the data after submitting the form, it just gives me a nil value.
Here's the form code:
<%= f.hidden_field :owner_id, :value => #tool.user_id %>
<%= f.hidden_field :tool_id, :value => #tool.id %>
<%= f.hidden_field :borrower_id, :value => current_user.id %>
And this is the create action in the controller:
def create
render text: params[:rental_agreement].inspect
#rental_agreement = RentalAgreement.create
#rental_agreement.owner_id = params[:owner_id]
# render text: #rental_agreement.inspect
end
When I hit the "Submit" button on the form, I see this:
{"owner_id"=>"3", "tool_id"=>"1", "borrower_id"=>"4"}
That's fine, but when I change which inspection renders (comment out the top line, uncomment the bottom), all it displays is:
#
And if I look in the Rails console at this object, all of the fields in it are nil (except the id and created_at fields).
I'm just trying to figure out how to assign the variables from the form (owner_id, tool_id, and borrower_id) to the rental_agreement variable. Any help is much appreciated!
Your create method seems wrong. Try this.
def create
#rental_agreement = RentalAgreement.new(params[:rental_agreement])
#rental_agreement.save
end

Rails & Sunspot facets and filtering

Pretty much a noobie here, so I appreciate any help someone can give.
I'm trying to add faceting to the search on my site through Sunspot. Ryan just released a great Railscast which got me started: http://railscasts.com/episodes/278-search-with-sunspot. I got that working and was able to add additional facets. My problem is that the facets are independent of each other. If I have 3 facets on 3 different attributes, when I select a facet once I already have on selected, I would like to display only results falling into both of those facests. As of now, it just switches from one facet to the other. I feel like this shouldn't be that difficult, but I can't figure out how to do it.
I did find this tutorial: http://blog.upubly.com/2011/01/06/using-sunspot-in-your-views/ which I think is doing what I want. I tried to get this working but, even when I attempt to make it work with just one facet I don't any results listed. Just the facet name and then nothing else.
Thoughts?
Thank you!!
UPDATE
Here is the code samples of what I am trying to do:
Adjusting the Railscasts code I got this:
In my StylesController:
def index
#search = Style.search do
fulltext params[:search]
facet :departmental, :seasonal, :classifier
with(:departmental, params[:department]) if params[:department].present?
with(:classifier, params[:classification]) if params[:classification].present?
with(:seasonal, params[:season]) if params[:season].present?
end
In my Style Index view (I know I need to condense this)
= form_tag styles_path, :method => :get do
%p
= text_field_tag :search, params[:search]
= submit_tag "Search", :name => nil
#facets
%h4 Departments
%ul
- for row in #search.facet(:departmental).rows
%li
- if params[:department].blank?
= link_to row.value, :department => row.value
(#{row.count})
- else
%strong= row.value
(#{link_to "remove", :department => nil})
%h4 Classifications
%ul
- for row in #search.facet(:classifier).rows
%li
- if params[:classification].blank?
= link_to row.value, :classification => row.value
(#{row.count})
- else
%strong= row.value
(#{link_to "remove", :classification => nil})
%h4 Seasons
%ul
- for row in #search.facet(:seasonal).rows
%li
- if params[:season].blank?
= link_to row.value, :season => row.value
(#{row.count})
- else
%strong= row.value
(#{link_to "remove", :season => nil})
In my Style Model:
searchable do
text :number, :description, :department, :classification, :season
string :departmental
string :classifier
string :seasonal
end
def departmental
self.department
end
def classifier
self.classification
end
def seasonal
self.season
end
And my version of the upubly code, paired down to just try to get the "seasonal" facet working:
I left the the Search Partial, the Search Model and the SearchHelper the same as in the example. I tried to mess with the Helper as my Facets will be pulling text values, not just IDs of other Models, but to no avail. I don't have my various attributes set up as individual Models as I didn't think I needed that functionality, but I am starting to think otherwise.
StylesController:
def index
#title = "All styles"
#search = search = Search.new(params[:search]) # need to set local variable to pass into search method
#search.url = styles_path
#search.facets = [:seasonal]
#solr_search = Style.search do
keywords search.query
with(:seasonal, true)
search.facets.each do |item|
facet(item)
with(:seasonal, params[:season]) if params[:season].present?
end
any_of do
# filter by facets
search.facets.each do |item|
with(item).all_of( params[item].try(:split, "-") ) if params[item].present?
end
end
paginate(:page => params[:page], :per_page => 10)
end
Again, I appreciate the help. Definitely a noob, but really enjoying the process of building this site. Stackoverflow has been a HUGE help for me already, so I owe everybody who posts answers on here a big-time thank you.
I needed the answer to this myself, and seeing as there seems to be nothing else on the web about it, I decided I'd try to figure it out myself.
First I came to the conclusion through logic, that the controller can handle multiple facets and there's no reasons it cannot, I remembered that the best part about ruby is that it is the most human readable code, try to read your first controller and you'll see that it makes sense that it works. I tested this by manually entering in a query string in url, which returned expected results. Therefore, once I figured that out, I knew the issue resided in my view (which made me facepalm because it's fairly obvious now)
Your example is significantly more complex than mine, and my answer might not 100% meet every requirement but I'm pretty sure it's close. Also your code in your model regarding "departmental" etc is a little redundant in my view
Controller
def index
#search = Style.search do
fulltext params[:search]
facet :departmental, :seasonal, :classifier
with(:departmental, params[:department]) if params[:department].present?
with(:classifier, params[:classification]) if params[:classification].present?
with(:seasonal, params[:season]) if params[:season].present?
end
View
%h4 Departments
%ul
- for row in #search.facet(:departmental).rows
%li
- if params[:department].blank?
= link_to row.value, styles_path(
:department => row.value,
:classification => (params[:classification] unless params[:season].blank?),
:season => (params[:season] unless params[:season].blank?))
(#{row.count})
- else
%strong= row.value
= link_to "remove", styles_path(
:department => nil,
:classification => (params[:classification] unless params[:season].blank?),
:season => (params[:season] unless params[:season].blank?))

Resources