Skip to content

Commit bd50baa

Browse files
author
Ivan Tyurin
committed
Add dataset filter methods
1 parent f879a1d commit bd50baa

2 files changed

Lines changed: 96 additions & 16 deletions

File tree

lib/sequel/plugins/enum_values.rb

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,21 @@ def self.configure(model, options = {})
3535
model.instance_exec do
3636
@enum_values_caching = options.fetch(:caching, @enum_values_caching)
3737

38-
predicate_methods = options.fetch(:predicate_methods, false)
38+
initialize_predicate_methods options.fetch(:predicate_methods, false)
3939

40-
transform_predicate_methods_to_enum_fields(predicate_methods)
41-
.each do |field|
42-
all_enum_fields[field][:enum_values].each do |enum_value|
43-
define_predicate_method field, enum_value
44-
end
45-
end
40+
@predicate_methods.each do |field|
41+
all_enum_fields[field][:enum_values]
42+
.each { |enum_value| define_predicate_method field, enum_value }
43+
end
44+
45+
create_enum_subsets if @dataset
4646
end
4747
end
4848

4949
## Module for class methods
5050
module ClassMethods
51+
Plugins.after_set_dataset(self, :create_enum_subsets)
52+
5153
## Get enum values for specific field
5254
## @param field [Symbol] name of enum field
5355
## @return [Array<String>] values of enum
@@ -68,15 +70,16 @@ def enum_values(field)
6870

6971
private
7072

71-
def transform_predicate_methods_to_enum_fields(predicate_methods)
72-
case predicate_methods
73-
when TrueClass
74-
all_enum_fields.keys
75-
when FalseClass
76-
[]
77-
else
78-
Array(predicate_methods)
79-
end
73+
def initialize_predicate_methods(predicate_methods_option)
74+
@predicate_methods =
75+
case predicate_methods_option
76+
when TrueClass
77+
all_enum_fields.keys
78+
when FalseClass
79+
[]
80+
else
81+
Array(predicate_methods_option)
82+
end
8083
end
8184

8285
def define_predicate_method(field, enum_value)
@@ -101,6 +104,27 @@ def raise_field_nonexistent(field)
101104
"'#{table_name}' table does not have '#{field}' column"
102105
)
103106
end
107+
108+
## Creates dataset methods for filtering
109+
## @return [Dataset]
110+
## @example Get dataset with filter for `status` field of `Item` model
111+
## Item.created =>
112+
## "SELECT * FROM \"items\" WHERE (\"status\" = 'created')"
113+
def create_enum_subsets
114+
return if @predicate_methods.empty?
115+
116+
fields =
117+
all_enum_fields
118+
.select { |field, _options| @predicate_methods.include?(field) }
119+
120+
return if fields.empty?
121+
122+
dataset_module do
123+
fields.each do |field, options|
124+
options[:enum_values].each { |value| where value, field => value }
125+
end
126+
end
127+
end
104128
end
105129
end
106130
end

spec/sequel/plugins/enum_values_spec.rb

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,62 @@
229229
end
230230
end
231231
end
232+
233+
describe 'Sequel::Model.enum_filter' do
234+
subject(:enum_filter) { item_class.public_send(enum_value).sql }
235+
236+
let(:predicate_methods) { true }
237+
238+
let(:item_class) do
239+
Class.new(Sequel::Model(:items)).tap do |klass|
240+
klass.plugin :enum_values, predicate_methods: predicate_methods
241+
end
242+
end
243+
244+
def filter_sql(column, value)
245+
"SELECT * FROM \"items\" WHERE (\"#{column}\" = '#{value}')"
246+
end
247+
248+
context 'with existing :type field' do
249+
let(:field) { :type }
250+
251+
context 'with existing field value' do
252+
let(:enum_value) { type_enum_values.first }
253+
254+
it { is_expected.to eq filter_sql(field, enum_value) }
255+
end
256+
257+
context 'with nonexistent field value' do
258+
let(:enum_value) { 'nonexistent' }
259+
260+
it { expect { enum_filter }.to raise_error(NoMethodError) }
261+
end
262+
end
263+
264+
context 'with existing :status field' do
265+
let(:field) { :status }
266+
267+
context 'with existing field value' do
268+
let(:enum_value) { status_enum_values.first }
269+
270+
it { is_expected.to eq filter_sql(field, enum_value) }
271+
end
272+
273+
context 'with nonexistent field value' do
274+
let(:enum_value) { 'nonexistent' }
275+
276+
it { expect { enum_filter }.to raise_error(NoMethodError) }
277+
end
278+
end
279+
280+
context 'with not included to predicate methods enum field' do
281+
let(:predicate_methods) { :status }
282+
let(:field) { :type }
283+
let(:enum_value) { type_enum_values.first }
284+
285+
it { expect { enum_filter }.to raise_error(NoMethodError) }
286+
end
287+
end
232288
end
233289

234290
# connection.drop_table :items

0 commit comments

Comments
 (0)