From b3c841bfd58a046ec676bd4ca449233028e2cb48 Mon Sep 17 00:00:00 2001 From: Aaron Lipman Date: Sun, 7 Jun 2020 22:15:18 -0400 Subject: [PATCH] Add ransack! method which raises error if passed unknown condition --- CHANGELOG.md | 4 +++ Gemfile | 2 +- README.md | 12 ++++++++ lib/ransack/adapters/active_record/base.rb | 4 +++ lib/ransack/search.rb | 3 +- .../adapters/active_record/base_spec.rb | 4 +++ spec/ransack/search_spec.rb | 30 +++++++++++++++++-- 7 files changed, 55 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a487e427..44d8caba6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +* Add `ActiveRecord::Base.ransack!` which raises error if passed unknown condition + + *Aaron Lipman* + ## 2.4.0 - 2020-11-27 * diff --git a/Gemfile b/Gemfile index ea198d7d2..6824ba819 100644 --- a/Gemfile +++ b/Gemfile @@ -42,7 +42,7 @@ else gem 'actionpack' end end -gem 'mysql2', '~> 0.5.2' +# gem 'mysql2', '~> 0.5.2' group :test do gem 'machinist', '~> 1.0.6' diff --git a/README.md b/README.md index ec4c1a992..6647dd369 100644 --- a/README.md +++ b/README.md @@ -316,6 +316,18 @@ by placing the following line in your Ransack initializer file at Ransack::Adapters::ActiveRecord::Base.class_eval('remove_method :search') ``` +### Ransack #ransack! method + +The `#ransack!` class method raises an error if passed an unknown condition: + +```ruby +Article.ransack!(unknown_attr_eq: 'Ernie') +# ArgumentError: Invalid search term unknown_attr_eq +``` + +This is equivilent to the `ignore_unknown_conditions` configuration option, +except it may be applied on a case-by-case basis. + ### Associations You can easily use Ransack to search for objects in `has_many` and `belongs_to` diff --git a/lib/ransack/adapters/active_record/base.rb b/lib/ransack/adapters/active_record/base.rb index fa8ed32ee..9ad348a75 100644 --- a/lib/ransack/adapters/active_record/base.rb +++ b/lib/ransack/adapters/active_record/base.rb @@ -18,6 +18,10 @@ def ransack(params = {}, options = {}) Search.new(self, params, options) end + def ransack!(params = {}, options = {}) + ransack(params, options.merge(ignore_unknown_conditions: false)) + end + def ransacker(name, opts = {}, &block) self._ransackers = _ransackers.merge name.to_s => Ransacker .new(self, name, opts, &block) diff --git a/lib/ransack/search.rb b/lib/ransack/search.rb index 9b4384443..35ca06539 100644 --- a/lib/ransack/search.rb +++ b/lib/ransack/search.rb @@ -30,6 +30,7 @@ def initialize(object, params = {}, options = {}) ) @scope_args = {} @sorts ||= [] + @ignore_unknown_conditions = options[:ignore_unknown_conditions] == false ? false : true build(params.with_indifferent_access) end @@ -45,7 +46,7 @@ def build(params) base.send("#{key}=", value) elsif @context.ransackable_scope?(key, @context.object) add_scope(key, value) - elsif !Ransack.options[:ignore_unknown_conditions] + elsif !Ransack.options[:ignore_unknown_conditions] || !@ignore_unknown_conditions raise ArgumentError, "Invalid search term #{key}" end end diff --git a/spec/ransack/adapters/active_record/base_spec.rb b/spec/ransack/adapters/active_record/base_spec.rb index 180d5e6a1..3ede567d1 100644 --- a/spec/ransack/adapters/active_record/base_spec.rb +++ b/spec/ransack/adapters/active_record/base_spec.rb @@ -122,6 +122,10 @@ module ActiveRecord expect { Person.ransack('') }.to_not raise_error end + it 'raises exception if ransack! called with unknown condition' do + expect { Person.ransack!(unknown_attr_eq: 'Ernie') }.to raise_error + end + it 'does not modify the parameters' do params = { name_eq: '' } expect { Person.ransack(params) }.not_to change { params } diff --git a/spec/ransack/search_spec.rb b/spec/ransack/search_spec.rb index a824f1373..0b134b2c5 100644 --- a/spec/ransack/search_spec.rb +++ b/spec/ransack/search_spec.rb @@ -232,7 +232,7 @@ module Ransack context 'with an invalid condition' do subject { Search.new(Person, unknown_attr_eq: 'Ernie') } - context 'when ignore_unknown_conditions is false' do + context 'when ignore_unknown_conditions configuration option is false' do before do Ransack.configure { |c| c.ignore_unknown_conditions = false } end @@ -240,13 +240,39 @@ module Ransack specify { expect { subject }.to raise_error ArgumentError } end - context 'when ignore_unknown_conditions is true' do + context 'when ignore_unknown_conditions configuration option is true' do before do Ransack.configure { |c| c.ignore_unknown_conditions = true } end specify { expect { subject }.not_to raise_error } end + + subject(:with_ignore_unknown_conditions_false) { + Search.new(Person, + { unknown_attr_eq: 'Ernie' }, + { ignore_unknown_conditions: false } + ) + } + + subject(:with_ignore_unknown_conditions_true) { + Search.new(Person, + { unknown_attr_eq: 'Ernie' }, + { ignore_unknown_conditions: true } + ) + } + + context 'when ignore_unknown_conditions search parameter is absent' do + specify { expect { subject }.not_to raise_error } + end + + context 'when ignore_unknown_conditions search parameter is false' do + specify { expect { with_ignore_unknown_conditions_false }.to raise_error ArgumentError } + end + + context 'when ignore_unknown_conditions search parameter is true' do + specify { expect { with_ignore_unknown_conditions_true }.not_to raise_error } + end end it 'does not modify the parameters' do