aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/model.rb
blob: 5fcb0359c52f6c749a7c2a0783c1b0aaa29744e0 (plain) (blame)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
require 'active_support/core_ext/module/attribute_accessors'

module ActiveRecord
  module Configuration # :nodoc:
    # This just abstracts out how we define configuration options in AR. Essentially we
    # have mattr_accessors on the ActiveRecord:Model constant that define global defaults.
    # Classes that then use AR get class_attributes defined, which means that when they
    # are assigned the default will be overridden for that class and subclasses. (Except
    # when options[:global] == true, in which case there is one global value always.)
    def config_attribute(name, options = {})
      if options[:global]
        class_eval <<-CODE, __FILE__, __LINE__ + 1
          def self.#{name};       ActiveRecord::Model.#{name};       end
          def #{name};            ActiveRecord::Model.#{name};       end
          def self.#{name}=(val); ActiveRecord::Model.#{name} = val; end
        CODE
      else
        options[:instance_writer] ||= false
        class_attribute name, options

        singleton_class.class_eval <<-CODE, __FILE__, __LINE__ + 1
          remove_method :#{name}
          def #{name}; ActiveRecord::Model.#{name}; end
        CODE
      end
    end
  end

  # This allows us to detect an ActiveRecord::Model while it's in the process of
  # being included.
  module Tag; end

  # <tt>ActiveRecord::Model</tt> can be included into a class to add Active Record
  # persistence. This is an alternative to inheriting from <tt>ActiveRecord::Base</tt>.
  #
  #     class Post
  #       include ActiveRecord::Model
  #     end
  module Model
    extend ActiveSupport::Concern
    extend ConnectionHandling
    extend ActiveModel::Observing::ClassMethods

    def self.append_features(base)
      base.class_eval do
        include Tag
        extend Configuration
      end

      super
    end

    included do
      extend ActiveModel::Naming
      extend ActiveSupport::Benchmarkable
      extend ActiveSupport::DescendantsTracker

      extend QueryCache::ClassMethods
      extend Querying
      extend Translation
      extend DynamicMatchers
      extend Explain
      extend ConnectionHandling

      initialize_generated_modules unless self == Base
    end

    include Persistence
    include ReadonlyAttributes
    include ModelSchema
    include Inheritance
    include Scoping
    include Sanitization
    include AttributeAssignment
    include ActiveModel::Conversion
    include Integration
    include Validations
    include CounterCache
    include Locking::Optimistic
    include Locking::Pessimistic
    include AttributeMethods
    include Callbacks
    include ActiveModel::Observing
    include Timestamp
    include Associations
    include ActiveModel::SecurePassword
    include AutosaveAssociation
    include NestedAttributes
    include Aggregations
    include Transactions
    include Reflection
    include Serialization
    include Store
    include Core

    class << self
      def arel_engine
        self
      end

      def abstract_class?
        false
      end

      # Defines the name of the table column which will store the class name on single-table
      # inheritance situations.
      #
      # The default inheritance column name is +type+, which means it's a
      # reserved word inside Active Record. To be able to use single-table
      # inheritance with another column name, or to use the column +type+ in
      # your own model for something else, you can set +inheritance_column+:
      #
      #     self.inheritance_column = 'zoink'
      def inheritance_column
        'type'
      end
    end
  end

  # This hook is where config accessors on Model should be defined.
  #
  # We don't want to just open the Model module and add stuff to it in other files, because
  # that would cause Model to load, which causes all sorts of loading order issues.
  #
  # We need this hook rather than just using the :active_record one, because users of the
  # :active_record hook may need to use config options.
  #
  # Users who wish to include a module in Model that they want to also
  # get inherited by Base should do so using this load hook. After Base
  # has included Model, any modules subsequently included in Model won't
  # be inherited by Base.
  ActiveSupport.run_load_hooks(:active_record_model, Model)

  # Load Base at this point, because the active_record load hook is run in that file.
  Base
end