Permalink
Browse files

Added support for filtering by membership in a has_and_belongs_to_many

relationship, along with a basic 'multiselect' helper for maintaining
them.
  • Loading branch information...
1 parent 08ed960 commit a2caaf473df60db9979ff0e7cd178f5213d17772 @matthewd matthewd committed Jun 25, 2007
Showing with 25 additions and 3 deletions.
  1. +5 −0 lib/auto_admin_configuration.rb
  2. +9 −2 lib/auto_admin_filter_sets.rb
  3. +11 −1 lib/auto_admin_simple_theme.rb
@@ -123,6 +123,9 @@ def filter_option_sql column_name, option_name
def filter_options_for column_name, custom_options, &block
(@custom_filter_options ||= {})[column_name.to_sym] = AutoAdmin::CustomFilterSet.new( self, reflect_on_association( column_name ) || find_column( column_name ), custom_options, &block )
end
+ def dynamic_filter_options_for column_name, &block
+ filter_options_for( column_name, block )
+ end
def filters
columns_for_filter.map { |col| filter_instance( col ) }
end
@@ -133,6 +136,8 @@ def filter_instance column_name
klass = case type = filter_type( column_name )
when :belongs_to: AutoAdmin::AssociationFilterSet
when :has_one: AutoAdmin::AssociationFilterSet
+ when :has_many: AutoAdmin::MultiAssociationFilterSet
+ when :has_and_belongs_to_many: AutoAdmin::MultiAssociationFilterSet
when :datetime: AutoAdmin::DateFilterSet
else
const = type.to_s.camelcase + 'FilterSet'
@@ -46,7 +46,9 @@ def sql_from_string option_name
end
def other_options
a = []
- @options.each do |k,v|
+ options = @options
+ options = options.call if options.respond_to?( :call )
+ options.each do |k,v|
o = build_option( k, v )
o[:sql] = @block.call( k ) unless @block.nil?
a << o
@@ -90,7 +92,7 @@ def name
assoc.name.to_s
end
def sql_column
- (assoc.options && assoc.options[:foreign_key]) || (assoc.name.to_s + '_id')
+ assoc.association_foreign_key
end
def objects
assoc.klass.find :all
@@ -105,6 +107,11 @@ def sql_from_string option_name
sql_from_value option_name.to_i
end
end
+ class MultiAssociationFilterSet < AssociationFilterSet
+ def sql_from_value option_name
+ ["EXISTS(SELECT * FROM #{assoc.options[:join_table]} WHERE #{assoc.primary_key_name} = #{assoc.active_record.primary_key} AND #{assoc.association_foreign_key} = ?)", option_name]
+ end
+ end
class BooleanFilterSet < SimpleFilterSet
def other_options
[ build_option( true, 'Yes' ), build_option( false, 'No' ) ]
@@ -177,7 +177,7 @@ def common_option_translations!(options)
end
def get_column_from_field(field)
assoc = model.reflect_on_association( field.to_sym )
- assoc ? assoc.primary_key_name : field
+ assoc ? ([:has_many, :has_and_belongs_to_many].include?(assoc.macro) ? "#{field.to_s.singularize}_ids" : assoc.primary_key_name) : field
end
def macro_type(column_name)
@@ -286,6 +286,16 @@ def select(field, options = {}, html_options = {})
end
super( field, dropdown_options, options, html_options )
end
+ def multiselect(field, options = {}, html_options = {})
+ common_option_translations! options
+ dropdown_options = find_choices(field, options)
+ column = get_column_from_field(field)
+ html_defaults = { :size => 8, :multiple => true,
+ :name => "#{@object_name}[#{column}][]",
+ :id => "#{@object_name}_#{column}" }
+
+ helpers.content_tag('select', helpers.options_for_select( dropdown_options, @object && @object.send(column) ), html_defaults.merge( html_options ) )
+ end
def radio_group(field, options = {})
common_option_translations! options
choices = find_choices(field, options)

0 comments on commit a2caaf4

Please sign in to comment.