1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
# frozen-string-literal: true
module Sequel
module Plugins
# The def_dataset_method plugin adds Model.def_dataset_method
# for defining dataset methods:
#
# Album.def_dataset_method(:by_name) do |name|
# where(name: name)
# end
#
# Additionally, this adds support for Model.subset, which can also
# be used to define dataset methods that add specific filters:
#
# Album.subset(:gold){copies_sold >= 500000}
#
# This exists for backwards compatibility with previous Sequel versions.
#
# Usage:
#
# # Make all model subclasses support Model.def_dataset_method
# # (called before loading subclasses)
# Sequel::Model.plugin :def_dataset_method
#
# # Make the Album class support Model.def_dataset_method
# Album.plugin :def_dataset_method
module DefDatasetMethod
module ClassMethods
# If a block is given, define a method on the dataset (if the model currently has an dataset) with the given argument name using
# the given block. Also define a class method on the model that calls the
# dataset method. Stores the method name and block so that it can be reapplied if the model's
# dataset changes.
#
# If a block is not given, just define a class method on the model for each argument
# that calls the dataset method of the same argument name.
#
# Using dataset_module is recommended over using this method. In addition to allowing
# more natural ruby syntax for defining methods manually, it also offers numerous
# helper methods that make defining common dataset methods more easily, as well as
# supporting dataset caching (assuming the arguments allow it).
#
# # Add new dataset method and class method that calls it
# Artist.def_dataset_method(:by_name){order(:name)}
# Artist.where(Sequel[:name].like('A%')).by_name
# Artist.by_name.where(Sequel[:name].like('A%'))
#
# # Just add a class method that calls an existing dataset method
# Artist.def_dataset_method(:paginate)
# Artist.paginate(2, 10)
def def_dataset_method(*args, &block)
raise(Error, "No arguments given") if args.empty?
if block
raise(Error, "Defining a dataset method using a block requires only one argument") if args.length > 1
dataset_module{define_method(args.first, &block)}
else
args.each{|arg| def_model_dataset_method(arg)}
end
end
# Sets up a dataset method that returns a filtered dataset.
# Sometimes thought of as a scope, and like most dataset methods,
# they can be chained.
# For example:
#
# Topic.subset(:joes, Sequel[:username].like('%joe%'))
# Topic.subset(:popular){num_posts > 100}
# Topic.subset(:recent){created_on > Date.today - 7}
#
# Allows you to do:
#
# Topic.joes.recent.popular
#
# to get topics with a username that includes joe that
# have more than 100 posts and were created less than
# 7 days ago.
#
# Both the args given and the block are passed to <tt>Dataset#where</tt>.
#
# This method creates dataset methods that do not accept arguments. To create
# dataset methods that accept arguments, you should use define a
# method directly inside a #dataset_module block.
def subset(*args, &block)
dataset_module{subset(*args, &block)}
end
end
end
end
end
|