active_model_persistence 0.4.0 → 0.5.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +0 -76
- data/lib/active_model_persistence/index.rb +4 -17
- data/lib/active_model_persistence/indexable.rb +8 -12
- data/lib/active_model_persistence/persistence.rb +33 -14
- data/lib/active_model_persistence/primary_key.rb +24 -22
- data/lib/active_model_persistence/primary_key_index.rb +1 -1
- data/lib/active_model_persistence/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3b8a31cdacf32baeaabb6d3c72631002098c9a35630d1c0aff5e836737e42dc
|
4
|
+
data.tar.gz: '00843ca11ad71c596c192d066efc3f43d7e531c068d12bea9866f58bea404b3e'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25984dd367fedae9ead6973601c042a164643e5aaa09e5198ebcc6a8f5dfe333eba73d37f34ca257f61a58f6aca7b6b9326727f337b2d159d5d0bd71db62e0bd
|
7
|
+
data.tar.gz: ca0ddf06112d7e70bb7898f8f3ba0a95f63f5db4f9cf3aee1f6a7d054b3fd5dfb705609844d42ff55d9eab05a7652fb6f2fa086ca8d1a7a97b79e61ee6811cfe
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,13 @@
|
|
7
7
|
|
8
8
|
The full change log is stored on [this project's GitHub releases page](https://github.com/jcouball/active_model_persistence/releases).
|
9
9
|
|
10
|
+
## v0.5.0
|
11
|
+
|
12
|
+
* 87b32e5 Fix the version file after the previous revert (#20)
|
13
|
+
* f4f6c39 Revert "Add inheritance support (#14)" (#19)
|
14
|
+
|
15
|
+
See https://github.com/ruby-git/ruby-git/releases/tag/v0.5.0
|
16
|
+
|
10
17
|
## v0.4.0
|
11
18
|
|
12
19
|
* e491e22 Set the version file back to the correct version (#17)
|
data/README.md
CHANGED
@@ -65,82 +65,6 @@ Employee.find_by_manager_id('boss') #=> [e1, e2]
|
|
65
65
|
# etc.
|
66
66
|
```
|
67
67
|
|
68
|
-
## Inheritance
|
69
|
-
|
70
|
-
ActiveModelPersistence supports inheritance in models. Include
|
71
|
-
`ActiveModelPersistence::Persistence` only in the base class.
|
72
|
-
|
73
|
-
Here is an example with a `User` base class and two derived clases `Employee` and `Member`.
|
74
|
-
Each derived class adds different attributes and indexes.
|
75
|
-
|
76
|
-
```ruby
|
77
|
-
require 'active_model_persistence'
|
78
|
-
|
79
|
-
class User
|
80
|
-
include ActiveModelPersistence::Persistence
|
81
|
-
|
82
|
-
attribute :id, :integer
|
83
|
-
attribute :name, :string
|
84
|
-
end
|
85
|
-
|
86
|
-
class Employee < User
|
87
|
-
attribute :manager_id, :integer
|
88
|
-
|
89
|
-
index :manager_id, unique: false
|
90
|
-
end
|
91
|
-
|
92
|
-
class Member < User
|
93
|
-
attribute :joined_on, :date, default: Date.today
|
94
|
-
|
95
|
-
index :joined_on, unique: false
|
96
|
-
end
|
97
|
-
```
|
98
|
-
|
99
|
-
As an example, say we have one instance of each class:
|
100
|
-
|
101
|
-
```ruby
|
102
|
-
user = User.create!(id: 1, name: 'User James')
|
103
|
-
employee = Employee.create!(id: 2, name: 'Employee Bob', manager_id: nil)
|
104
|
-
member = Member.create!(id: 3, name: 'Member Mary', joined_on: Date.parse('2022-01-01'))
|
105
|
-
```
|
106
|
-
|
107
|
-
The primary key is shared by all objects of these classes so it must be unique for
|
108
|
-
all objects created from these classes. For instance:
|
109
|
-
|
110
|
-
```ruby
|
111
|
-
require 'rspec-expectations'
|
112
|
-
include RSpec::Matchers
|
113
|
-
|
114
|
-
# Creating a Member with the same primary key as a User will fail
|
115
|
-
expect { Member.create!(id: 1, name: 'Member Jason') }.to(
|
116
|
-
raise_error(ActiveModelPersistence::UniqueConstraintError)
|
117
|
-
)
|
118
|
-
```
|
119
|
-
|
120
|
-
Calling a find method such as `find` or `find_by_*` on a class will only return
|
121
|
-
objects that are a kind of that class.
|
122
|
-
|
123
|
-
That means calling a find method on `User` will return users, employees, or members:
|
124
|
-
|
125
|
-
```ruby
|
126
|
-
expect(User.find(1)).to eq(user)
|
127
|
-
expect(User.find(2)).to eq(employee)
|
128
|
-
expect(User.find(3)).to eq(member)
|
129
|
-
```
|
130
|
-
|
131
|
-
While calling a find method on `Employee` will only return employees:
|
132
|
-
|
133
|
-
```ruby
|
134
|
-
expect(Employee.find(1)).to be_nil
|
135
|
-
expect(Employee.find(2)).to eq(employee)
|
136
|
-
expect(Employee.find(3)).to be_nil
|
137
|
-
```
|
138
|
-
|
139
|
-
`all`, `count`, `delete_all`, `destroy_all` and other methods similarly limit what
|
140
|
-
objects are acted upon based on what class they are called on.
|
141
|
-
|
142
|
-
## API Documentation
|
143
|
-
|
144
68
|
See [the full API documentation](https://jcouball.github.io/active_record_persistence/) for more details.
|
145
69
|
|
146
70
|
## Installation
|
@@ -15,18 +15,6 @@ module ActiveModelPersistence
|
|
15
15
|
#
|
16
16
|
attr_reader :name
|
17
17
|
|
18
|
-
# Identifies the base class this index applies to
|
19
|
-
#
|
20
|
-
# Objects that are not of this class or one of its subclasses will not be added to the index.
|
21
|
-
#
|
22
|
-
# @example
|
23
|
-
# i = Index.new(name: 'id', base_class: self, key_source: :id, unique: true)
|
24
|
-
# i.base_class == self #=> true
|
25
|
-
#
|
26
|
-
# @return [Class] the class this index applies to
|
27
|
-
#
|
28
|
-
attr_reader :base_class
|
29
|
-
|
30
18
|
# Defines how the object's key value is calculated
|
31
19
|
#
|
32
20
|
# If a proc is provided, it will be called with the object as an argument to get the key value.
|
@@ -34,7 +22,7 @@ module ActiveModelPersistence
|
|
34
22
|
# If a symbol is provided, it will identify the method to call on the object to get the key value.
|
35
23
|
#
|
36
24
|
# @example
|
37
|
-
# i = Index.new(name: 'id',
|
25
|
+
# i = Index.new(name: 'id', key_value_source: :id, unique: true)
|
38
26
|
# i.key_value_source # => :id
|
39
27
|
#
|
40
28
|
# @return [Symbol, Proc] the method name or proc used to calculate the index key
|
@@ -49,7 +37,7 @@ module ActiveModelPersistence
|
|
49
37
|
# when trying to add the second object.
|
50
38
|
#
|
51
39
|
# @example
|
52
|
-
# i = Index.new(name: 'id',
|
40
|
+
# i = Index.new(name: 'id', key_value_source: :id, unique: true)
|
53
41
|
# i.unique? # => true
|
54
42
|
#
|
55
43
|
# @return [Boolean] true if the index is unique
|
@@ -86,9 +74,8 @@ module ActiveModelPersistence
|
|
86
74
|
# @param key_value_source [Symbol, Proc] the attribute name or proc used to calculate the index key
|
87
75
|
# @param unique [Boolean] when true the index will only allow one object per key
|
88
76
|
#
|
89
|
-
def initialize(name:,
|
77
|
+
def initialize(name:, key_value_source: nil, unique: false)
|
90
78
|
@name = name.to_s
|
91
|
-
@base_class = base_class
|
92
79
|
@key_value_source = determine_key_value_source(name, key_value_source)
|
93
80
|
@unique = unique
|
94
81
|
@key_to_objects_map = {}
|
@@ -241,7 +228,7 @@ module ActiveModelPersistence
|
|
241
228
|
# @api private
|
242
229
|
#
|
243
230
|
def remove_object_from_index(object, key)
|
244
|
-
key_to_objects_map[key].delete_if { |o| o.
|
231
|
+
key_to_objects_map[key].delete_if { |o| o.primary_key == object.primary_key }
|
245
232
|
key_to_objects_map.delete(key) if key_to_objects_map[key].empty?
|
246
233
|
object.clear_index_key(name)
|
247
234
|
end
|
@@ -60,7 +60,6 @@ module ActiveModelPersistence
|
|
60
60
|
# make these class methods on that class.
|
61
61
|
#
|
62
62
|
module ClassMethods
|
63
|
-
# @!attribute [r] indexes
|
64
63
|
# Returns a hash of indexes for the model keyed by name
|
65
64
|
#
|
66
65
|
# @example
|
@@ -68,7 +67,9 @@ module ActiveModelPersistence
|
|
68
67
|
#
|
69
68
|
# @return [Hash<String, ActiveModelPersistence::Index>] the indexes defined by the model
|
70
69
|
#
|
71
|
-
|
70
|
+
def indexes
|
71
|
+
@indexes ||= {}
|
72
|
+
end
|
72
73
|
|
73
74
|
# Adds an index to the model
|
74
75
|
#
|
@@ -97,7 +98,9 @@ module ActiveModelPersistence
|
|
97
98
|
indexes[index_name.to_sym] = index
|
98
99
|
|
99
100
|
singleton_class.define_method("find_by_#{index_name}") do |key|
|
100
|
-
index.objects(key).
|
101
|
+
index.objects(key).tap do |objects|
|
102
|
+
objects.each { |o| o.instance_variable_set(:@previously_new_record, false) }
|
103
|
+
end
|
101
104
|
end
|
102
105
|
end
|
103
106
|
|
@@ -122,9 +125,7 @@ module ActiveModelPersistence
|
|
122
125
|
# @return [void]
|
123
126
|
#
|
124
127
|
def update_indexes(object)
|
125
|
-
indexes.each_value
|
126
|
-
index.add_or_update(object) if object.is_a?(index.base_class)
|
127
|
-
end
|
128
|
+
indexes.each_value { |index| index.add_or_update(object) }
|
128
129
|
end
|
129
130
|
|
130
131
|
# Removes the given object from all defined indexes
|
@@ -143,9 +144,7 @@ module ActiveModelPersistence
|
|
143
144
|
# @return [void]
|
144
145
|
#
|
145
146
|
def remove_from_indexes(object)
|
146
|
-
indexes.each_value
|
147
|
-
index.remove(object) if object.is_a?(index.base_class)
|
148
|
-
end
|
147
|
+
indexes.each_value { |index| index.remove(object) }
|
149
148
|
end
|
150
149
|
|
151
150
|
private
|
@@ -159,15 +158,12 @@ module ActiveModelPersistence
|
|
159
158
|
def default_index_options(index_name)
|
160
159
|
{
|
161
160
|
name: index_name.to_sym,
|
162
|
-
base_class: self,
|
163
161
|
unique: false
|
164
162
|
}
|
165
163
|
end
|
166
164
|
end
|
167
165
|
|
168
166
|
included do
|
169
|
-
cattr_reader :indexes, instance_accessor: false, default: {}
|
170
|
-
|
171
167
|
# Adds the object to the indexes defined by the model
|
172
168
|
#
|
173
169
|
# @example
|
@@ -158,7 +158,7 @@ module ActiveModelPersistence
|
|
158
158
|
# @return [Array<Object>] the model objects in the object store
|
159
159
|
#
|
160
160
|
def all
|
161
|
-
object_array.
|
161
|
+
object_array.each
|
162
162
|
end
|
163
163
|
|
164
164
|
# The number of model objects saved in the object store
|
@@ -174,7 +174,7 @@ module ActiveModelPersistence
|
|
174
174
|
# @return [Integer] the number of model objects in the object store
|
175
175
|
#
|
176
176
|
def count
|
177
|
-
object_array.
|
177
|
+
object_array.size
|
178
178
|
end
|
179
179
|
|
180
180
|
alias size count
|
@@ -196,11 +196,30 @@ module ActiveModelPersistence
|
|
196
196
|
# @return [void]
|
197
197
|
#
|
198
198
|
def destroy_all
|
199
|
-
|
200
|
-
objects_to_destroy.each(&:destroy)
|
199
|
+
object_array.first.destroy while object_array.size.positive?
|
201
200
|
end
|
202
201
|
|
203
|
-
|
202
|
+
# Removes all model objects from the object store
|
203
|
+
#
|
204
|
+
# Each saved model object's `#destroy` method is NOT called.
|
205
|
+
#
|
206
|
+
# @example
|
207
|
+
# array_of_attributes = [
|
208
|
+
# { id: 1, name: 'James' },
|
209
|
+
# { id: 2, name: 'Frank' }
|
210
|
+
# ]
|
211
|
+
# ModelExample.create(array_of_attributes)
|
212
|
+
# ModelExample.all.count #=> 2
|
213
|
+
# ModelExample.destroy_all
|
214
|
+
# ModelExample.all.count #=> 0
|
215
|
+
#
|
216
|
+
# @return [void]
|
217
|
+
#
|
218
|
+
def delete_all
|
219
|
+
@object_array = []
|
220
|
+
indexes.values.each(&:remove_all)
|
221
|
+
nil
|
222
|
+
end
|
204
223
|
|
205
224
|
# private
|
206
225
|
|
@@ -210,12 +229,13 @@ module ActiveModelPersistence
|
|
210
229
|
#
|
211
230
|
# @api private
|
212
231
|
#
|
232
|
+
def object_array
|
233
|
+
@object_array ||= []
|
234
|
+
end
|
213
235
|
end
|
214
236
|
|
215
237
|
# rubocop:disable Metrics/BlockLength
|
216
238
|
included do
|
217
|
-
cattr_reader :object_array, instance_accessor: false, default: []
|
218
|
-
|
219
239
|
# Returns true if this object hasn't been saved or destroyed yet
|
220
240
|
#
|
221
241
|
# @example
|
@@ -351,7 +371,7 @@ module ActiveModelPersistence
|
|
351
371
|
def destroy
|
352
372
|
if persisted?
|
353
373
|
remove_from_indexes
|
354
|
-
self.class.object_array.delete_if { |o| o.
|
374
|
+
self.class.object_array.delete_if { |o| o.primary_key == primary_key }
|
355
375
|
end
|
356
376
|
@new_record = false
|
357
377
|
@destroyed = true
|
@@ -409,14 +429,13 @@ module ActiveModelPersistence
|
|
409
429
|
# Creates a record with values matching those of the instance attributes
|
410
430
|
# and returns its id.
|
411
431
|
#
|
412
|
-
# @return [Object] the
|
432
|
+
# @return [Object] the primary_key of the created object
|
413
433
|
#
|
414
434
|
# @api private
|
415
435
|
#
|
416
436
|
def _create
|
417
|
-
return false unless
|
418
|
-
|
419
|
-
raise UniqueConstraintError if primary_key_index.include?(primary_key_value)
|
437
|
+
return false unless primary_key?
|
438
|
+
raise UniqueConstraintError if primary_key_index.include?(primary_key)
|
420
439
|
|
421
440
|
self.class.object_array << self
|
422
441
|
|
@@ -424,7 +443,7 @@ module ActiveModelPersistence
|
|
424
443
|
|
425
444
|
yield(self) if block_given?
|
426
445
|
|
427
|
-
|
446
|
+
primary_key
|
428
447
|
end
|
429
448
|
|
430
449
|
# Updates an object that is already in the object store
|
@@ -434,7 +453,7 @@ module ActiveModelPersistence
|
|
434
453
|
# @api private
|
435
454
|
#
|
436
455
|
def _update
|
437
|
-
raise RecordNotFound unless primary_key_index.include?(
|
456
|
+
raise RecordNotFound unless primary_key_index.include?(primary_key)
|
438
457
|
|
439
458
|
yield(self) if block_given?
|
440
459
|
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/core_ext/module'
|
4
|
-
|
5
3
|
module ActiveModelPersistence
|
6
4
|
# Exposes the `primary_key` accessor to read or write the primary key attribute value
|
7
5
|
#
|
@@ -44,8 +42,7 @@ module ActiveModelPersistence
|
|
44
42
|
# make these class methods on that class.
|
45
43
|
#
|
46
44
|
module ClassMethods
|
47
|
-
#
|
48
|
-
# Identifies the attribute that the `primary_key_value` accessor maps to
|
45
|
+
# Identifies the attribute that the `primary_key` accessor maps to
|
49
46
|
#
|
50
47
|
# The primary key is 'id' by default.
|
51
48
|
#
|
@@ -57,28 +54,33 @@ module ActiveModelPersistence
|
|
57
54
|
# end
|
58
55
|
# Employee.primary_key #=> :username
|
59
56
|
#
|
60
|
-
# @return [
|
57
|
+
# @return [Symbol] the attribute that the `primary_key` accessor is an alias for
|
61
58
|
#
|
62
|
-
|
63
|
-
|
59
|
+
def primary_key
|
60
|
+
@primary_key ||= 'id'
|
61
|
+
end
|
64
62
|
|
65
|
-
|
66
|
-
# @!attribute [r] primary_key
|
67
|
-
# Identifies the attribute that the `primary_key_value` accessor maps to
|
68
|
-
#
|
69
|
-
# The primary key is 'id' by default.
|
63
|
+
# Sets the attribute to use for the primary key
|
70
64
|
#
|
71
65
|
# @example
|
72
66
|
# class Employee
|
73
67
|
# include ActiveModelPersistence::PrimaryKey
|
74
68
|
# attribute :username, :string
|
75
|
-
#
|
69
|
+
# primary_key = :username
|
76
70
|
# end
|
77
|
-
# Employee.
|
71
|
+
# e = Employee.new(username: 'couballj')
|
72
|
+
# e.primary_key #=> 'couballj'
|
73
|
+
#
|
74
|
+
# @param attribute [Symbol] the attribute to use for the primary key
|
75
|
+
#
|
76
|
+
# @return [void]
|
78
77
|
#
|
79
|
-
|
80
|
-
|
78
|
+
def primary_key=(attribute)
|
79
|
+
@primary_key = attribute.to_s
|
80
|
+
end
|
81
|
+
end
|
81
82
|
|
83
|
+
included do
|
82
84
|
# Returns the primary key attribute's value
|
83
85
|
#
|
84
86
|
# @example
|
@@ -92,8 +94,8 @@ module ActiveModelPersistence
|
|
92
94
|
#
|
93
95
|
# @return [Object] the primary key attribute's value
|
94
96
|
#
|
95
|
-
def
|
96
|
-
__send__(primary_key)
|
97
|
+
def primary_key
|
98
|
+
__send__(self.class.primary_key)
|
97
99
|
end
|
98
100
|
|
99
101
|
# Sets the primary key atribute's value
|
@@ -112,8 +114,8 @@ module ActiveModelPersistence
|
|
112
114
|
#
|
113
115
|
# @return [void]
|
114
116
|
#
|
115
|
-
def
|
116
|
-
__send__("#{primary_key}=", value)
|
117
|
+
def primary_key=(value)
|
118
|
+
__send__("#{self.class.primary_key}=", value)
|
117
119
|
end
|
118
120
|
|
119
121
|
# Returns true if the primary key attribute's value is not null or empty
|
@@ -131,8 +133,8 @@ module ActiveModelPersistence
|
|
131
133
|
#
|
132
134
|
# @return [Boolean] true if the primary key attribute's value is not null or empty
|
133
135
|
#
|
134
|
-
def
|
135
|
-
|
136
|
+
def primary_key?
|
137
|
+
primary_key.present?
|
136
138
|
end
|
137
139
|
end
|
138
140
|
end
|