I am creating a search for with multiple imputs, I am just wondering how to pass params from the select
<%= form.select :listing_type, Listing.listing_types.keys, {}, {class: "form-select form-select-lg", id: "floatingSelect"}, :selected => params[:listing_type] %>
gives me the error
wrong number of arguments (given 5, expected 1..4)
I am creating a search for with multiple imputs, I am just wondering how to pass params from the select
<%= form.select :listing_type, Listing.listing_types.keys, {}, {class: "form-select form-select-lg", id: "floatingSelect"}, :selected => params[:listing_type] %>
gives me the error
Share Improve this question asked Feb 21 at 5:58 Joe BloggosJoe Bloggos 8898 silver badges25 bronze badgeswrong number of arguments (given 5, expected 1..4)
1 Answer
Reset to default 1You're passing an additional empty hash that's not needed. The dreadful signature of select
is:
form.select(method, choices = nil, options = {}, html_options = {}, &block)
Giving an arity of 1..4
. Number 5 is (, :selected => params[:listing_type]
) since the brackets can be omitted from a hash if it's passed as the last argument.
When dealing with these janky old pre Ruby 2 methods (which introduced keywords) it helps to use a decent line length limit so that you can keep track of the arguments.
<%= form.select
:listing_type, # method
Listing.listing_types.keys, # choices
{ selected: params[:listing_type] }, # options
{ class: "form-select form-select-lg", id: "floatingSelect" } # html_options
%>
It could be argued though that letting the view directly access the params is a bit stinky as that is the job of the controller. I generally prefer using the form object pattern instead of leaving all the wires dangling out.
# app/forms/listing_search.rb
class ListingSearch
include ActiveModel::Model
include ActiveModel::Attributes
attribute :listing_type, :string
# Gives a collection of listings with the search filters applied
def resolve
if listing_type.present?
Listing.where(listing_type: listing_type)
else
Listing.all
end
end
end
class ListingsController < ApplicationController
# GET /listings
# GET /listings?q[listing_type]=man_cave
def index
@listing_search = ListingSearch.new(listing_search_params)
@listings = @listing_search.resolve
@listing_types = Listing.listing_types.keys
end
private
def listing_search_params
# the key q is just for breivity so you don't get super long URLs.
params.fetch(:q, {})
.permit(:listing_type)
end
end
<%= form_with model: @listing_search, url: listings_path, method: :get, scope: :q do |form| %>
<div class="field">
<%= form.label :listing_type %>
<%= form.select :listing_type,
@listing_types,
{}, # just because this damn method is ancient
{ class: "form-select form-select-lg", id: "floatingSelect" }
%>
</div>
<div class="actons">
<%= form.submit "Search" %>
</div>
<% end %>
When you pass a model the selected attribute will be populated by calling :listing_type
(the first argument) so you don't need to do it explicitly.