Rails scope
returns all
(ActiveRecord::Relation
) instead of nil
.
So that I can use method chain when condition
is nil
.
class MyClass < ApplicationRecord
scope :my_filter, ->(condition) { where(condition: condition) if condition.present? }
end
MyClass.where(foo: 'foo').my_filter(condition).order(:date)
I want to implement similar functionality in Sequel, but this code doesn't work well because all in Sequel returns an Array. How can I write a functionality in Sequel similar to Rails scope?
class MyClass < Sequel::Model
dataset_module do
def my_filter(condition)
return all if condition.nil?
where(condition: condition)
end
end
end
Since where
returns a Dataset
I am assuming you would also like "all" to return the same object.
As you have identified all
will return an Array
; however you can retrieve the Dataset
by using either clone
or self
So we can just change your implementation to:
class MyClass < Sequel::Model
datase_module do
def my_filter(condition)
return clone if condition.nil?
where(condition: condition)
end
end
end
Working Example: https://replit.com/@engineersmnky/SequelGemRailsScope#main.rb
Additional Info:
I chose clone
because most query methods utilize this method (similar to spawn
in ActiveRecord
).
Dataset#clone
looks like this
def clone(opts = nil || (return self))
c = super(:freeze=>false)
c.opts.merge!(opts)
unless opts.each_key{|o| break if COLUMN_CHANGE_OPTS.include?(o)}
c.clear_columns_cache
end
c.freeze
end
clone
's method signature shortcuts execution if no condition is passed and simply returns self
.
As stated in the comments
return self used above because clone is called by almost all other query methods, and it is the fastest approach
However the comments do also state
This method should generally not be called directly by user code.
So you could choose to just use return self
instead.*
*I implemented both options in my Example above to show their identical functionality plus that method signature is pretty interesting