File: def_dataset_method.rb

package info (click to toggle)
ruby-sequel 5.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 8,856 kB
  • sloc: ruby: 95,762; makefile: 3
file content (90 lines) | stat: -rw-r--r-- 3,683 bytes parent folder | download | duplicates (4)
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