activeentity 0.0.1.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +42 -0
  3. data/README.md +145 -0
  4. data/Rakefile +29 -0
  5. data/lib/active_entity.rb +73 -0
  6. data/lib/active_entity/aggregations.rb +276 -0
  7. data/lib/active_entity/associations.rb +146 -0
  8. data/lib/active_entity/associations/embedded/association.rb +134 -0
  9. data/lib/active_entity/associations/embedded/builder/association.rb +100 -0
  10. data/lib/active_entity/associations/embedded/builder/collection_association.rb +69 -0
  11. data/lib/active_entity/associations/embedded/builder/embedded_in.rb +38 -0
  12. data/lib/active_entity/associations/embedded/builder/embeds_many.rb +13 -0
  13. data/lib/active_entity/associations/embedded/builder/embeds_one.rb +16 -0
  14. data/lib/active_entity/associations/embedded/builder/singular_association.rb +28 -0
  15. data/lib/active_entity/associations/embedded/collection_association.rb +188 -0
  16. data/lib/active_entity/associations/embedded/collection_proxy.rb +310 -0
  17. data/lib/active_entity/associations/embedded/embedded_in_association.rb +31 -0
  18. data/lib/active_entity/associations/embedded/embeds_many_association.rb +15 -0
  19. data/lib/active_entity/associations/embedded/embeds_one_association.rb +19 -0
  20. data/lib/active_entity/associations/embedded/singular_association.rb +35 -0
  21. data/lib/active_entity/attribute_assignment.rb +85 -0
  22. data/lib/active_entity/attribute_decorators.rb +90 -0
  23. data/lib/active_entity/attribute_methods.rb +330 -0
  24. data/lib/active_entity/attribute_methods/before_type_cast.rb +78 -0
  25. data/lib/active_entity/attribute_methods/primary_key.rb +98 -0
  26. data/lib/active_entity/attribute_methods/query.rb +35 -0
  27. data/lib/active_entity/attribute_methods/read.rb +47 -0
  28. data/lib/active_entity/attribute_methods/serialization.rb +90 -0
  29. data/lib/active_entity/attribute_methods/time_zone_conversion.rb +91 -0
  30. data/lib/active_entity/attribute_methods/write.rb +63 -0
  31. data/lib/active_entity/attributes.rb +165 -0
  32. data/lib/active_entity/base.rb +303 -0
  33. data/lib/active_entity/coders/json.rb +15 -0
  34. data/lib/active_entity/coders/yaml_column.rb +50 -0
  35. data/lib/active_entity/core.rb +281 -0
  36. data/lib/active_entity/define_callbacks.rb +17 -0
  37. data/lib/active_entity/enum.rb +234 -0
  38. data/lib/active_entity/errors.rb +80 -0
  39. data/lib/active_entity/gem_version.rb +17 -0
  40. data/lib/active_entity/inheritance.rb +278 -0
  41. data/lib/active_entity/integration.rb +78 -0
  42. data/lib/active_entity/locale/en.yml +45 -0
  43. data/lib/active_entity/model_schema.rb +115 -0
  44. data/lib/active_entity/nested_attributes.rb +592 -0
  45. data/lib/active_entity/readonly_attributes.rb +47 -0
  46. data/lib/active_entity/reflection.rb +441 -0
  47. data/lib/active_entity/serialization.rb +25 -0
  48. data/lib/active_entity/store.rb +242 -0
  49. data/lib/active_entity/translation.rb +24 -0
  50. data/lib/active_entity/type.rb +73 -0
  51. data/lib/active_entity/type/date.rb +9 -0
  52. data/lib/active_entity/type/date_time.rb +9 -0
  53. data/lib/active_entity/type/decimal_without_scale.rb +15 -0
  54. data/lib/active_entity/type/hash_lookup_type_map.rb +25 -0
  55. data/lib/active_entity/type/internal/timezone.rb +17 -0
  56. data/lib/active_entity/type/json.rb +30 -0
  57. data/lib/active_entity/type/modifiers/array.rb +72 -0
  58. data/lib/active_entity/type/registry.rb +92 -0
  59. data/lib/active_entity/type/serialized.rb +71 -0
  60. data/lib/active_entity/type/text.rb +11 -0
  61. data/lib/active_entity/type/time.rb +21 -0
  62. data/lib/active_entity/type/type_map.rb +62 -0
  63. data/lib/active_entity/type/unsigned_integer.rb +17 -0
  64. data/lib/active_entity/validate_embedded_association.rb +305 -0
  65. data/lib/active_entity/validations.rb +50 -0
  66. data/lib/active_entity/validations/absence.rb +25 -0
  67. data/lib/active_entity/validations/associated.rb +60 -0
  68. data/lib/active_entity/validations/length.rb +26 -0
  69. data/lib/active_entity/validations/presence.rb +68 -0
  70. data/lib/active_entity/validations/subset.rb +76 -0
  71. data/lib/active_entity/validations/uniqueness_in_embedding.rb +99 -0
  72. data/lib/active_entity/version.rb +10 -0
  73. data/lib/tasks/active_entity_tasks.rake +6 -0
  74. metadata +155 -0
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model/attribute/user_provided_default"
4
+
5
+ module ActiveEntity
6
+ # See ActiveEntity::Attributes::ClassMethods for documentation
7
+ module Attributes
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false, default: {} # :internal:
12
+ end
13
+
14
+ module ClassMethods
15
+ # Defines an attribute with a type on this model.
16
+ #
17
+ # +name+ The name of the methods to define attribute methods for, and the
18
+ # column which this will persist to.
19
+ #
20
+ # +cast_type+ A symbol such as +:string+ or +:integer+, or a type object
21
+ # to be used for this attribute. See the examples below for more
22
+ # information about providing custom type objects.
23
+ #
24
+ # ==== Options
25
+ #
26
+ # The following options are accepted:
27
+ #
28
+ # +default+ The default value to use when no value is provided. If this option
29
+ # is not passed, the previous default value (if any) will be used.
30
+ # Otherwise, the default will be +nil+.
31
+ #
32
+ # +array+ Specifies that the type should be an array (see the
33
+ # examples below).
34
+ #
35
+ # ==== Examples
36
+ #
37
+ # # app/models/my_model.rb
38
+ # class MyModel < ActiveEntity::Base
39
+ # attribute :my_string, :string
40
+ # attribute :my_int_array, :integer, array: true
41
+ # attribute :my_float_range, :float, range: true
42
+ # end
43
+ #
44
+ # model = MyModel.new(
45
+ # my_string: "string",
46
+ # my_int_array: ["1", "2", "3"],
47
+ # my_float_range: "[1,3.5]",
48
+ # )
49
+ # model.attributes
50
+ # # =>
51
+ # {
52
+ # my_string: "string",
53
+ # my_int_array: [1, 2, 3],
54
+ # my_float_range: 1.0..3.5
55
+ # }
56
+ #
57
+ # ==== Creating Custom Types
58
+ #
59
+ # Users may also define their own custom types, as long as they respond
60
+ # to the methods defined on the value type. The method +deserialize+ or
61
+ # +cast+ will be called on your type object, with raw input from the
62
+ # database or from your controllers. See ActiveModel::Type::Value for the
63
+ # expected API. It is recommended that your type objects inherit from an
64
+ # existing type, or from ActiveEntity::Type::Value
65
+ #
66
+ # class MoneyType < ActiveEntity::Type::Integer
67
+ # def cast(value)
68
+ # if !value.kind_of?(Numeric) && value.include?('$')
69
+ # price_in_dollars = value.gsub(/\$/, '').to_f
70
+ # super(price_in_dollars * 100)
71
+ # else
72
+ # super
73
+ # end
74
+ # end
75
+ # end
76
+ #
77
+ # # config/initializers/types.rb
78
+ # ActiveEntity::Type.register(:money, MoneyType)
79
+ #
80
+ # # app/models/store_listing.rb
81
+ # class StoreListing < ActiveEntity::Base
82
+ # attribute :price_in_cents, :money
83
+ # end
84
+ #
85
+ # store_listing = StoreListing.new(price_in_cents: '$10.00')
86
+ # store_listing.price_in_cents # => 1000
87
+ #
88
+ # For more details on creating custom types, see the documentation for
89
+ # ActiveModel::Type::Value. For more details on registering your types
90
+ # to be referenced by a symbol, see ActiveEntity::Type.register. You can
91
+ # also pass a type object directly, in place of a symbol.
92
+ #
93
+ # ==== Dirty Tracking
94
+ #
95
+ # The type of an attribute is given the opportunity to change how dirty
96
+ # tracking is performed. The methods +changed?+ and +changed_in_place?+
97
+ # will be called from ActiveModel::Dirty. See the documentation for those
98
+ # methods in ActiveModel::Type::Value for more details.
99
+ def attribute(name, cast_type = Type::Value.new, **options)
100
+ name = name.to_s
101
+ reload_schema_from_cache
102
+
103
+ self.attributes_to_define_after_schema_loads =
104
+ attributes_to_define_after_schema_loads.merge(
105
+ name => [cast_type, options]
106
+ )
107
+ end
108
+
109
+ # This is the low level API which sits beneath +attribute+. It only
110
+ # accepts type objects, and will do its work immediately instead of
111
+ # waiting for the schema to load. Automatic schema detection and
112
+ # ClassMethods#attribute both call this under the hood. While this method
113
+ # is provided so it can be used by plugin authors, application code
114
+ # should probably use ClassMethods#attribute.
115
+ #
116
+ # +name+ The name of the attribute being defined. Expected to be a +String+.
117
+ #
118
+ # +cast_type+ The type object to use for this attribute.
119
+ #
120
+ # +default+ The default value to use when no value is provided. If this option
121
+ # is not passed, the previous default value (if any) will be used.
122
+ # Otherwise, the default will be +nil+. A proc can also be passed, and
123
+ # will be called once each time a new value is needed.
124
+ def define_attribute(
125
+ name,
126
+ cast_type,
127
+ default: NO_DEFAULT_PROVIDED
128
+ )
129
+ attribute_types[name] = cast_type
130
+ define_default_attribute(name, default, cast_type)
131
+ end
132
+
133
+ def load_schema! # :nodoc:
134
+ super
135
+ attributes_to_define_after_schema_loads.each do |name, (type, options)|
136
+ if type.is_a?(Symbol)
137
+ type = ActiveEntity::Type.lookup(type, **options.except(:default))
138
+ end
139
+
140
+ define_attribute(name, type, **options.slice(:default))
141
+ end
142
+ end
143
+
144
+ private
145
+
146
+ NO_DEFAULT_PROVIDED = Object.new # :nodoc:
147
+ private_constant :NO_DEFAULT_PROVIDED
148
+
149
+ def define_default_attribute(name, value, type)
150
+ default_attribute =
151
+ if value == NO_DEFAULT_PROVIDED
152
+ _default_attributes[name].with_type(type)
153
+ else
154
+ ActiveModel::Attribute::UserProvidedDefault.new(
155
+ name,
156
+ value,
157
+ type,
158
+ _default_attributes.fetch(name.to_s) { nil },
159
+ )
160
+ end
161
+ _default_attributes[name] = default_attribute
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,303 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "active_support/benchmarkable"
5
+ require "active_support/dependencies"
6
+ require "active_support/descendants_tracker"
7
+ require "active_support/time"
8
+ require "active_support/core_ext/module/attribute_accessors"
9
+ require "active_support/core_ext/array/extract_options"
10
+ require "active_support/core_ext/hash/deep_merge"
11
+ require "active_support/core_ext/hash/slice"
12
+ require "active_support/core_ext/string/behavior"
13
+ require "active_support/core_ext/kernel/singleton_class"
14
+ require "active_support/core_ext/module/introspection"
15
+ require "active_support/core_ext/object/duplicable"
16
+ require "active_support/core_ext/class/subclasses"
17
+ require "active_entity/attribute_decorators"
18
+ require "active_entity/define_callbacks"
19
+ require "active_entity/errors"
20
+ require "active_entity/attributes"
21
+
22
+ module ActiveEntity #:nodoc:
23
+ # = Active Entity
24
+ #
25
+ # Active Entity objects don't specify their attributes directly, but rather infer them from
26
+ # the table definition with which they're linked. Adding, removing, and changing attributes
27
+ # and their type is done directly in the database. Any change is instantly reflected in the
28
+ # Active Entity objects. The mapping that binds a given Active Entity class to a certain
29
+ # database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.
30
+ #
31
+ # See the mapping rules in table_name and the full example in link:files/activerecord/README_rdoc.html for more insight.
32
+ #
33
+ # == Creation
34
+ #
35
+ # Active Entitys accept constructor parameters either in a hash or as a block. The hash
36
+ # method is especially useful when you're receiving the data from somewhere else, like an
37
+ # HTTP request. It works like this:
38
+ #
39
+ # user = User.new(name: "David", occupation: "Code Artist")
40
+ # user.name # => "David"
41
+ #
42
+ # You can also use block initialization:
43
+ #
44
+ # user = User.new do |u|
45
+ # u.name = "David"
46
+ # u.occupation = "Code Artist"
47
+ # end
48
+ #
49
+ # And of course you can just create a bare object and specify the attributes after the fact:
50
+ #
51
+ # user = User.new
52
+ # user.name = "David"
53
+ # user.occupation = "Code Artist"
54
+ #
55
+ # == Conditions
56
+ #
57
+ # Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
58
+ # The array form is to be used when the condition input is tainted and requires sanitization. The string form can
59
+ # be used for statements that don't involve tainted data. The hash form works much like the array form, except
60
+ # only equality and range is possible. Examples:
61
+ #
62
+ # class User < ActiveEntity::Base
63
+ # def self.authenticate_unsafely(user_name, password)
64
+ # where("user_name = '#{user_name}' AND password = '#{password}'").first
65
+ # end
66
+ #
67
+ # def self.authenticate_safely(user_name, password)
68
+ # where("user_name = ? AND password = ?", user_name, password).first
69
+ # end
70
+ #
71
+ # def self.authenticate_safely_simply(user_name, password)
72
+ # where(user_name: user_name, password: password).first
73
+ # end
74
+ # end
75
+ #
76
+ # The <tt>authenticate_unsafely</tt> method inserts the parameters directly into the query
77
+ # and is thus susceptible to SQL-injection attacks if the <tt>user_name</tt> and +password+
78
+ # parameters come directly from an HTTP request. The <tt>authenticate_safely</tt> and
79
+ # <tt>authenticate_safely_simply</tt> both will sanitize the <tt>user_name</tt> and +password+
80
+ # before inserting them in the query, which will ensure that an attacker can't escape the
81
+ # query and fake the login (or worse).
82
+ #
83
+ # When using multiple parameters in the conditions, it can easily become hard to read exactly
84
+ # what the fourth or fifth question mark is supposed to represent. In those cases, you can
85
+ # resort to named bind variables instead. That's done by replacing the question marks with
86
+ # symbols and supplying a hash with values for the matching symbol keys:
87
+ #
88
+ # Company.where(
89
+ # "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
90
+ # { id: 3, name: "37signals", division: "First", accounting_date: '2005-01-01' }
91
+ # ).first
92
+ #
93
+ # Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND
94
+ # operator. For instance:
95
+ #
96
+ # Student.where(first_name: "Harvey", status: 1)
97
+ # Student.where(params[:student])
98
+ #
99
+ # A range may be used in the hash to use the SQL BETWEEN operator:
100
+ #
101
+ # Student.where(grade: 9..12)
102
+ #
103
+ # An array may be used in the hash to use the SQL IN operator:
104
+ #
105
+ # Student.where(grade: [9,11,12])
106
+ #
107
+ # When joining tables, nested hashes or keys written in the form 'table_name.column_name'
108
+ # can be used to qualify the table name of a particular condition. For instance:
109
+ #
110
+ # Student.joins(:schools).where(schools: { category: 'public' })
111
+ # Student.joins(:schools).where('schools.category' => 'public' )
112
+ #
113
+ # == Overwriting default accessors
114
+ #
115
+ # All column values are automatically available through basic accessors on the Active Entity
116
+ # object, but sometimes you want to specialize this behavior. This can be done by overwriting
117
+ # the default accessors (using the same name as the attribute) and calling
118
+ # +super+ to actually change things.
119
+ #
120
+ # class Song < ActiveEntity::Base
121
+ # # Uses an integer of seconds to hold the length of the song
122
+ #
123
+ # def length=(minutes)
124
+ # super(minutes.to_i * 60)
125
+ # end
126
+ #
127
+ # def length
128
+ # super / 60
129
+ # end
130
+ # end
131
+ #
132
+ # == Attribute query methods
133
+ #
134
+ # In addition to the basic accessors, query methods are also automatically available on the Active Entity object.
135
+ # Query methods allow you to test whether an attribute value is present.
136
+ # Additionally, when dealing with numeric values, a query method will return false if the value is zero.
137
+ #
138
+ # For example, an Active Entity User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
139
+ # to determine whether the user has a name:
140
+ #
141
+ # user = User.new(name: "David")
142
+ # user.name? # => true
143
+ #
144
+ # anonymous = User.new(name: "")
145
+ # anonymous.name? # => false
146
+ #
147
+ # == Accessing attributes before they have been typecasted
148
+ #
149
+ # Sometimes you want to be able to read the raw attribute data without having the column-determined
150
+ # typecast run its course first. That can be done by using the <tt><attribute>_before_type_cast</tt>
151
+ # accessors that all attributes have. For example, if your Account model has a <tt>balance</tt> attribute,
152
+ # you can call <tt>account.balance_before_type_cast</tt> or <tt>account.id_before_type_cast</tt>.
153
+ #
154
+ # This is especially useful in validation situations where the user might supply a string for an
155
+ # integer field and you want to display the original string back in an error message. Accessing the
156
+ # attribute normally would typecast the string to 0, which isn't what you want.
157
+ #
158
+ # == Dynamic attribute-based finders
159
+ #
160
+ # Dynamic attribute-based finders are a mildly deprecated way of getting (and/or creating) objects
161
+ # by simple queries without turning to SQL. They work by appending the name of an attribute
162
+ # to <tt>find_by_</tt> like <tt>Person.find_by_user_name</tt>.
163
+ # Instead of writing <tt>Person.find_by(user_name: user_name)</tt>, you can use
164
+ # <tt>Person.find_by_user_name(user_name)</tt>.
165
+ #
166
+ # It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
167
+ # ActiveEntity::RecordNotFound error if they do not return any records,
168
+ # like <tt>Person.find_by_last_name!</tt>.
169
+ #
170
+ # It's also possible to use multiple attributes in the same <tt>find_by_</tt> by separating them with
171
+ # "_and_".
172
+ #
173
+ # Person.find_by(user_name: user_name, password: password)
174
+ # Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
175
+ #
176
+ # It's even possible to call these dynamic finder methods on relations and named scopes.
177
+ #
178
+ # Payment.order("created_on").find_by_amount(50)
179
+ #
180
+ # == Saving arrays, hashes, and other non-mappable objects in text columns
181
+ #
182
+ # Active Entity can serialize any object in text columns using YAML. To do so, you must
183
+ # specify this with a call to the class method
184
+ # {serialize}[rdoc-ref:AttributeMethods::Serialization::ClassMethods#serialize].
185
+ # This makes it possible to store arrays, hashes, and other non-mappable objects without doing
186
+ # any additional work.
187
+ #
188
+ # class User < ActiveEntity::Base
189
+ # serialize :preferences
190
+ # end
191
+ #
192
+ # user = User.create(preferences: { "background" => "black", "display" => large })
193
+ # User.find(user.id).preferences # => { "background" => "black", "display" => large }
194
+ #
195
+ # You can also specify a class option as the second parameter that'll raise an exception
196
+ # if a serialized object is retrieved as a descendant of a class not in the hierarchy.
197
+ #
198
+ # class User < ActiveEntity::Base
199
+ # serialize :preferences, Hash
200
+ # end
201
+ #
202
+ # user = User.create(preferences: %w( one two three ))
203
+ # User.find(user.id).preferences # raises SerializationTypeMismatch
204
+ #
205
+ # When you specify a class option, the default value for that attribute will be a new
206
+ # instance of that class.
207
+ #
208
+ # class User < ActiveEntity::Base
209
+ # serialize :preferences, OpenStruct
210
+ # end
211
+ #
212
+ # user = User.new
213
+ # user.preferences.theme_color = "red"
214
+ #
215
+ #
216
+ # == Single table inheritance
217
+ #
218
+ # Active Entity allows inheritance by storing the name of the class in a
219
+ # column that is named "type" by default. See ActiveEntity::Inheritance for
220
+ # more details.
221
+ #
222
+ # == Connection to multiple databases in different models
223
+ #
224
+ # Connections are usually created through
225
+ # {ActiveEntity::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] and retrieved
226
+ # by ActiveEntity::Base.connection. All classes inheriting from ActiveEntity::Base will use this
227
+ # connection. But you can also set a class-specific connection. For example, if Course is an
228
+ # ActiveEntity::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
229
+ # and Course and all of its subclasses will use this connection instead.
230
+ #
231
+ # This feature is implemented by keeping a connection pool in ActiveEntity::Base that is
232
+ # a hash indexed by the class. If a connection is requested, the
233
+ # {ActiveEntity::Base.retrieve_connection}[rdoc-ref:ConnectionHandling#retrieve_connection] method
234
+ # will go up the class-hierarchy until a connection is found in the connection pool.
235
+ #
236
+ # == Exceptions
237
+ #
238
+ # * ActiveEntityError - Generic error class and superclass of all other errors raised by Active Entity.
239
+ # * AdapterNotSpecified - The configuration hash used in
240
+ # {ActiveEntity::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
241
+ # didn't include an <tt>:adapter</tt> key.
242
+ # * AdapterNotFound - The <tt>:adapter</tt> key used in
243
+ # {ActiveEntity::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
244
+ # specified a non-existent adapter
245
+ # (or a bad spelling of an existing one).
246
+ # * AssociationTypeMismatch - The object assigned to the association wasn't of the type
247
+ # specified in the association definition.
248
+ # * AttributeAssignmentError - An error occurred while doing a mass assignment through the
249
+ # {ActiveEntity::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
250
+ # You can inspect the +attribute+ property of the exception object to determine which attribute
251
+ # triggered the error.
252
+ # * ConnectionNotEstablished - No connection has been established.
253
+ # Use {ActiveEntity::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying.
254
+ # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
255
+ # {ActiveEntity::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
256
+ # The +errors+ property of this exception contains an array of
257
+ # AttributeAssignmentError
258
+ # objects that should be inspected to determine which attributes triggered the errors.
259
+ # * RecordInvalid - raised by {ActiveEntity::Base#save!}[rdoc-ref:Persistence#save!] and
260
+ # {ActiveEntity::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
261
+ # when the record is invalid.
262
+ # * RecordNotFound - No record responded to the {ActiveEntity::Base.find}[rdoc-ref:FinderMethods#find] method.
263
+ # Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions.
264
+ # Some {ActiveEntity::Base.find}[rdoc-ref:FinderMethods#find] calls do not raise this exception to signal
265
+ # nothing was found, please check its documentation for further details.
266
+ # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
267
+ # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
268
+ #
269
+ # *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
270
+ # So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
271
+ # instances in the current object space.
272
+ class Base
273
+ extend ActiveModel::Naming
274
+
275
+ extend ActiveSupport::Benchmarkable
276
+ extend ActiveSupport::DescendantsTracker
277
+
278
+ extend Translation
279
+ extend Enum
280
+ extend Aggregations::ClassMethods
281
+
282
+ include Core
283
+ include ReadonlyAttributes
284
+ include ModelSchema
285
+ include Inheritance
286
+ include AttributeAssignment
287
+ include ActiveModel::Conversion
288
+ include Integration
289
+ include Validations
290
+ include Attributes
291
+ include AttributeDecorators
292
+ include DefineCallbacks
293
+ include AttributeMethods
294
+ include Associations
295
+ include ValidateEmbeddedAssociation
296
+ include NestedAttributes
297
+ include Reflection
298
+ include Serialization
299
+ include Store
300
+ end
301
+
302
+ ActiveSupport.run_load_hooks(:active_entity, Base)
303
+ end