Reputation: 6569
What would be the most efficient way of accomplishing the following: Grab a value from a drop down and pass it with a search function into model.
Here is the html for search:
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
Here is the code in controller:
def index
@trucks = Truck.search(params[:search])
respond_to do |format|
format.html # index.html.erb
format.json { render json: @trucks }
end
end
Here is the model
def self.search(search)
if search
where('truck_no LIKE ?', "%#{search}%")
else
scoped
end
In the model I have 'truck_no LIKE ?'
I would like it to become column_name + ' LIKE ?'
where I pass in the column name through the method parameter. How would I setup my drop down list in the html and pass it all the way to the controller? What is the best way of accomplishing this?
Edit: forgot to mention, the drop down should display things like Truck Number, but pass in the value truck_no
Upvotes: 2
Views: 2683
Reputation: 54882
Here is the base for you:
# view
<p>
<%= text_field_tag :search, params[:search] %>
<%= select_tag :search_column, options_for_select(Truck.column_names, params[:search_column]) %>
<%= submit_tag "Search", :name => nil %>
</p>
# controller
def index
@trucks = Truck.search(params[:search], params[:search_column])
# model
def self.search(keyword, column_name)
if self.column_names.include?(column_name.to_s)
where("trucks.#{column_name} LIKE ?", "%#{keyword}%")
else
scoped
end
end
There is several improvements you can do here:
select_field_tag
to see the translated attributessanitize
to make sure the column_name
is safeI can help you with the improvements if you need.
Here we have a choice, should we get all the columns and take off some of them? OR should we just select the one we want? The first option implies that if you add an attribute to the model, it will be by default added to the options, unless you take it off. The reverse will happen with the second option:
# model
# This method should return the columns defined in the `wanted_columns` array
def self.searchable_columns
wanted_columns = ['name', 'description', 'etc' ]
self.column_names.select{ |column| wanted_column.include?(column) }
end
# This method will return the columns NOT IN the `unwanted_columns` array
def self.searchable_columns
unwanted_column = ['id', 'created_at', 'updated_at']
self.column_names.reject{ |column| unwanted_column.include?(column) }
end
# view
<%= select_tag :search_column, options_for_select(Truck.searchable_columns, params[:search_column]) %>
# model
# This method return an array of arrays formatted like following:
# [ ['Name', 'name'], ['Truck Number', 'truck_no'] ]
def self.translated_searchable_columns
columns = self.searchable_columns
result = columns.map{ |column| [Truck.human_attribute_name(column.to_sym), column] }
result
end
# view
<%= select_tag :search_column, options_for_select(Truck.translated_searchable_columns, params[:search_column]) %>
Upvotes: 5