lib/autocomplete_rails/controller.rb in autocomplete_rails-0.3.1 vs lib/autocomplete_rails/controller.rb in autocomplete_rails-0.4.0
- old
+ new
@@ -24,10 +24,12 @@
# Parameters:
# * model_symbol - model class to autocomplete, e.g.
# * value_method - method on model to autocomplete. This supplies the 'value' field in results.
# Also used as the label unless you supply options[:label_method].
# * options - hash of optional settings.
+ # * &block - an optional block to further modify the results set,
+ # e.g. `{ |results| results.where(smth: @instance_variable) }`
#
#
# Options accepts a hash of:
# * :label_method - call a separate method for the label, otherwise defaults to value_method. If your label
# method is a method that is *not* a column in your DB, you may need options[:full_model].
@@ -37,10 +39,12 @@
# * :additional_data - collect additional data. Will be added to select unless full_model is invoked.
# * :full_search - search the entire value string for the term. Defaults to false, in which case the value
# field being searched (see value_method above) must start with the search term.
# * :scopes - Build your autocomplete query from the specified ActiveRecord scope(s). Multiple scopes can be
# used, pass them in as an array. Example: `scopes: [:scope1, :scope2]`
+ # If you need to pass additional arguments to your scope, define them as an array of arrays.
+ # Example: `scopes: [:scope1, [:scope2, 'argument 1', 'argument 2] ]`
# * :order - specify an order clause, defaults to 'LOWER(#{table}.#{value_method}) ASC'
#
# Be sure to add a route to reach the generated controller method. Example:
#
# resources :users do
@@ -52,31 +56,40 @@
#
# class UsersController
# autocomplete :user, :email, label_method: full_name, full_model: true
# end
#
- def autocomplete(model_symbol, value_method, options = {})
+ def autocomplete(model_symbol, value_method, options = {}, &block)
label_method = options[:label_method] || value_method
model = model_symbol.to_s.camelize.constantize
autocomplete_method_name = "autocomplete_#{model_symbol}_#{value_method}"
define_method(autocomplete_method_name) do
- results = autocomplete_results(model, value_method, label_method, options)
+ results = autocomplete_results(model, value_method, label_method, options, &block)
render json: autocomplete_build_json(results, value_method, label_method, options), root: false
end
end
end
protected
- def autocomplete_results(model, value_method, label_method = nil, options)
+ def autocomplete_results(model, value_method, label_method = nil, options, &block)
term = params[:term]
return {} if term.blank?
results = model.where(nil) # make an empty scope to add select, where, etc, to.
scopes = Array(options[:scopes])
- scopes.each { |scope| results = results.send(scope) } unless scopes.empty?
+ unless scopes.empty?
+ scopes.each do |scope|
+ if scope.is_a?(Array)
+ results = results.send(scope.slice(0), *scope.drop(1))
+ else
+ results = results.send(scope)
+ end
+ end
+ end
+ results = instance_exec(results, &block) if block
results = results.select(autocomplete_select_clause(model, value_method, label_method, options)) unless
options[:full_model]
results.
where(autocomplete_where_clause(term, model, value_method, options)).
limit(autocomplete_limit_clause(options)).
@@ -110,10 +123,10 @@
def autocomplete_order_clause(model, value_method, options)
return options[:order] if options[:order]
# default to ASC order
table_prefix = "#{model.table_name}."
- "LOWER(#{table_prefix}#{value_method}) ASC"
+ Arel.sql("LOWER(#{table_prefix}#{value_method}) ASC")
end
def autocomplete_build_json(results, value_method, label_method, options)
results.collect do |result|
data = HashWithIndifferentAccess.new(id: result.id,