mongoid-rspec 4.1.0 → 4.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c59448b4e72ebb718332a28e7ddf77de5b792a09ea273b75959930e2c6c2918
4
- data.tar.gz: b1818ed7a513db7a4e31bcdd5a492504a75becfc866dd95505192da1db7a56cc
3
+ metadata.gz: 711f91347b02d3d6982a72b6946bb781ea07dba16f858109da01166c7a768ecf
4
+ data.tar.gz: 58e81131678e670e5a7b63385122fa316afadb18d49749c3544a4e5e1898d3fc
5
5
  SHA512:
6
- metadata.gz: 995c284d71146d52d554e8eff18e48605e76546ebce9428674d1fcefe4c560a73973651f4eb4496d21a839fb35944c37f98cc21eb78ddd1e1eea80a57d1392c4
7
- data.tar.gz: a2e400ead572f31c614a294f1d5d10116e08fa6f152b2f58cf112da45608a3d72be2c5893ceb035c8a6f514af8ef55bcfdffd0a55a81a2e0f97ad43fd0699cf2
6
+ metadata.gz: 7aab1843f0f0b8778916039f3ef8b0f89e815bbc9cfafe0d7244a903df8c524ec6e990914478d6cd403b5b9e81e885b007850fe58cbf78841d989a472e98cdb2
7
+ data.tar.gz: 3e068496db19d24acfd05ff8ac630ecd41ccab1606e6597ddf0d0bf5969296dd7e1f2f5cf3a7a847801b44c84363e784908024a392317b7d1a95825f2c66bf9f
data/README.md CHANGED
@@ -1,10 +1,17 @@
1
1
  # [mongoid-rspec](https://github.com/mongoid/mongoid-rspec "A collection of RSpec-compatible matchers that help to test Mongoid documents.")
2
2
 
