bullet 6.0.2 → 6.1.4
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/.travis.yml +3 -1
- data/CHANGELOG.md +25 -0
- data/Gemfile.rails-6.0 +1 -1
- data/Gemfile.rails-6.1 +15 -0
- data/README.md +12 -2
- data/lib/bullet.rb +31 -20
- data/lib/bullet/active_job.rb +1 -3
- data/lib/bullet/active_record4.rb +9 -23
- data/lib/bullet/active_record41.rb +7 -19
- data/lib/bullet/active_record42.rb +8 -16
- data/lib/bullet/active_record5.rb +188 -170
- data/lib/bullet/active_record52.rb +187 -161
- data/lib/bullet/active_record60.rb +194 -175
- data/lib/bullet/active_record61.rb +278 -0
- data/lib/bullet/bullet_xhr.js +17 -23
- data/lib/bullet/dependency.rb +42 -34
- data/lib/bullet/detector/association.rb +24 -18
- data/lib/bullet/detector/base.rb +1 -2
- data/lib/bullet/detector/counter_cache.rb +10 -6
- data/lib/bullet/detector/n_plus_one_query.rb +18 -8
- data/lib/bullet/detector/unused_eager_loading.rb +5 -2
- data/lib/bullet/mongoid4x.rb +3 -7
- data/lib/bullet/mongoid5x.rb +3 -7
- data/lib/bullet/mongoid6x.rb +3 -7
- data/lib/bullet/mongoid7x.rb +3 -7
- data/lib/bullet/notification/base.rb +14 -18
- data/lib/bullet/notification/n_plus_one_query.rb +2 -4
- data/lib/bullet/notification/unused_eager_loading.rb +2 -4
- data/lib/bullet/rack.rb +23 -15
- data/lib/bullet/stack_trace_filter.rb +7 -16
- data/lib/bullet/version.rb +1 -1
- data/lib/generators/bullet/install_generator.rb +23 -23
- data/perf/benchmark.rb +8 -14
- data/spec/bullet/detector/counter_cache_spec.rb +6 -6
- data/spec/bullet/detector/n_plus_one_query_spec.rb +7 -3
- data/spec/bullet/detector/unused_eager_loading_spec.rb +19 -6
- data/spec/bullet/notification/base_spec.rb +1 -3
- data/spec/bullet/notification/n_plus_one_query_spec.rb +16 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +5 -1
- data/spec/bullet/rack_spec.rb +133 -7
- data/spec/bullet/registry/association_spec.rb +2 -2
- data/spec/bullet/registry/base_spec.rb +1 -1
- data/spec/bullet_spec.rb +10 -29
- data/spec/integration/active_record/association_spec.rb +77 -122
- data/spec/integration/counter_cache_spec.rb +10 -30
- data/spec/integration/mongoid/association_spec.rb +18 -32
- data/spec/models/attachment.rb +5 -0
- data/spec/models/folder.rb +1 -2
- data/spec/models/group.rb +1 -2
- data/spec/models/page.rb +1 -2
- data/spec/models/submission.rb +1 -0
- data/spec/models/user.rb +1 -0
- data/spec/models/writer.rb +1 -2
- data/spec/spec_helper.rb +6 -10
- data/spec/support/bullet_ext.rb +8 -9
- data/spec/support/mongo_seed.rb +2 -16
- data/spec/support/sqlite_seed.rb +8 -0
- metadata +10 -6
@@ -4,25 +4,17 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
if !mongoid? && active_record?
|
6
6
|
describe Bullet::Detector::CounterCache do
|
7
|
-
before(:each)
|
8
|
-
Bullet.start_request
|
9
|
-
end
|
7
|
+
before(:each) { Bullet.start_request }
|
10
8
|
|
11
|
-
after(:each)
|
12
|
-
Bullet.end_request
|
13
|
-
end
|
9
|
+
after(:each) { Bullet.end_request }
|
14
10
|
|
15
11
|
it 'should need counter cache with all cities' do
|
16
|
-
Country.all.each
|
17
|
-
country.cities.size
|
18
|
-
end
|
12
|
+
Country.all.each { |country| country.cities.size }
|
19
13
|
expect(Bullet.collected_counter_cache_notifications).not_to be_empty
|
20
14
|
end
|
21
15
|
|
22
16
|
it 'should not need counter cache if already define counter_cache' do
|
23
|
-
Person.all.each
|
24
|
-
person.pets.size
|
25
|
-
end
|
17
|
+
Person.all.each { |person| person.pets.size }
|
26
18
|
expect(Bullet.collected_counter_cache_notifications).to be_empty
|
27
19
|
end
|
28
20
|
|
@@ -32,32 +24,24 @@ if !mongoid? && active_record?
|
|
32
24
|
end
|
33
25
|
|
34
26
|
it 'should not need counter cache without size' do
|
35
|
-
Country.includes(:cities).each
|
36
|
-
country.cities.empty?
|
37
|
-
end
|
27
|
+
Country.includes(:cities).each { |country| country.cities.empty? }
|
38
28
|
expect(Bullet.collected_counter_cache_notifications).to be_empty
|
39
29
|
end
|
40
30
|
|
41
31
|
if active_record5? || active_record6?
|
42
32
|
it 'should not need counter cache for has_many through' do
|
43
|
-
Client.all.each
|
44
|
-
client.firms.size
|
45
|
-
end
|
33
|
+
Client.all.each { |client| client.firms.size }
|
46
34
|
expect(Bullet.collected_counter_cache_notifications).to be_empty
|
47
35
|
end
|
48
36
|
else
|
49
37
|
it 'should need counter cache for has_many through' do
|
50
|
-
Client.all.each
|
51
|
-
client.firms.size
|
52
|
-
end
|
38
|
+
Client.all.each { |client| client.firms.size }
|
53
39
|
expect(Bullet.collected_counter_cache_notifications).not_to be_empty
|
54
40
|
end
|
55
41
|
end
|
56
42
|
|
57
43
|
it 'should not need counter cache with part of cities' do
|
58
|
-
Country.all.each
|
59
|
-
country.cities.where(name: 'first').size
|
60
|
-
end
|
44
|
+
Country.all.each { |country| country.cities.where(name: 'first').size }
|
61
45
|
expect(Bullet.collected_counter_cache_notifications).to be_empty
|
62
46
|
end
|
63
47
|
|
@@ -66,9 +50,7 @@ if !mongoid? && active_record?
|
|
66
50
|
after { Bullet.counter_cache_enable = true }
|
67
51
|
|
68
52
|
it 'should not detect counter cache' do
|
69
|
-
Country.all.each
|
70
|
-
country.cities.size
|
71
|
-
end
|
53
|
+
Country.all.each { |country| country.cities.size }
|
72
54
|
expect(Bullet.collected_counter_cache_notifications).to be_empty
|
73
55
|
end
|
74
56
|
end
|
@@ -78,9 +60,7 @@ if !mongoid? && active_record?
|
|
78
60
|
after { Bullet.clear_whitelist }
|
79
61
|
|
80
62
|
it 'should not detect counter cache' do
|
81
|
-
Country.all.each
|
82
|
-
country.cities.size
|
83
|
-
end
|
63
|
+
Country.all.each { |country| country.cities.size }
|
84
64
|
expect(Bullet.collected_counter_cache_notifications).to be_empty
|
85
65
|
end
|
86
66
|
end
|
@@ -7,9 +7,7 @@ if mongoid?
|
|
7
7
|
context 'embeds_many' do
|
8
8
|
context 'posts => users' do
|
9
9
|
it 'should detect nothing' do
|
10
|
-
Mongoid::Post.all.each
|
11
|
-
post.users.map(&:name)
|
12
|
-
end
|
10
|
+
Mongoid::Post.all.each { |post| post.users.map(&:name) }
|
13
11
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
14
12
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
15
13
|
|
@@ -21,9 +19,7 @@ if mongoid?
|
|
21
19
|
context 'has_many' do
|
22
20
|
context 'posts => comments' do
|
23
21
|
it 'should detect non preload posts => comments' do
|
24
|
-
Mongoid::Post.all.each
|
25
|
-
post.comments.map(&:name)
|
26
|
-
end
|
22
|
+
Mongoid::Post.all.each { |post| post.comments.map(&:name) }
|
27
23
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
28
24
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
29
25
|
|
@@ -31,9 +27,7 @@ if mongoid?
|
|
31
27
|
end
|
32
28
|
|
33
29
|
it 'should detect preload post => comments' do
|
34
|
-
Mongoid::Post.includes(:comments).each
|
35
|
-
post.comments.map(&:name)
|
36
|
-
end
|
30
|
+
Mongoid::Post.includes(:comments).each { |post| post.comments.map(&:name) }
|
37
31
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
38
32
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
39
33
|
|
@@ -78,7 +72,10 @@ if mongoid?
|
|
78
72
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
79
73
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
80
74
|
|
81
|
-
expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(
|
75
|
+
expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(
|
76
|
+
Mongoid::Category,
|
77
|
+
:posts
|
78
|
+
)
|
82
79
|
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Mongoid::Category, :entries)
|
83
80
|
end
|
84
81
|
|
@@ -103,9 +100,7 @@ if mongoid?
|
|
103
100
|
end
|
104
101
|
|
105
102
|
it 'should detect unused preload with category => entries, but not with category => posts' do
|
106
|
-
Mongoid::Category.includes(:posts, :entries).each
|
107
|
-
category.posts.map(&:name)
|
108
|
-
end
|
103
|
+
Mongoid::Category.includes(:posts, :entries).each { |category| category.posts.map(&:name) }
|
109
104
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
110
105
|
expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Mongoid::Category, :posts)
|
111
106
|
expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Mongoid::Category, :entries)
|
@@ -116,9 +111,7 @@ if mongoid?
|
|
116
111
|
|
117
112
|
context 'post => comment' do
|
118
113
|
it 'should detect unused preload with post => comments' do
|
119
|
-
Mongoid::Post.includes(:comments).each
|
120
|
-
post.comments.first.name
|
121
|
-
end
|
114
|
+
Mongoid::Post.includes(:comments).each { |post| post.comments.first.name }
|
122
115
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
123
116
|
expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Mongoid::Post, :comments)
|
124
117
|
|
@@ -136,9 +129,7 @@ if mongoid?
|
|
136
129
|
|
137
130
|
context 'scope preload_comments' do
|
138
131
|
it 'should detect preload post => comments with scope' do
|
139
|
-
Mongoid::Post.preload_comments.each
|
140
|
-
post.comments.map(&:name)
|
141
|
-
end
|
132
|
+
Mongoid::Post.preload_comments.each { |post| post.comments.map(&:name) }
|
142
133
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
143
134
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
144
135
|
|
@@ -158,9 +149,7 @@ if mongoid?
|
|
158
149
|
context 'belongs_to' do
|
159
150
|
context 'comment => post' do
|
160
151
|
it 'should detect non preload with comment => post' do
|
161
|
-
Mongoid::Comment.all.each
|
162
|
-
comment.post.name
|
163
|
-
end
|
152
|
+
Mongoid::Comment.all.each { |comment| comment.post.name }
|
164
153
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
165
154
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
166
155
|
|
@@ -176,9 +165,7 @@ if mongoid?
|
|
176
165
|
end
|
177
166
|
|
178
167
|
it 'should detect preload with comment => post' do
|
179
|
-
Mongoid::Comment.includes(:post).each
|
180
|
-
comment.post.name
|
181
|
-
end
|
168
|
+
Mongoid::Comment.includes(:post).each { |comment| comment.post.name }
|
182
169
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
183
170
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
184
171
|
|
@@ -207,20 +194,19 @@ if mongoid?
|
|
207
194
|
context 'company => address' do
|
208
195
|
if Mongoid::VERSION !~ /\A3.0/
|
209
196
|
it 'should detect non preload association' do
|
210
|
-
Mongoid::Company.all.each
|
211
|
-
company.address.name
|
212
|
-
end
|
197
|
+
Mongoid::Company.all.each { |company| company.address.name }
|
213
198
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
214
199
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
215
200
|
|
216
|
-
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(
|
201
|
+
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(
|
202
|
+
Mongoid::Company,
|
203
|
+
:address
|
204
|
+
)
|
217
205
|
end
|
218
206
|
end
|
219
207
|
|
220
208
|
it 'should detect preload association' do
|
221
|
-
Mongoid::Company.includes(:address).each
|
222
|
-
company.address.name
|
223
|
-
end
|
209
|
+
Mongoid::Company.includes(:address).each { |company| company.address.name }
|
224
210
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
225
211
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
226
212
|
|
data/spec/models/folder.rb
CHANGED
data/spec/models/group.rb
CHANGED
data/spec/models/page.rb
CHANGED
data/spec/models/submission.rb
CHANGED
data/spec/models/user.rb
CHANGED
data/spec/models/writer.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -4,14 +4,16 @@ require 'rspec'
|
|
4
4
|
begin
|
5
5
|
require 'active_record'
|
6
6
|
rescue LoadError
|
7
|
+
|
7
8
|
end
|
8
9
|
begin
|
9
10
|
require 'mongoid'
|
10
11
|
rescue LoadError
|
12
|
+
|
11
13
|
end
|
12
14
|
|
13
15
|
module Rails
|
14
|
-
class <<self
|
16
|
+
class << self
|
15
17
|
def root
|
16
18
|
File.expand_path(__FILE__).split('/')[0..-3].join('/')
|
17
19
|
end
|
@@ -60,9 +62,7 @@ if active_record?
|
|
60
62
|
Bullet.enable = true
|
61
63
|
end
|
62
64
|
|
63
|
-
config.after(:example)
|
64
|
-
Bullet.end_request
|
65
|
-
end
|
65
|
+
config.after(:example) { Bullet.end_request }
|
66
66
|
end
|
67
67
|
|
68
68
|
if ENV['BULLET_LOG']
|
@@ -87,13 +87,9 @@ if mongoid?
|
|
87
87
|
Support::MongoSeed.teardown_db
|
88
88
|
end
|
89
89
|
|
90
|
-
config.before(:each)
|
91
|
-
Bullet.start_request
|
92
|
-
end
|
90
|
+
config.before(:each) { Bullet.start_request }
|
93
91
|
|
94
|
-
config.after(:each)
|
95
|
-
Bullet.end_request
|
96
|
-
end
|
92
|
+
config.after(:each) { Bullet.end_request }
|
97
93
|
end
|
98
94
|
|
99
95
|
if ENV['BULLET_LOG']
|
data/spec/support/bullet_ext.rb
CHANGED
@@ -2,9 +2,7 @@
|
|
2
2
|
|
3
3
|
module Bullet
|
4
4
|
def self.collected_notifications_of_class(notification_class)
|
5
|
-
Bullet.notification_collector.collection.select
|
6
|
-
notification.is_a? notification_class
|
7
|
-
end
|
5
|
+
Bullet.notification_collector.collection.select { |notification| notification.is_a? notification_class }
|
8
6
|
end
|
9
7
|
|
10
8
|
def self.collected_counter_cache_notifications
|
@@ -23,7 +21,7 @@ end
|
|
23
21
|
module Bullet
|
24
22
|
module Detector
|
25
23
|
class Association
|
26
|
-
class <<self
|
24
|
+
class << self
|
27
25
|
# returns true if all associations are preloaded
|
28
26
|
def completely_preloading_associations?
|
29
27
|
Bullet.collected_n_plus_one_query_notifications.empty?
|
@@ -35,21 +33,22 @@ module Bullet
|
|
35
33
|
|
36
34
|
# returns true if a given object has a specific association
|
37
35
|
def creating_object_association_for?(object, association)
|
38
|
-
object_associations[object.bullet_key].present? &&
|
36
|
+
object_associations[object.bullet_key].present? &&
|
37
|
+
object_associations[object.bullet_key].include?(association)
|
39
38
|
end
|
40
39
|
|
41
40
|
# returns true if a given class includes the specific unpreloaded association
|
42
41
|
def detecting_unpreloaded_association_for?(klass, association)
|
43
|
-
Bullet.collected_n_plus_one_query_notifications.select
|
42
|
+
Bullet.collected_n_plus_one_query_notifications.select do |notification|
|
44
43
|
notification.base_class == klass.to_s && notification.associations.include?(association)
|
45
|
-
|
44
|
+
end.present?
|
46
45
|
end
|
47
46
|
|
48
47
|
# returns true if the given class includes the specific unused preloaded association
|
49
48
|
def unused_preload_associations_for?(klass, association)
|
50
|
-
Bullet.collected_unused_eager_association_notifications.select
|
49
|
+
Bullet.collected_unused_eager_association_notifications.select do |notification|
|
51
50
|
notification.base_class == klass.to_s && notification.associations.include?(association)
|
52
|
-
|
51
|
+
end.present?
|
53
52
|
end
|
54
53
|
end
|
55
54
|
end
|
data/spec/support/mongo_seed.rb
CHANGED
@@ -39,25 +39,11 @@ module Support
|
|
39
39
|
def setup_db
|
40
40
|
if Mongoid::VERSION =~ /\A4/
|
41
41
|
Mongoid.configure do |config|
|
42
|
-
config.load_configuration(
|
43
|
-
sessions: {
|
44
|
-
default: {
|
45
|
-
database: 'bullet',
|
46
|
-
hosts: ['localhost:27017']
|
47
|
-
}
|
48
|
-
}
|
49
|
-
)
|
42
|
+
config.load_configuration(sessions: { default: { database: 'bullet', hosts: %w[localhost:27017] } })
|
50
43
|
end
|
51
44
|
else
|
52
45
|
Mongoid.configure do |config|
|
53
|
-
config.load_configuration(
|
54
|
-
clients: {
|
55
|
-
default: {
|
56
|
-
database: 'bullet',
|
57
|
-
hosts: ['localhost:27017']
|
58
|
-
}
|
59
|
-
}
|
60
|
-
)
|
46
|
+
config.load_configuration(clients: { default: { database: 'bullet', hosts: %w[localhost:27017] } })
|
61
47
|
end
|
62
48
|
# Increase the level from DEBUG in order to avoid excessive logging to the screen
|
63
49
|
Mongo::Logger.logger.level = Logger::WARN
|
data/spec/support/sqlite_seed.rb
CHANGED
@@ -95,6 +95,9 @@ module Support
|
|
95
95
|
submission1.replies.create(name: 'reply2')
|
96
96
|
submission2.replies.create(name: 'reply3')
|
97
97
|
submission2.replies.create(name: 'reply4')
|
98
|
+
|
99
|
+
submission1.create_attachment(file_name: 'submission1 file')
|
100
|
+
submission2.create_attachment(file_name: 'submission2 file')
|
98
101
|
end
|
99
102
|
|
100
103
|
def setup_db
|
@@ -240,6 +243,11 @@ module Support
|
|
240
243
|
t.column :name, :string
|
241
244
|
t.column :category_id, :integer
|
242
245
|
end
|
246
|
+
|
247
|
+
create_table :attachments do |t|
|
248
|
+
t.column :file_name, :string
|
249
|
+
t.column :submission_id, :integer
|
250
|
+
end
|
243
251
|
end
|
244
252
|
end
|
245
253
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Huang
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- Gemfile.rails-5.1
|
63
63
|
- Gemfile.rails-5.2
|
64
64
|
- Gemfile.rails-6.0
|
65
|
+
- Gemfile.rails-6.1
|
65
66
|
- Guardfile
|
66
67
|
- Hacking.md
|
67
68
|
- MIT-LICENSE
|
@@ -76,6 +77,7 @@ files:
|
|
76
77
|
- lib/bullet/active_record5.rb
|
77
78
|
- lib/bullet/active_record52.rb
|
78
79
|
- lib/bullet/active_record60.rb
|
80
|
+
- lib/bullet/active_record61.rb
|
79
81
|
- lib/bullet/bullet_xhr.js
|
80
82
|
- lib/bullet/dependency.rb
|
81
83
|
- lib/bullet/detector.rb
|
@@ -127,6 +129,7 @@ files:
|
|
127
129
|
- spec/integration/counter_cache_spec.rb
|
128
130
|
- spec/integration/mongoid/association_spec.rb
|
129
131
|
- spec/models/address.rb
|
132
|
+
- spec/models/attachment.rb
|
130
133
|
- spec/models/author.rb
|
131
134
|
- spec/models/base_user.rb
|
132
135
|
- spec/models/category.rb
|
@@ -173,7 +176,7 @@ licenses:
|
|
173
176
|
metadata:
|
174
177
|
changelog_uri: https://github.com/flyerhzm/bullet/blob/master/CHANGELOG.md
|
175
178
|
source_code_uri: https://github.com/flyerhzm/bullet
|
176
|
-
post_install_message:
|
179
|
+
post_install_message:
|
177
180
|
rdoc_options: []
|
178
181
|
require_paths:
|
179
182
|
- lib
|
@@ -188,8 +191,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
191
|
- !ruby/object:Gem::Version
|
189
192
|
version: 1.3.6
|
190
193
|
requirements: []
|
191
|
-
rubygems_version: 3.
|
192
|
-
signing_key:
|
194
|
+
rubygems_version: 3.1.4
|
195
|
+
signing_key:
|
193
196
|
specification_version: 4
|
194
197
|
summary: help to kill N+1 queries and unused eager loading.
|
195
198
|
test_files:
|
@@ -214,6 +217,7 @@ test_files:
|
|
214
217
|
- spec/integration/counter_cache_spec.rb
|
215
218
|
- spec/integration/mongoid/association_spec.rb
|
216
219
|
- spec/models/address.rb
|
220
|
+
- spec/models/attachment.rb
|
217
221
|
- spec/models/author.rb
|
218
222
|
- spec/models/base_user.rb
|
219
223
|
- spec/models/category.rb
|