File: update_refresh.rb

package info (click to toggle)
ruby-sequel 5.63.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,408 kB
  • sloc: ruby: 113,747; makefile: 3
file content (88 lines) | stat: -rw-r--r-- 2,891 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
# frozen-string-literal: true

module Sequel
  module Plugins
    # The update_refresh plugin makes the model class refresh
    # the object after updating.  By default, Sequel only
    # refreshes automatically after inserting new rows, not
    # after updating.  However, if you are using triggers
    # to modify the contents of updated rows, it can be
    # helpful to immediately get the current data after
    # updating.
    #
    # If the dataset supports UPDATE RETURNING, this
    # plugin will use it so that it can retrieve the current
    # data in the same query it uses for the update.
    #
    # Usage:
    #
    #   # Make all model subclasses refresh after update
    #   Sequel::Model.plugin :update_refresh
    #
    #   # Make the Album class refresh after update
    #   Album.plugin :update_refresh
    #
    # As a performance optimisation, if you know only specific
    # columns will have changed, you can specify them to the
    # +columns+ option. This can be a performance gain if it
    # would avoid pointlessly comparing many other columns.
    # Note that this option currently only has an effect if the
    # dataset supports RETURNING.
    #
    #   # Only include the artist column in RETURNING
    #   Album.plugin :update_refresh, columns: :artist
    #
    #   # Only include the artist and title columns in RETURNING
    #   Album.plugin :update_refresh, columns: [:artist, :title]
    module UpdateRefresh
      # Set the specific columns to refresh, if the :columns option
      # is provided.
      def self.configure(model, opts=OPTS)
        model.instance_exec do
          @update_refresh_columns = Array(opts[:columns]) || []
        end
      end

      module ClassMethods
        # The specific columns to refresh when updating, if UPDATE RETURNING is supported.
        attr_reader :update_refresh_columns

        # Freeze the update refresh columns when freezing the model class.
        def freeze
          @update_refresh_columns.freeze

          super
        end
      end

      module InstanceMethods
        # If the dataset does not support UPDATE RETURNING, then refresh after an update.
        def after_update
          super
          unless this.supports_returning?(:update)
            refresh
          end
        end

        private

        # If the dataset supports UPDATE RETURNING, use it to do the refresh in the same
        # query as the update.
        def _update_without_checking(columns)
          ds = _update_dataset
          if ds.supports_returning?(:update)
            ds = ds.opts[:returning] ? ds : ds.returning(*self.class.update_refresh_columns)
            rows = ds.update(columns)
            n = rows.length
            if n == 1
              @values.merge!(rows.first)
            end
            n
          else
            super
          end
        end
      end
    end
  end
end