File: acts_as_sequenced.rb

package info (click to toggle)
ruby-sequenced 3.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,884 kB
  • sloc: ruby: 696; makefile: 3
file content (74 lines) | stat: -rw-r--r-- 2,519 bytes parent folder | download | duplicates (3)
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
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/class/attribute_accessors'

module Sequenced
  module ActsAsSequenced
    DEFAULT_OPTIONS = {
      column: :sequential_id,
      start_at: 1
    }.freeze
    SequencedColumnExists = Class.new(StandardError)

    def self.included(base)
      base.extend ClassMethods
    end

    module ClassMethods
      # Public: Defines ActiveRecord callbacks to set a sequential ID scoped
      # on a specific class.
      #
      # Can be called multiple times to add hooks for different column names.
      #
      # options - The Hash of options for configuration:
      #           :scope    - The Symbol representing the columm on which the
      #                       sequential ID should be scoped (default: nil)
      #           :column   - The Symbol representing the column that stores the
      #                       sequential ID (default: :sequential_id)
      #           :start_at - The Integer value at which the sequence should
      #                       start (default: 1)
      #           :skip     - Skips the sequential ID generation when the lambda
      #                       expression evaluates to nil. Gets passed the
      #                       model object
      #
      # Examples
      #
      #   class Answer < ActiveRecord::Base
      #     belongs_to :question
      #     acts_as_sequenced :scope => :question_id
      #   end
      #
      # Returns nothing.
      def acts_as_sequenced(options = {})
        unless defined?(sequenced_options)
          include Sequenced::ActsAsSequenced::InstanceMethods

          mattr_accessor :sequenced_options, instance_accessor: false
          self.sequenced_options = []

          before_save :set_sequential_ids
        end

        options = DEFAULT_OPTIONS.merge(options)
        column_name = options[:column]

        if sequenced_options.any? {|options| options[:column] == column_name}
          raise(SequencedColumnExists, <<-MSG.squish)
            Tried to set #{column_name} as sequenced but there was already a
            definition here. Did you accidentally call acts_as_sequenced
            multiple times on the same column?
          MSG
        else
          sequenced_options << options
        end
      end
    end

    module InstanceMethods
      def set_sequential_ids
        self.class.base_class.sequenced_options.each do |options|
          Sequenced::Generator.new(self, options).set
        end
      end
    end
  end
end