0

My autocomplet works, and it looks decent enough, but oh boy, the controller is a mess. The autocomplete searches across multiple models which does not help things, and totalling up the found sets ect - there are country flags for customers etc.

I'd like to extract this to a partial ideally or another way to make the code easier to deal with.

  def autocomplete
      customer_count = (Customer.select("company").where("LOWER(company) LIKE ? AND deleted != ?", "#{params[:term].downcase}%", true).count) + (Product.select("model_number,description").where("LOWER(description) LIKE ? OR LOWER(model_number) LIKE ? AND deleted != ?", "#{params[:term].downcase}%", "#{params[:term].downcase}%", true).count) + (Order.where("LOWER(order_number) LIKE ? AND deleted != true","#{params[:term].downcase}%").count)
      @customers = [{:label => (customer_count > 1 ? "<div style='font-weight: bold; text-align: left;'>Show all #{customer_count} records</div" : customer_count > 0 ? '' : "<div style='font-weight: bold; text-align: left;'>No records found</div>"), :link => "/customers?company=#{params[:term].downcase}"}]
      @customers.concat(Customer.select("id, company, country").where("LOWER(company) LIKE ? AND deleted != ?", "#{params[:term].downcase}%", true).limit(24).collect{|customer|{:label=>("<div style='float:left;margin-top:4px;margin-right:8px;'><img alt='Mini_usa' src='/images/#{customer.country_div}'/></div> #{customer.company}").html_safe,:link =>"/customers/#{customer.id}"}})
      @customers.concat(Product.select("id, model_number, description").where("LOWER(description) LIKE ? OR LOWER(model_number) LIKE ? AND deleted != ?","#{params[:term].downcase}%","#{params[:term].downcase}%",true).limit(24).collect{|product|{:label => ("#{product.model_number.titlecase}&nbsp;#{product.description.titlecase}").html_safe,:link =>"/products/#{product.model_number}"}})
      @customers.concat(Order.select("id, order_number").where("LOWER(order_number) LIKE ? AND deleted != true","#{params[:term].downcase}%").limit(24).collect{ |order| { :label => ("#{order.order_number}").html_safe, :link =>"/orders/#{order.id}" } })
  end

1 Answer 1

2

Why don't you make autocomplete (or perhaps search is a better name for the context) methods for each individual model, then call and combine them each from your controller? This keeps the responsibility of knowing how to search where the data itself lies (in the model).

In general you want to favor putting logic in your model, not your controller.

Sign up to request clarification or add additional context in comments.

5 Comments

So you're saying that each model needs its own self.search(term) method, "term" being passed in by the ActionController that processes the form (possibly products#index)...?
@james_dunn_jr Yup! Controller takes in the parameters from the user, then asks the model to search for records that match it, because the controller shouldn't know how to search, only how to ask for search results.
@fatfrog Put them in the view where they belong :)
according to the Railscast tutorial, server side search it's done in the controller and I can't figure out how to get it out : railscasts.com/episodes/…
I can't watch that as I don't subscribe to Railscasts Pro. Just put it in a new view and call render with that view. Instead of concating your objects in the controller, keep them separate so the view can manipulate them accordingly for rendering.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.