Skip to content

Commit

Permalink
Merge pull request #2971 from mshytikov/issue/rails5-enum-filter
Browse files Browse the repository at this point in the history
Fixed filter by enum filter when label <> value
  • Loading branch information
mshibuya committed Feb 17, 2018
2 parents 401c9b9 + 1720e49 commit 8576961
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 10 deletions.
9 changes: 2 additions & 7 deletions lib/rails_admin/adapters/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,6 @@ def initialize(scope)

def add(field, value, operator)
field.searchable_columns.flatten.each do |column_infos|
value =
if value.is_a?(Array)
value.map { |v| field.parse_value(v) }
else
field.parse_value(value)
end
statement, value1, value2 = StatementBuilder.new(column_infos[:column], column_infos[:type], value, operator).to_statement
@statements << statement if statement.present?
@values << value1 unless value1.nil?
Expand All @@ -126,7 +120,8 @@ def build
def query_scope(scope, query, fields = config.list.fields.select(&:queryable?))
wb = WhereBuilder.new(scope)
fields.each do |field|
wb.add(field, field.parse_value(query), field.search_operator)
value = parse_field_value(field, query)
wb.add(field, value, field.search_operator)
end
# OR all query statements
wb.build
Expand Down
20 changes: 17 additions & 3 deletions lib/rails_admin/config/fields/types/active_record_enum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,20 @@ def type
def parse_value(value)
return unless value.present?
if ::Rails.version >= '5'
abstract_model.model.attribute_types[name.to_s].deserialize(value)
abstract_model.model.attribute_types[name.to_s].serialize(value)
else
enum.invert[type_cast_value(value)]
# Depending on the colum type and AR version, we might get a
# string or an integer, so we need to handle both cases.
enum.fetch(value) do
type_cast_value(value)
end
end
end

def parse_input(params)
params[name] = parse_value(params[name]) if params[name]
value = params[name]
return unless value
params[name] = parse_input_value(value)
end

def form_value
Expand All @@ -46,6 +52,14 @@ def form_value

private

def parse_input_value(value)
if ::Rails.version >= '5'
abstract_model.model.attribute_types[name.to_s].deserialize(value)
else
enum.invert[type_cast_value(value)]
end
end

def type_cast_value(value)
if ::Rails.version >= '4.2'
abstract_model.model.column_types[name.to_s].type_cast_from_user(value)
Expand Down
5 changes: 5 additions & 0 deletions spec/dummy_app/app/active_record/field_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,9 @@ class FieldTest < ActiveRecord::Base
mount_uploader :carrierwave_asset, CarrierwaveUploader

attachment :refile_asset if defined?(Refile)

if ::Rails.version >= '4.1' # enum support was added in Rails 4.1
enum size_string_enum: {S: 's', M: 'm', L: 'l'}
enum size_integer_enum: [:small, :medium, :large]
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddSizeEnumToFieldTests < MigrationBase
def change
add_column :field_tests, :size_string_enum, :string
add_column :field_tests, :size_integer_enum, :integer
end
end
40 changes: 40 additions & 0 deletions spec/rails_admin/abstract_model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,46 @@
end
end

context 'on ActiveRecord native enum' do
shared_examples "filter on enum" do
before do
["S", "M", "L"].each do |size|
FactoryGirl.create(:field_test, size_string_enum: size)
end

["small", "medium", "large"].each do |size|
FactoryGirl.create(:field_test, size_integer_enum: size)
end
end
let(:model) { RailsAdmin::AbstractModel.new('FieldTest') }
let(:filters) { {enum_field => {'1' => {v: filter_value, o: 'is'}}} }
subject(:elements) { model.all(filters: filters) }

it 'lists elements by value' do
expect(elements.count).to eq(expected_elements_count)
expect(elements.map(&enum_field.to_sym)).to all(eq(enum_label))
end
end

context "when enum is integer enum" do
it_behaves_like "filter on enum" do
let(:filter_value) { 0 }
let(:enum_field) { "size_integer_enum" }
let(:enum_label) { 'small' }
let(:expected_elements_count) { 1 }
end
end

context "when enum is string enum where label <> value" do
it_behaves_like "filter on enum" do
let(:filter_value) { 's' }
let(:enum_field) { "size_string_enum" }
let(:enum_label) { 'S' }
let(:expected_elements_count) { 1 }
end
end
end if CI_ORM == :active_record && ::Rails.version >= '4.1'

context 'on dates with :en locale' do
before do
[Date.new(2012, 1, 1), Date.new(2012, 1, 2), Date.new(2012, 1, 3), Date.new(2012, 1, 4)].each do |date|
Expand Down

0 comments on commit 8576961

Please sign in to comment.