3
- [![Build Status](https://travis-ci.org/mongoid/mongoid-rspec.svg?branch=master)](https://travis-ci.org/mongoid/mongoid-rspec)
4
3
  [![Gem Version](https://badge.fury.io/rb/mongoid-rspec.svg)](https://badge.fury.io/rb/mongoid-rspec)
4
+ [![Test Status](https://github.com/mongoid/mongoid-rspec/workflows/Test/badge.svg)](https://github.com/mongoid/mongoid-rspec/actions)
5
+ [![Rubocop Status](https://github.com/mongoid/mongoid-rspec/workflows/Rubocop/badge.svg)](https://github.com/mongoid/mongoid-rspec/actions)
5
6
 
6
7
  The mongoid-rspec library provides a collection of RSpec-compatible matchers that help to test Mongoid documents.
7
8
 
9
+ [Tested](https://github.com/mongoid/mongoid-locker/actions) against:
10
+ - MRI: `2.6.x`, `2.7.x`, `3.0.x`, `3.1.x`, `3.2.x`
11
+ - Mongoid: `4`, `5`, `6`, `7`, `8`, `9`
12
+
13
+ See [.github/workflows/rspec.yml](.github/workflows/rspec.yml) for the latest test matrix.
14
+
8
15
  ## Installation
9
16
 
10
17
  Drop this line into your Gemfile:
@@ -18,7 +25,7 @@ end
18
25
 
19
26
  ## Compatibility
20
27
 
21
- This gem is compatible with Mongoid 3, 4, 5, 6 and 7.
28
+ This gem is compatible with Mongoid 3, 4, 5, 6, 7, 8, 9.
22
29
 
23
30
  ## Configuration
24
31
 
@@ -181,7 +188,7 @@ end
181
188
 
182
189
  ```ruby
183
190
  class Article
184
- index({ title: 1 }, { unique: true, background: true, drop_dups: true })
191
+ index({ title: 1 }, { unique: true, background: true })
185
192
  index({ title: 1, created_at: -1 })
186
193
  index({ category: 1 })
187
194
  end
@@ -190,7 +197,7 @@ RSpec.describe Article, type: :model do
190
197
  it do
191
198
  is_expected
192
199
  .to have_index_for(title: 1)
193
- .with_options(unique: true, background: true, drop_dups: true)
200
+ .with_options(unique: true, background: true)
194
201
  end
195
202
  it { is_expected.to have_index_for(title: 1, created_at: -1) }
196
203
  it { is_expected.to have_index_for(category: 1) }
@@ -201,9 +208,9 @@ end
201
208
 
202
209
  ```ruby
203
210
  RSpec.describe Article do
204
- it { is_expected.to have_field(:published).of_type(Boolean).with_default_value_of(false) }
205
- it { is_expected.to have_field(:allow_comments).of_type(Boolean).with_default_value_of(true) }
206
- it { is_expected.not_to have_field(:allow_comments).of_type(Boolean).with_default_value_of(false) }
211
+ it { is_expected.to have_field(:published).of_type(Mongoid::Boolean).with_default_value_of(false) }
212
+ it { is_expected.to have_field(:allow_comments).of_type(Mongoid::Boolean).with_default_value_of(true) }
213
+ it { is_expected.not_to have_field(:allow_comments).of_type(Mongoid::Boolean).with_default_value_of(false) }
207
214
  it { is_expected.not_to have_field(:number_of_comments).of_type(Integer).with_default_value_of(1) }
208
215
  end
209
216
 
@@ -249,6 +256,27 @@ RSpec.describe Article do
249
256
  it { is_expected.to embed_many(:comments) }
250
257
  end
251
258
 
259
+ # when the touch option is provided, then we can also verify that it is set
260
+
261
+ # by default, with_touch matches true when no parameters are provided
262
+ describe Article do
263
+ it { is_expected.to belong_to(:author).of_type(User).as_inverse_of(:articles).with_index.with_touch }
264
+ end
265
+
266
+ # parameters are supported for explicit matching
267
+ describe Comment do
268
+ it { is_expected.to be_embedded_in(:article).as_inverse_of(:comments).with_polymorphism.with_touch(true) }
269
+ end
270
+
271
+ describe Permalink do
272
+ it { is_expected.to be_embedded_in(:linkable).as_inverse_of(:link).with_touch(false) }
273
+ end
274
+
275
+ # touch can also take a symbol representing a field on the parent to touch
276
+ describe Record do
277
+ it { is_expected.to belong_to(:user).as_inverse_of(:record).with_touch(:record_updated_at) }
278
+ end
279
+
252
280
  RSpec.describe Comment do
253
281
  it { is_expected.to be_embedded_in(:article).as_inverse_of(:comments) }
254
282
  it { is_expected.to belong_to(:user).as_inverse_of(:comments) }
@@ -315,6 +343,22 @@ RSpec.describe Person do
315
343
  # should redefine the kind method to return :custom, i.e. "def self.kind() :custom end"
316
344
  it { is_expected.to custom_validate(:ssn).with_validator(SsnValidator) }
317
345
  end
346
+
347
+ # If you're using validators with if/unless conditionals, spec subject must be object instance
348
+ # This is supported on Mongoid 4 and newer
349
+ Rspec.describe User do
350
+ context 'when user has `admin` role' do
351
+ subject { User.new(role: 'admin') }
352
+
353
+ it { is_expected.to validate_length_of(:password).greater_than(20) }
354
+ end
355
+
356
+ context 'when user does not have `admin` role' do
357
+ subject { User.new(role: 'member') }
358
+
359
+ it { is_expected.not_to validate_length_of(:password) }
360
+ end
361
+ end
318
362
  ```
319
363
 
320
364
  ### Mass Assignment Matcher
data/Rakefile CHANGED
@@ -14,7 +14,4 @@ RSpec::Core::RakeTask.new(:rcov) do |spec|
14
14
  spec.rcov = true
15
15
  end
16
16
 
17
- require 'rubocop/rake_task'
18
- RuboCop::RakeTask.new(:rubocop)
19
-
20
- task default: %i[rubocop spec]
17
+ task default: %i[spec]
@@ -119,6 +119,12 @@ module Mongoid
119
119
  self
120
120
  end
121
121
 
122
+ def with_touch(touch = true)
123
+ @association[:touch] = touch
124
+ @expectation_message << " which specifies touch as #{@association[:touch]}"
125
+ self
126
+ end
127
+
122
128
  def with_optional
123
129
  @association[:optional] = true
124
130
  @expectation_message << " which specifies optional as #{@association[:optional]}"
@@ -272,6 +278,15 @@ module Mongoid
272
278
  end
273
279
  end
274
280
 
281
+ unless @association[:touch].nil?
282
+ if metadata.options[:touch] != @association[:touch]
283
+ @negative_result_message = "#{@positive_result_message} which sets touch as #{metadata.options[:touch].inspect}"
284
+ return false
285
+ else
286
+ @positive_result_message = "#{@positive_result_message} which sets touch as #{metadata.options[:touch].inspect}"
287
+ end
288
+ end
289
+
275
290
  if @association[:optional]
276
291
  if metadata.options[:optional] != true
277
292
  @negative_result_message = "#{@positive_result_message} which did not set optional"
@@ -44,7 +44,7 @@ module Mongoid
44
44
  private
45
45
 
46
46
  MAPPINGS = {
47
- dropDups: :drop_dups
47
+ dropDups: :drop_dups # Deprecated from MongoDB 3.0
48
48
  }.freeze
49
49
 
50
50
  def denormalising_options(opts)
@@ -12,7 +12,8 @@ module Mongoid
12
12
  @klass = actual.is_a?(Class) ? actual : actual.class
13
13
 
14
14
  @validator = @klass.validators_on(@field).detect do |v|
15
- (v.kind.to_s == @type) && (!v.options[:on] || on_options_matches?(v))
15
+ (v.kind.to_s == @type) && (!v.options[:on] || on_options_matches?(v)) &&
16
+ if_condition_matches?(actual, v) && unless_condition_matches?(actual, v)
16
17
  end
17
18
 
18
19
  if @validator
@@ -59,6 +60,31 @@ module Mongoid
59
60
 
60
61
  private
61
62
 
63
+ def if_condition_matches?(actual, validator)
64
+ return true unless validator.options[:if]
65
+
66
+ check_condition actual, validator.options[:if]
67
+ end
68
+
69
+ def unless_condition_matches?(actual, validator)
70
+ return true unless validator.options[:unless]
71
+
72
+ !check_condition actual, validator.options[:unless]
73
+ end
74
+
75
+ def check_condition(actual, filter)
76
+ raise ArgumentError, 'Spec subject must be object instance when testing validators with if/unless condition.' if actual.is_a?(Class)
77
+
78
+ case filter
79
+ when Symbol
80
+ actual.send filter
81
+ when ::Proc
82
+ actual.instance_exec(&filter)
83
+ else
84
+ raise ArgumentError, "Unexpected filter: #{filter.inspect}"
85
+ end
86
+ end
87
+
62
88
  def check_on
63
89
  validator_on_methods = [@validator.options[:on]].flatten
64
90
 
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module RSpec
3
- VERSION = '4.1.0'.freeze
3
+ VERSION = '4.2.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,128 +1,134 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Sagge
8
8
  - Rodrigo Pinto
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-06-12 00:00:00.000000000 Z
12
+ date: 2024-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: activesupport
15
+ name: appraisal
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ">="
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: 3.0.0
21
- type: :runtime
20
+ version: '2.0'
21
+ type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ">="
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: 3.0.0
27
+ version: '2.0'
28
28
  - !ruby/object:Gem::Dependency
29
- name: mongoid
29
+ name: mongoid-danger
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ">="
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '3.1'
35
- type: :runtime
34
+ version: '0.2'
35
+ type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ">="
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '3.1'
41
+ version: '0.2'
42
42
  - !ruby/object:Gem::Dependency
43
- name: mongoid-compatibility
43
+ name: pry
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: 0.5.1
49
- type: :runtime
48
+ version: '0'
49
+ type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - ">="
54
54
  - !ruby/object:Gem::Version
55
- version: 0.5.1
55
+ version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
- name: rspec-core
57
+ name: rails
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - "~>"
60
+ - - ">="
61
61
  - !ruby/object:Gem::Version
62
- version: '3.3'
63
- type: :runtime
62
+ version: '0'
63
+ type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - "~>"
67
+ - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: '3.3'
69
+ version: '0'
70
70
  - !ruby/object:Gem::Dependency
71
- name: rspec-expectations
71
+ name: rspec
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - "~>"
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
- version: '3.3'
77
- type: :runtime
76
+ version: '0'
77
+ type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - "~>"
81
+ - - ">="
82
82
  - !ruby/object:Gem::Version
83
- version: '3.3'
83
+ version: '0'
84
84
  - !ruby/object:Gem::Dependency
85
- name: rspec-mocks
85
+ name: rubocop
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
88
  - - "~>"
89
89
  - !ruby/object:Gem::Version
90
- version: '3.3'
91
- type: :runtime
90
+ version: 1.36.0
91
+ type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
95
  - - "~>"
96
96
  - !ruby/object:Gem::Version
97
- version: '3.3'
97
+ version: 1.36.0
98
98
  - !ruby/object:Gem::Dependency
99
- name: appraisal
99
+ name: mongoid
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - "~>"
102
+ - - ">="
103
103
  - !ruby/object:Gem::Version
104
- version: '2.2'
105
- type: :development
104
+ version: '3.0'
105
+ - - "<"
106
+ - !ruby/object:Gem::Version
107
+ version: '10.0'
108
+ type: :runtime
106
109
  prerelease: false
107
110
  version_requirements: !ruby/object:Gem::Requirement
108
111
  requirements:
109
- - - "~>"
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '3.0'
115
+ - - "<"
110
116
  - !ruby/object:Gem::Version
111
- version: '2.2'
117
+ version: '10.0'
112
118
  - !ruby/object:Gem::Dependency
113
- name: rake
119
+ name: mongoid-compatibility
114
120
  requirement: !ruby/object:Gem::Requirement
115
121
  requirements:
116
- - - "~>"
122
+ - - ">="
117
123
  - !ruby/object:Gem::Version
118
- version: '10.0'
119
- type: :development
124
+ version: 0.5.1
125
+ type: :runtime
120
126
  prerelease: false
121
127
  version_requirements: !ruby/object:Gem::Requirement
122
128
  requirements:
123
- - - "~>"
129
+ - - ">="
124
130
  - !ruby/object:Gem::Version
125
- version: '10.0'
131
+ version: 0.5.1
126
132
  description: RSpec matches for Mongoid models, including association and validation
127
133
  matchers.
128
134
  email: evansagge@gmail.com contato@rodrigopinto.me
@@ -160,33 +166,12 @@ files:
160
166
  - lib/mongoid-rspec.rb
161
167
  - lib/mongoid/rspec.rb
162
168
  - lib/mongoid/rspec/version.rb
163
- - spec/models/article.rb
164
- - spec/models/comment.rb
165
- - spec/models/log.rb
166
- - spec/models/message.rb
167
- - spec/models/movie_article.rb
168
- - spec/models/permalink.rb
169
- - spec/models/person.rb
170
- - spec/models/profile.rb
171
- - spec/models/record.rb
172
- - spec/models/site.rb
173
- - spec/models/user.rb
174
- - spec/spec_helper.rb
175
- - spec/unit/accept_nested_attributes_spec.rb
176
- - spec/unit/associations_spec.rb
177
- - spec/unit/be_dynamic_document_spec.rb
178
- - spec/unit/be_mongoid_document_spec.rb
179
- - spec/unit/be_stored_in.rb
180
- - spec/unit/document_spec.rb
181
- - spec/unit/have_index_for_spec.rb
182
- - spec/unit/have_timestamps_spec.rb
183
- - spec/unit/validations_spec.rb
184
- - spec/validators/ssn_validator.rb
185
169
  homepage: http://github.com/mongoid-rspec/mongoid-rspec
186
170
  licenses:
187
171
  - MIT
188
- metadata: {}
189
- post_install_message:
172
+ metadata:
173
+ rubygems_mfa_required: 'true'
174
+ post_install_message:
190
175
  rdoc_options: []
191
176
  require_paths:
192
177
  - lib
@@ -194,37 +179,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
194
179
  requirements:
195
180
  - - ">="
196
181
  - !ruby/object:Gem::Version
197
- version: '2.2'
182
+ version: '2.6'
198
183
  required_rubygems_version: !ruby/object:Gem::Requirement
199
184
  requirements:
200
185
  - - ">="
201
186
  - !ruby/object:Gem::Version
202
187
  version: 1.3.6
203
188
  requirements: []
204
- rubygems_version: 3.1.3
205
- signing_key:
189
+ rubygems_version: 3.5.10
190
+ signing_key:
206
191
  specification_version: 4
207
192
  summary: RSpec matchers for Mongoid
208
- test_files:
209
- - spec/spec_helper.rb
210
- - spec/unit/associations_spec.rb
211
- - spec/unit/be_dynamic_document_spec.rb
212
- - spec/unit/validations_spec.rb
213
- - spec/unit/be_stored_in.rb
214
- - spec/unit/have_index_for_spec.rb
215
- - spec/unit/accept_nested_attributes_spec.rb
216
- - spec/unit/document_spec.rb
217
- - spec/unit/be_mongoid_document_spec.rb
218
- - spec/unit/have_timestamps_spec.rb
219
- - spec/models/article.rb
220
- - spec/models/movie_article.rb
221
- - spec/models/record.rb
222
- - spec/models/site.rb
223
- - spec/models/message.rb
224
- - spec/models/permalink.rb
225
- - spec/models/profile.rb
226
- - spec/models/comment.rb
227
- - spec/models/person.rb
228
- - spec/models/log.rb
229
- - spec/models/user.rb
230
- - spec/validators/ssn_validator.rb
193
+ test_files: []
@@ -1,32 +0,0 @@
1
- class Article
2
- include Mongoid::Document
3
- include Mongoid::Timestamps
4
-
5
- field :title, localize: true
6
- field :content
7
- field :published, type: Boolean, default: false
8
- field :allow_comments, type: Boolean, default: true
9
- field :number_of_comments, type: Integer
10
- field :status, type: Symbol
11
- field :deletion_date, type: DateTime, default: nil
12
-
13
- embeds_many :comments, cascade_callbacks: true, inverse_of: :article
14
- embeds_one :permalink, inverse_of: :linkable
15
- belongs_to :author, class_name: 'User', inverse_of: :articles, index: true
16
-
17
- validates :title, presence: true
18
-
19
- validates_inclusion_of :status, in: [:pending], on: :create
20
- validates_inclusion_of :status, in: %i[approved rejected], on: :update
21
-
22
- validates_length_of :title, within: 8..16
23
- validates_length_of :content, minimum: 200
24
-
25
- validates_absence_of :deletion_date if Mongoid::Compatibility::Version.mongoid4_or_newer?
26
-
27
- index({ title: 1 }, unique: true, background: true, drop_dups: true)
28
- index(published: 1)
29
- index('permalink._id' => 1)
30
-
31
- accepts_nested_attributes_for :permalink
32
- end
@@ -1,6 +0,0 @@
1
- class Comment
2
- include Mongoid::Document
3
-
4
- embedded_in :article, inverse_of: :comments, polymorphic: true
5
- belongs_to :user, inverse_of: :comments
6
- end
data/spec/models/log.rb DELETED
@@ -1,9 +0,0 @@
1
- class Log
2
- include Mongoid::Document
3
- include Mongoid::Timestamps
4
- include Mongoid::Attributes::Dynamic if Mongoid::Compatibility::Version.mongoid4_or_newer?
5
-
6
- store_in collection: 'logs'
7
-
8
- index({ created_at: 1 }, bucket_size: 100, expire_after_seconds: 3600)
9
- end
@@ -1,17 +0,0 @@
1
- class Message
2
- include Mongoid::Document
3
-
4
- field :identifier
5
- field :from
6
- field :to
7
-
8
- if Mongoid::Compatibility::Version.mongoid6_or_newer?
9
- belongs_to :user, optional: true
10
- else
11
- belongs_to :user
12
- end
13
-
14
- validates :identifier, uniqueness: { message: 'uniqueness' }
15
- validates :from, presence: { message: 'required' }
16
- validates :to, format: { with: /[a-z]+/, message: 'format' }
17
- end
@@ -1,7 +0,0 @@
1
- class MovieArticle < Article
2
- field :rating, type: Float
3
- field :classification, type: Integer
4
-
5
- validates :rating, numericality: { greater_than: 0, less_than_or_equal_to: 5 }
6
- validates :classification, numericality: { even: true, only_integer: true, allow_nil: false }
7
- end
@@ -1,5 +0,0 @@
1
- class Permalink
2
- include Mongoid::Document
3
-
4
- embedded_in :linkable, inverse_of: :link
5
- end
@@ -1,10 +0,0 @@
1
- require 'ssn_validator.rb'
2
-
3
- class Person
4
- include Mongoid::Document
5
-
6
- field :name
7
- field :ssn
8
-
9
- validates :ssn, ssn: true
10
- end
@@ -1,16 +0,0 @@
1
- class Profile
2
- include Mongoid::Document
3
-
4
- field :first_name
5
- field :last_name
6
- field :age
7
- field :hobbies, type: Array, default: []
8
-
9
- embedded_in :user, inverse_of: :profile
10
-
11
- validates :age, numericality: { greater_than: 0 }
12
- validates :terms_of_service, acceptance: true
13
- validates :hobbies, length: { minimum: 1, message: 'requires at least one hobby' }
14
-
15
- index(first_name: 1, last_name: 1)
16
- end
@@ -1,5 +0,0 @@
1
- class Record
2
- include Mongoid::Document
3
-
4
- belongs_to :user, inverse_of: :record
5
- end
data/spec/models/site.rb DELETED
@@ -1,13 +0,0 @@
1
- class Site
2
- include Mongoid::Document
3
-
4
- field :name
5
-
6
- if Mongoid::Compatibility::Version.mongoid6_or_older?
7
- has_many :users, inverse_of: :site, order: :email.desc, counter_cache: true
8
- else
9
- has_many :users, inverse_of: :site, order: :email.desc
10
- end
11
-
12
- validates :name, presence: true, uniqueness: true
13
- end
data/spec/models/user.rb DELETED
@@ -1,38 +0,0 @@
1
- class User
2
- include Mongoid::Document
3
- include Mongoid::Timestamps::Created
4
-
5
- field :login
6
- field :email
7
- field :role
8
- field :age, type: Integer
9
- field :password, type: String
10
- field :provider_uid
11
- field :locale
12
-
13
- belongs_to :site, inverse_of: :users
14
- has_many :articles, foreign_key: :author_id, order: :title
15
- has_many :comments, dependent: :destroy, autosave: true
16
- has_many :messages, dependent: :destroy
17
- has_and_belongs_to_many :children, class_name: 'User'
18
- has_one :record, autobuild: true, inverse_of: :user
19
-
20
- embeds_one :profile, inverse_of: :user
21
-
22
- validates :login, presence: true, uniqueness: { scope: :site }, format: { with: /\A[\w\-]+\z/ }, exclusion: { in: %w[super index edit] }
23
- validates :email, uniqueness: { case_sensitive: false, scope: :site, message: 'is already taken' }, confirmation: true
24
- validates :role, presence: true, inclusion: { in: %w[admin moderator member] }
25
- validates :profile, presence: true, associated: true
26
- validates :age, presence: true, numericality: true, inclusion: { in: 23..42 }, on: %i[create update]
27
- validates :password, presence: true, on: %i[create update]
28
- validates :password, exclusion: { in: ->(_user) { ['password'] } }
29
- validates :password, confirmation: { message: 'Password confirmation must match given password' }
30
- validates :provider_uid, presence: true
31
- validates :locale, inclusion: { in: ->(_user) { %i[en ru] } }
32
-
33
- accepts_nested_attributes_for :articles, :comments
34
-
35
- def admin?
36
- false
37
- end
38
- end
data/spec/spec_helper.rb DELETED
@@ -1,35 +0,0 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
3
- MODELS = File.join(File.dirname(__FILE__), 'models')
4
- $LOAD_PATH.unshift(MODELS)
5
- VALIDATORS = File.join(File.dirname(__FILE__), 'validators')
6
- $LOAD_PATH.unshift(VALIDATORS)
7
-
8
- require 'rubygems'
9
- require 'bundler'
10
- Bundler.setup
11
-
12
- require 'mongoid'
13
- require 'rspec/core'
14
- require 'rspec/expectations'
15
- require 'mongoid/compatibility'
16
-
17
- Mongoid::Config.connect_to('mongoid-rspec-test') if Mongoid::Compatibility::Version.mongoid3_or_newer?
18
- Mongo::Logger.logger.level = ::Logger::INFO if Mongoid::Compatibility::Version.mongoid5_or_newer?
19
-
20
- Dir[File.join(MODELS, '*.rb')].sort.each { |file| require File.basename(file) }
21
-
22
- require 'mongoid-rspec'
23
-
24
- RSpec.configure do |config|
25
- config.include RSpec::Matchers
26
- config.include Mongoid::Matchers
27
- config.mock_with :rspec
28
- config.after :all do
29
- Mongoid::Config.purge!
30
- end
31
- config.after :suite do
32
- print "\n# Mongoid v#{Mongoid::VERSION}"
33
- end
34
- config.disable_monkey_patching!
35
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe 'AcceptsNestedAttributes' do
4
- describe User do
5
- it { is_expected.to accept_nested_attributes_for(:articles) }
6
- it { is_expected.to accept_nested_attributes_for(:comments) }
7
- end
8
-
9
- describe Article do
10
- it { is_expected.to accept_nested_attributes_for(:permalink) }
11
- end
12
- end
@@ -1,54 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe 'Associations' do
4
- describe User do
5
- if Mongoid::Compatibility::Version.mongoid6_or_newer?
6
- it { is_expected.to have_many(:articles).with_foreign_key(:author_id).ordered_by(:title) }
7
- end
8
-
9
- it { is_expected.to have_one(:record).as_inverse_of(:user).with_autobuild }
10
-
11
- it { is_expected.to have_many(:comments).with_dependent(:destroy).with_autosave }
12
-
13
- it { is_expected.to embed_one(:profile).as_inverse_of(:user) }
14
-
15
- it { is_expected.to have_and_belong_to_many(:children).of_type(User) }
16
- end
17
-
18
- describe Profile do
19
- it { is_expected.to be_embedded_in(:user).as_inverse_of(:profile) }
20
- end
21
-
22
- describe Article do
23
- it { is_expected.to belong_to(:author).of_type(User).as_inverse_of(:articles).with_index }
24
- it { is_expected.to embed_many(:comments).as_inverse_of(:article).with_cascading_callbacks }
25
- it { is_expected.to embed_one(:permalink).as_inverse_of(:linkable) }
26
- end
27
-
28
- describe Comment do
29
- it { is_expected.to be_embedded_in(:article).as_inverse_of(:comments).with_polymorphism }
30
- it { is_expected.to belong_to(:user).as_inverse_of(:comments) }
31
- end
32
-
33
- describe Record do
34
- it { is_expected.to belong_to(:user).as_inverse_of(:record) }
35
- end
36
-
37
- describe Permalink do
38
- it { is_expected.to be_embedded_in(:linkable).as_inverse_of(:link) }
39
- end
40
-
41
- describe Site do
42
- if Mongoid::Compatibility::Version.mongoid6_or_older?
43
- it { is_expected.to have_many(:users).as_inverse_of(:site).ordered_by(:email.desc).with_counter_cache }
44
- elsif Mongoid::Compatibility::Version.mongoid7_or_newer?
45
- it { is_expected.to have_many(:users).as_inverse_of(:site).ordered_by(:email.desc) }
46
- end
47
- end
48
-
49
- describe Message do
50
- if Mongoid::Compatibility::Version.mongoid6_or_newer?
51
- it { is_expected.to belong_to(:user).with_optional }
52
- end
53
- end
54
- end
@@ -1,21 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Mongoid::Matchers::BeDynamicDocument do
4
- context 'when model does\'t include Mongoid::Document' do
5
- subject do
6
- Class.new
7
- end
8
-
9
- it { is_expected.not_to be_mongoid_document }
10
- end
11
-
12
- context 'when model doesn\'t include Mongoid::Document' do
13
- subject do
14
- Class.new do
15
- include Mongoid::Document
16
- end
17
- end
18
-
19
- it { is_expected.to be_mongoid_document }
20
- end
21
- end
@@ -1,25 +0,0 @@
1
- require 'spec_helper'
2
- if Mongoid::Compatibility::Version.mongoid4_or_newer?
3
- RSpec.describe Mongoid::Matchers::BeMongoidDocument do
4
- context 'when model does\'t include Mongoid::Attributes::Dynamic' do
5
- subject do
6
- Class.new do
7
- include Mongoid::Document
8
- end
9
- end
10
-
11
- it { is_expected.not_to be_dynamic_document }
12
- end
13
-
14
- context 'when model doesn\'t include Mongoid::Attributes::Dynamic' do
15
- subject do
16
- Class.new do
17
- include Mongoid::Document
18
- include Mongoid::Attributes::Dynamic
19
- end
20
- end
21
-
22
- it { is_expected.to be_dynamic_document }
23
- end
24
- end
25
- end
@@ -1,54 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Mongoid::Matchers::BeStoredIn do
4
- subject do
5
- Class.new do
6
- include Mongoid::Document
7
- store_in collection: 'citizens', database: 'other', client: 'secondary'
8
- end
9
- end
10
-
11
- it 'detects storage options' do
12
- is_expected.to be_stored_in(collection: 'citizens', database: 'other', client: 'secondary')
13
- end
14
-
15
- it 'detects even part of storage options' do
16
- is_expected.to be_stored_in(database: 'other')
17
- is_expected.to be_stored_in(client: 'secondary')
18
- is_expected.to be_stored_in(collection: 'citizens')
19
- is_expected.to be_stored_in(collection: 'citizens', database: 'other')
20
- is_expected.to be_stored_in(database: 'other', client: 'secondary')
21
- is_expected.to be_stored_in(collection: 'citizens', client: 'secondary')
22
- end
23
-
24
- it 'detects differences' do
25
- is_expected.not_to be_stored_in(collection: 'aliens')
26
- end
27
-
28
- context 'when models has storage options defined via blocks, procs or lambdas' do
29
- subject do
30
- Class.new do
31
- include Mongoid::Document
32
- store_in database: -> { Thread.current[:database] }
33
- end
34
- end
35
-
36
- before do
37
- Thread.current[:database] = 'db1981'
38
- end
39
-
40
- it 'detects storage options' do
41
- is_expected.to be_stored_in(database: 'db1981')
42
- end
43
-
44
- it 'reflects changes in storage options' do
45
- is_expected.to be_stored_in(database: 'db1981')
46
- Thread.current[:database] = 'db2200'
47
- is_expected.to be_stored_in(database: 'db2200')
48
- end
49
-
50
- it 'detects differences' do
51
- is_expected.not_to be_stored_in(database: 'other')
52
- end
53
- end
54
- end
@@ -1,17 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe 'Document' do
4
- describe User do
5
- it { is_expected.to have_fields(:email, :login) }
6
- end
7
-
8
- describe Article do
9
- klass_boolean = Mongoid::Compatibility::Version.mongoid4_or_newer? ? Mongoid::Boolean : Boolean
10
- it { is_expected.to have_field(:published).of_type(klass_boolean).with_default_value_of(false) }
11
- it { is_expected.to have_field(:allow_comments).of_type(klass_boolean).with_default_value_of(true) }
12
- it { is_expected.to belong_to(:author) }
13
- it { is_expected.to have_field(:title).localized }
14
- it { is_expected.not_to have_field(:allow_comments).of_type(klass_boolean).with_default_value_of(false) }
15
- it { is_expected.not_to have_field(:number_of_comments).of_type(Integer).with_default_value_of(1) }
16
- end
17
- end
@@ -1,46 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Mongoid::Matchers::HaveIndexFor do
4
- subject do
5
- Class.new do
6
- include Mongoid::Document
7
-
8
- field :fizz, as: :buzz, type: String
9
-
10
- index(foo: 1)
11
- index({ bar: 1 }, unique: true, background: true, drop_dups: true)
12
- index(foo: 1, bar: -1)
13
- index('baz._id' => 1)
14
- index(buzz: 1)
15
- end
16
- end
17
-
18
- it 'detects an index for singular field key' do
19
- is_expected.to have_index_for(foo: 1)
20
- end
21
-
22
- it 'detects an index for multipple fields key' do
23
- is_expected.to have_index_for(foo: 1, bar: -1)
24
- end
25
-
26
- it 'detects an index with options' do
27
- is_expected
28
- .to have_index_for(bar: 1)
29
- .with_options(unique: true, background: true, drop_dups: true)
30
- end
31
-
32
- it 'detects an index with only part of options' do
33
- is_expected
34
- .to have_index_for(bar: 1)
35
- .with_options(unique: true)
36
- end
37
-
38
- it 'detects an index for string key' do
39
- is_expected.to have_index_for('baz._id' => 1)
40
- end
41
-
42
- it 'detect an index for aliased fields' do
43
- is_expected.to have_index_for(fizz: 1)
44
- is_expected.to have_index_for(buzz: 1) if Mongoid::Compatibility::Version.mongoid4_or_newer?
45
- end
46
- end
@@ -1,71 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Mongoid::Matchers::HaveTimestamps do
4
- context 'when model includes Mongoid::Timestamps' do
5
- subject do
6
- Class.new do
7
- include Mongoid::Document
8
- include Mongoid::Timestamps
9
- end
10
- end
11
-
12
- it { is_expected.to have_timestamps }
13
- end
14
-
15
- context 'when model includes Mongoid::Timestamps::Short' do
16
- subject do
17
- Class.new do
18
- include Mongoid::Document
19
- include Mongoid::Timestamps::Short
20
- end
21
- end
22
-
23
- it { is_expected.to have_timestamps.shortened }
24
- end
25
-
26
- context 'when model includes Mongoid::Timestamps::Updated' do
27
- subject do
28
- Class.new do
29
- include Mongoid::Document
30
- include Mongoid::Timestamps::Updated
31
- end
32
- end
33
-
34
- it { is_expected.to have_timestamps.for(:updating) }
35
- end
36
-
37
- context 'when model includes Mongoid::Timestamps::Updated::Short' do
38
- subject do
39
- Class.new do
40
- include Mongoid::Document
41
- include Mongoid::Timestamps::Updated::Short
42
- end
43
- end
44
-
45
- it { is_expected.to have_timestamps.for(:updating).shortened }
46
- it { is_expected.to have_timestamps.shortened.for(:updating) }
47
- end
48
-
49
- context 'when model includes Mongoid::Timestamps::Created' do
50
- subject do
51
- Class.new do
52
- include Mongoid::Document
53
- include Mongoid::Timestamps::Created
54
- end
55
- end
56
-
57
- it { is_expected.to have_timestamps.for(:creating) }
58
- end
59
-
60
- context 'when model includes Mongoid::Timestamps::Created::Short' do
61
- subject do
62
- Class.new do
63
- include Mongoid::Document
64
- include Mongoid::Timestamps::Created::Short
65
- end
66
- end
67
-
68
- it { is_expected.to have_timestamps.for(:creating).shortened }
69
- it { is_expected.to have_timestamps.shortened.for(:creating) }
70
- end
71
- end
@@ -1,61 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe 'Validations' do
4
- describe Site do
5
- it { is_expected.to validate_presence_of(:name) }
6
- it { is_expected.to validate_uniqueness_of(:name) }
7
- end
8
-
9
- describe User do
10
- it { is_expected.to validate_presence_of(:login) }
11
- it { is_expected.to validate_uniqueness_of(:login).scoped_to(:site) }
12
- it { is_expected.to validate_uniqueness_of(:email).case_insensitive.with_message('is already taken') }
13
- it { is_expected.to validate_format_of(:login).to_allow('valid_login').not_to_allow('invalid login') }
14
- it { is_expected.to validate_associated(:profile) }
15
- it { is_expected.to validate_exclusion_of(:login).to_not_allow('super', 'index', 'edit') }
16
- it { is_expected.to validate_exclusion_of(:password).to_not_allow('password') }
17
- it { is_expected.to validate_inclusion_of(:role).to_allow('admin', 'member') }
18
- it { is_expected.to validate_inclusion_of(:role).to_allow(%w[admin member]) }
19
- it { is_expected.to validate_confirmation_of(:email) }
20
- it { is_expected.to validate_presence_of(:age).on(:create, :update) }
21
- it { is_expected.to validate_numericality_of(:age).on(:create, :update) }
22
- it { is_expected.to validate_inclusion_of(:age).to_allow(23..42).on(%i[create update]) }
23
- it { is_expected.to validate_presence_of(:password).on(:create) }
24
- it { is_expected.to validate_confirmation_of(:password).with_message('Password confirmation must match given password') }
25
- it { is_expected.to validate_presence_of(:provider_uid).on(:create) }
26
- it { is_expected.to validate_inclusion_of(:locale).to_allow(%i[en ru]) }
27
- end
28
-
29
- describe Profile do
30
- it { is_expected.to validate_numericality_of(:age).greater_than(0) }
31
- it { is_expected.not_to validate_numericality_of(:age).greater_than(0).only_integer(true) }
32
- it { is_expected.to validate_acceptance_of(:terms_of_service) }
33
- it { is_expected.to validate_length_of(:hobbies).with_minimum(1).with_message('requires at least one hobby') }
34
- end
35
-
36
- describe Article do
37
- it { is_expected.to validate_length_of(:title).within(8..16) }
38
- it { is_expected.not_to validate_length_of(:content).greater_than(200).less_than(16) }
39
- it { is_expected.to validate_length_of(:content).greater_than(200) }
40
- it { is_expected.to validate_inclusion_of(:status).to_allow([:pending]).on(:create) }
41
- it { is_expected.to validate_inclusion_of(:status).to_allow(%i[approved rejected]).on(:update) }
42
- it { is_expected.to validate_absence_of(:deletion_date) } if Mongoid::Compatibility::Version.mongoid4_or_newer?
43
- end
44
-
45
- describe MovieArticle do
46
- it { is_expected.to validate_numericality_of(:rating).greater_than(0) }
47
- it { is_expected.to validate_numericality_of(:rating).to_allow(greater_than: 0).less_than_or_equal_to(5) }
48
- it { is_expected.to validate_numericality_of(:classification).to_allow(even: true, only_integer: true, nil: false) }
49
- end
50
-
51
- describe Person do
52
- it { is_expected.to custom_validate(:ssn).with_validator(SsnValidator) }
53
- it { is_expected.not_to custom_validate(:name) }
54
- end
55
-
56
- describe Message do
57
- it { is_expected.to validate_uniqueness_of(:identifier).with_message('uniqueness') }
58
- it { is_expected.to validate_presence_of(:from).with_message('required') }
59
- it { is_expected.to validate_format_of(:to).with_message('format') }
60
- end
61
- end
@@ -1,16 +0,0 @@
1
- class SsnValidator < ActiveModel::EachValidator
2
- def validate_each(record, attribute, value)
3
- unless valid_ssn?(record, attribute, value)
4
- record.errors[attribute] << "#{value} is not a valid Social Security Number"
5
- end
6
- end
7
-
8
- def self.kind
9
- :custom
10
- end
11
-
12
- def valid_ssn?(_record, _attribute, _value)
13
- # irrelevant here how validation is done
14
- true
15
- end
16
- end