mongoid-embedded-errors 2.0.1 → 4.0.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 +5 -5
- data/.codeclimate.yml +20 -0
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/.rubocop.yml +83 -0
- data/.semaphore/semaphore.yml +46 -0
- data/Appraisals +7 -0
- data/CHANGELOG.md +33 -0
- data/Gemfile +12 -3
- data/Guardfile +42 -0
- data/README.md +6 -7
- data/Rakefile +11 -7
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/mongoid_4.gemfile +16 -0
- data/gemfiles/mongoid_5.gemfile +16 -0
- data/gemfiles/mongoid_6.gemfile +16 -0
- data/gemfiles/mongoid_7.gemfile +19 -0
- data/gemfiles/mongoid_8.gemfile +19 -0
- data/lib/mongoid/embedded_errors/embedded_in.rb +18 -0
- data/lib/mongoid/embedded_errors/version.rb +6 -0
- data/lib/mongoid/embedded_errors.rb +51 -0
- data/lib/mongoid-embedded-errors.rb +3 -41
- data/mongoid-embedded-errors.gemspec +26 -15
- data/spec/lib/mongoid/embedded_errors_spec.rb +89 -0
- data/spec/spec_helper.rb +29 -10
- data/spec/support/database_cleaner.rb +18 -0
- data/spec/support/models/annotation.rb +11 -0
- data/spec/support/models/article.rb +17 -0
- data/spec/support/models/page.rb +13 -0
- data/spec/support/models/section.rb +13 -0
- data/spec/support/mongoid.yml +13 -0
- metadata +84 -24
- data/Gemfile.lock +0 -44
- data/lib/mongoid-embedded-errors/embedded_in.rb +0 -16
- data/lib/mongoid-embedded-errors/version.rb +0 -5
- data/spec/config.yml +0 -6
- data/spec/embedded_errors_spec.rb +0 -41
- data/spec/support/models.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5a086d5eabe3e2746bbf05833787ee55f8e4b838f666e3aea1c5780e860aa58c
|
4
|
+
data.tar.gz: 1f8a09d1d856795631b53f6cbfe1bf832f385a350ff9e8a4e6f7cc0f4c0815c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a6735fbef90d1143c2e724cdc2d33d669e6c829425e7ca4e1f548e2b7b11db5f817d1579cf1a6ba308c1758e628e70afc53865a3b35e84cbe2b3efee42d83cf
|
7
|
+
data.tar.gz: 7828bf072974db784c32622002c80650f0debb0858c10f4749906e77cb1ce5daa7658f483614b51b683e66db6f62c5334b4b322282eea247ff481e1ee3976422
|
data/.codeclimate.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
---
|
2
|
+
version: "2"
|
3
|
+
|
4
|
+
plugins:
|
5
|
+
rubocop:
|
6
|
+
enabled: true
|
7
|
+
bundler-audit:
|
8
|
+
enabled: true
|
9
|
+
fixme:
|
10
|
+
enabled: true
|
11
|
+
duplication:
|
12
|
+
enabled: true
|
13
|
+
reek:
|
14
|
+
enabled: true
|
15
|
+
git-legal:
|
16
|
+
enabled: true
|
17
|
+
|
18
|
+
config:
|
19
|
+
languages:
|
20
|
+
- ruby
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Use RuboCop RSpec
|
2
|
+
require: rubocop-rspec
|
3
|
+
|
4
|
+
# Common configuration.
|
5
|
+
AllCops:
|
6
|
+
# Cop names are not displayed in offense messages by default. Change behavior
|
7
|
+
# by overriding DisplayCopNames, or by giving the -D/--display-cop-names
|
8
|
+
# option.
|
9
|
+
DisplayCopNames: true
|
10
|
+
Exclude:
|
11
|
+
- Guardfile
|
12
|
+
- gemfiles/**/*
|
13
|
+
- bin/*
|
14
|
+
- vendor/bundle/**/*
|
15
|
+
- tmp/**/*
|
16
|
+
NewCops: enable
|
17
|
+
|
18
|
+
Naming/FileName:
|
19
|
+
Exclude:
|
20
|
+
- Appraisals
|
21
|
+
|
22
|
+
Layout/SpaceInsideHashLiteralBraces:
|
23
|
+
EnforcedStyle: no_space
|
24
|
+
EnforcedStyleForEmptyBraces: no_space
|
25
|
+
SupportedStyles:
|
26
|
+
- space
|
27
|
+
- no_space
|
28
|
+
|
29
|
+
Metrics/MethodLength:
|
30
|
+
CountComments: false # count full line comments?
|
31
|
+
Max: 40
|
32
|
+
|
33
|
+
Metrics/AbcSize:
|
34
|
+
Max: 40
|
35
|
+
|
36
|
+
Layout/LineLength:
|
37
|
+
Max: 120
|
38
|
+
|
39
|
+
Metrics/BlockLength:
|
40
|
+
Max: 50
|
41
|
+
|
42
|
+
Style/Documentation:
|
43
|
+
Description: 'Document classes and non-namespace modules.'
|
44
|
+
Enabled: false
|
45
|
+
|
46
|
+
Style/AutoResourceCleanup:
|
47
|
+
Description: 'Suggests the usage of an auto resource cleanup version of a method (if available).'
|
48
|
+
Enabled: true
|
49
|
+
|
50
|
+
Style/CollectionMethods:
|
51
|
+
Description: 'Preferred collection methods.'
|
52
|
+
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size'
|
53
|
+
Enabled: true
|
54
|
+
|
55
|
+
Style/MethodCalledOnDoEndBlock:
|
56
|
+
Description: 'Avoid chaining a method call on a do...end block.'
|
57
|
+
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks'
|
58
|
+
Enabled: true
|
59
|
+
|
60
|
+
Layout/ExtraSpacing:
|
61
|
+
Description: 'Do not use unnecessary spacing.'
|
62
|
+
Enabled: true
|
63
|
+
|
64
|
+
Style/ClassAndModuleChildren:
|
65
|
+
# Checks the style of children definitions at classes and modules.
|
66
|
+
#
|
67
|
+
# Basically there are two different styles:
|
68
|
+
#
|
69
|
+
# `nested` - have each child on a separate line
|
70
|
+
# class Foo
|
71
|
+
# class Bar
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# `compact` - combine definitions as much as possible
|
76
|
+
# class Foo::Bar
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# The compact style is only forced, for classes / modules with one child.
|
80
|
+
EnforcedStyle: compact
|
81
|
+
SupportedStyles:
|
82
|
+
- nested
|
83
|
+
- compact
|
@@ -0,0 +1,46 @@
|
|
1
|
+
version: v1.0
|
2
|
+
name: mongoid-embedded-errors
|
3
|
+
agent:
|
4
|
+
machine:
|
5
|
+
type: e1-standard-2
|
6
|
+
os_image: ubuntu1804
|
7
|
+
|
8
|
+
blocks:
|
9
|
+
- name: Code Climate
|
10
|
+
task:
|
11
|
+
jobs:
|
12
|
+
- name: Code Climate
|
13
|
+
commands:
|
14
|
+
- checkout
|
15
|
+
- cache restore gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock),gems-$SEMAPHORE_GIT_BRANCH,gems-master
|
16
|
+
- bundle install --path vendor/bundle
|
17
|
+
- cache store gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock) vendor/bundle
|
18
|
+
- docker run --interactive --tty --rm --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /tmp/cc:/tmp/cc --volume /var/run/docker.sock:/var/run/docker.sock codeclimate/codeclimate analyze
|
19
|
+
|
20
|
+
- name: Unit tests
|
21
|
+
task:
|
22
|
+
jobs:
|
23
|
+
- name: Appraisal
|
24
|
+
commands:
|
25
|
+
- checkout
|
26
|
+
- cache restore gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock),gems-$SEMAPHORE_GIT_BRANCH,gems-master
|
27
|
+
- bundle install --path vendor/bundle
|
28
|
+
- cache store gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock) vendor/bundle
|
29
|
+
- cache restore appraisal-$SEMAPHORE_GIT_BRANCH-$(checksum gemfiles/*.gemfile.lock),appraisal-$SEMAPHORE_GIT_BRANCH,appraisal-master
|
30
|
+
- bundle exec appraisal
|
31
|
+
- cache store appraisal-$SEMAPHORE_GIT_BRANCH-$(checksum gemfiles/*.gemfile.lock) vendor/bundle
|
32
|
+
- sem-service start mongodb
|
33
|
+
- bundle exec appraisal rake test
|
34
|
+
|
35
|
+
- name: Mutant
|
36
|
+
task:
|
37
|
+
jobs:
|
38
|
+
- name: Mutant
|
39
|
+
commands:
|
40
|
+
- checkout
|
41
|
+
- cache restore gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock),gems-$SEMAPHORE_GIT_BRANCH,gems-master
|
42
|
+
- bundle install --path vendor/bundle
|
43
|
+
- cache store gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock) vendor/bundle
|
44
|
+
- sem-service start mongodb
|
45
|
+
- MUTANT=true bundle exec mutant --since "$SEMAPHORE_GIT_SHA~1" --include lib --require mongoid --use rspec "Mongoid::EmbeddedErrors*"
|
46
|
+
|
data/Appraisals
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
5
|
+
|
6
|
+
## [Unreleased]
|
7
|
+
- TODO
|
8
|
+
|
9
|
+
## [v4.0.0] - 2022-08-31
|
10
|
+
- Fix rails 6 active model error deprecations (#22)
|
11
|
+
- Added Mongoid 8 support
|
12
|
+
- Dropped support for Mongoid 4, 5 and 6
|
13
|
+
|
14
|
+
## [v3.0.1] - 2020-09-29
|
15
|
+
### Added
|
16
|
+
- Started 🔎 tracking changes in a changelog!
|
17
|
+
- Mongoid 7 support
|
18
|
+
- Ruby 2.4 support by using `send` instead of `public_send` [#18]
|
19
|
+
|
20
|
+
### Removed
|
21
|
+
- Mongoid 3 support
|
22
|
+
|
23
|
+
### Fixed
|
24
|
+
- Updated style to fix Rubocop issues (as per included .rubocop.yml configuration file)
|
25
|
+
- Removed .lock files as these are not supposed to be included with gem source code
|
26
|
+
|
27
|
+
## [v3.0.0] - 2020-09-29 [YANKED]
|
28
|
+
- Yanked due to wrong dependencies in gemspec.
|
29
|
+
|
30
|
+
[Unreleased]: https://github.com/glooko/mongoid-embedded-errors/compare/v4.0.0...HEAD
|
31
|
+
[v4.0.0]: https://github.com/glooko/mongoid-embedded-errors/compare/v3.0.1...v4.0.0
|
32
|
+
[v3.0.1]: https://github.com/glooko/mongoid-embedded-errors/compare/v3.0.0...v3.0.1
|
33
|
+
[v3.0.0]: https://github.com/glooko/mongoid-embedded-errors/compare/f1ce0d8ed140de86c894b2fad7ad197504fefd5a...v3.0.0
|
data/Gemfile
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in
|
3
|
+
# Specify your gem's dependencies in mongoid-embedded-errors.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
|
7
|
-
gem '
|
6
|
+
group :development do
|
7
|
+
gem 'rake'
|
8
|
+
end
|
9
|
+
|
10
|
+
group :test do
|
11
|
+
gem 'appraisal'
|
12
|
+
gem 'database_cleaner-mongoid', '~> 2.0', '>= 2.0.1'
|
13
|
+
gem 'guard-rspec'
|
14
|
+
gem 'mutant-rspec'
|
15
|
+
gem 'rspec'
|
16
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features) \
|
6
|
+
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
7
|
+
|
8
|
+
## Note: if you are using the `directories` clause above and you are not
|
9
|
+
## watching the project directory ('.'), then you will want to move
|
10
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
11
|
+
#
|
12
|
+
# $ mkdir config
|
13
|
+
# $ mv Guardfile config/
|
14
|
+
# $ ln -s config/Guardfile .
|
15
|
+
#
|
16
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
|
+
|
18
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
19
|
+
# rspec may be run, below are examples of the most common uses.
|
20
|
+
# * bundler: 'bundle exec rspec'
|
21
|
+
# * bundler binstubs: 'bin/rspec'
|
22
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
23
|
+
# installed the spring binstubs per the docs)
|
24
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
|
+
# * 'just' rspec: 'rspec'
|
26
|
+
|
27
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
28
|
+
require "guard/rspec/dsl"
|
29
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
30
|
+
|
31
|
+
# Feel free to open issues for suggestions and improvements
|
32
|
+
|
33
|
+
# RSpec files
|
34
|
+
rspec = dsl.rspec
|
35
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
36
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
37
|
+
watch(rspec.spec_files)
|
38
|
+
|
39
|
+
# Ruby files
|
40
|
+
ruby = dsl.ruby
|
41
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
42
|
+
end
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Mongoid::EmbeddedErrors
|
2
|
+
[](https://codeclimate.com/github/glooko/mongoid-embedded-errors)
|
2
3
|
|
3
|
-
Easily bubble up errors from embedded documents in Mongoid.
|
4
|
+
Easily bubble up errors from embedded documents in Mongoid and newer.
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
@@ -61,7 +62,7 @@ If we were to create an invalid `Article` with an invalid `Page` and tried to va
|
|
61
62
|
article = Article.new(pages: [Page.new])
|
62
63
|
article.valid? # => false
|
63
64
|
|
64
|
-
article.
|
65
|
+
article.errors.messages
|
65
66
|
# => {:name=>["can't be blank"], :summary=>["can't be blank"], :pages=>["is invalid"]}
|
66
67
|
```
|
67
68
|
|
@@ -83,7 +84,7 @@ end
|
|
83
84
|
article = Article.new(pages: [Page.new(sections: [Section.new])])
|
84
85
|
article.valid? # => false
|
85
86
|
|
86
|
-
article.
|
87
|
+
article.errors.messages
|
87
88
|
{
|
88
89
|
:name => ["can't be blank"],
|
89
90
|
:summary => ["can't be blank"],
|
@@ -102,8 +103,6 @@ Now, isn't that much nicer? Yeah, I think so to.
|
|
102
103
|
4. Push to the branch (`git push origin my-new-feature`)
|
103
104
|
5. Create new Pull Request
|
104
105
|
|
105
|
-
##
|
106
|
+
## Contributors
|
106
107
|
|
107
|
-
|
108
|
-
* Evgeniy Denisov
|
109
|
-
* Nick Plante
|
108
|
+
[See here](https://github.com/glooko/mongoid-embedded-errors/graphs/contributors)
|
data/Rakefile
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
|
2
6
|
Bundler::GemHelper.install_tasks
|
3
7
|
|
4
|
-
desc
|
5
|
-
task :
|
8
|
+
desc 'Run tests'
|
9
|
+
task default: [:test]
|
6
10
|
|
7
|
-
|
11
|
+
desc 'Run tests'
|
12
|
+
task spec: [:test]
|
8
13
|
|
9
|
-
|
10
|
-
|
11
|
-
end
|
14
|
+
desc 'Run tests'
|
15
|
+
task(:test) { system 'bundle exec rspec' }
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "mongoid", "~> 4.0"
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "appraisal"
|
9
|
+
gem "database_cleaner"
|
10
|
+
gem "guard-rspec"
|
11
|
+
gem "mutant-rspec"
|
12
|
+
gem "rake"
|
13
|
+
gem "rspec"
|
14
|
+
end
|
15
|
+
|
16
|
+
gemspec path: "../"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "mongoid", "~> 5.0"
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "appraisal"
|
9
|
+
gem "database_cleaner"
|
10
|
+
gem "guard-rspec"
|
11
|
+
gem "mutant-rspec"
|
12
|
+
gem "rake"
|
13
|
+
gem "rspec"
|
14
|
+
end
|
15
|
+
|
16
|
+
gemspec path: "../"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "mongoid", "~> 6.0"
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "appraisal"
|
9
|
+
gem "database_cleaner"
|
10
|
+
gem "guard-rspec"
|
11
|
+
gem "mutant-rspec"
|
12
|
+
gem "rake"
|
13
|
+
gem "rspec"
|
14
|
+
end
|
15
|
+
|
16
|
+
gemspec path: "../"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "mongoid", "~> 7.0"
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "rake"
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem "appraisal"
|
13
|
+
gem "database_cleaner-mongoid", "~> 2.0", ">= 2.0.1"
|
14
|
+
gem "guard-rspec"
|
15
|
+
gem "mutant-rspec"
|
16
|
+
gem "rspec"
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec path: "../"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "mongoid", "~> 8.0"
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "rake"
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem "appraisal"
|
13
|
+
gem "database_cleaner-mongoid", "~> 2.0", ">= 2.0.1"
|
14
|
+
gem "guard-rspec"
|
15
|
+
gem "mutant-rspec"
|
16
|
+
gem "rspec"
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec path: "../"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
if Gem::Version.new(Mongoid::VERSION) >= Gem::Version.new('7.0.0')
|
2
|
+
require 'mongoid/association/embedded/embedded_in'
|
3
|
+
ASSOCIATION = Mongoid::Association::Macros::ClassMethods
|
4
|
+
EMBEDS_MANY = Mongoid::Association::Embedded::EmbedsMany
|
5
|
+
else
|
6
|
+
require 'mongoid/relations/embedded/in'
|
7
|
+
ASSOCIATION = Mongoid::Relations::Macros::ClassMethods
|
8
|
+
EMBEDS_MANY = Mongoid::Relations::Embedded::Many
|
9
|
+
end
|
10
|
+
|
11
|
+
module ASSOCIATION
|
12
|
+
alias embedded_in_without_embedded_errors embedded_in
|
13
|
+
def embedded_in(*args)
|
14
|
+
relation = embedded_in_without_embedded_errors(*args)
|
15
|
+
send(:include, Mongoid::EmbeddedErrors)
|
16
|
+
relation
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mongoid'
|
4
|
+
require 'mongoid/embedded_errors/version'
|
5
|
+
require 'mongoid/embedded_errors/embedded_in'
|
6
|
+
|
7
|
+
module Mongoid::EmbeddedErrors
|
8
|
+
def self.included(klass)
|
9
|
+
return if klass.instance_methods.include?(:errors_without_embedded_errors)
|
10
|
+
|
11
|
+
klass.send :alias_method, :errors_without_embedded_errors, :errors
|
12
|
+
klass.send :alias_method, :errors, :errors_with_embedded_errors
|
13
|
+
end
|
14
|
+
|
15
|
+
def errors_with_embedded_errors
|
16
|
+
errors_without_embedded_errors.tap do |errs|
|
17
|
+
embedded_relations.each do |name, metadata|
|
18
|
+
# name is something like pages or sections
|
19
|
+
# if there is an 'is invalid' message for the relation then let's work it:
|
20
|
+
next unless Array(public_send(name)).any? { |doc| doc.errors.any? }
|
21
|
+
|
22
|
+
# first delete the generic 'is invalid' error for the relation
|
23
|
+
errs.delete name.to_sym, :invalid
|
24
|
+
errs.delete name.to_sym if errs[name].empty?
|
25
|
+
|
26
|
+
# next, loop through each of the relations (pages, sections, etc...)
|
27
|
+
[public_send(name)].flatten.reject(&:nil?).each_with_index do |rel, i|
|
28
|
+
next unless rel.errors.any?
|
29
|
+
|
30
|
+
# get each of their individual message and add them to the parent's errors:
|
31
|
+
rel.errors.each do |error|
|
32
|
+
attribute = error.attribute
|
33
|
+
message = error.message
|
34
|
+
relation = if Gem::Version.new(Mongoid::VERSION) >= Gem::Version.new('7.0.0')
|
35
|
+
metadata.class
|
36
|
+
else
|
37
|
+
metadata.relation
|
38
|
+
end
|
39
|
+
key = if relation.equal? EMBEDS_MANY
|
40
|
+
"#{name}[#{i}].#{attribute}"
|
41
|
+
else
|
42
|
+
"#{name}.#{attribute}"
|
43
|
+
end.to_sym
|
44
|
+
errs.delete(key)
|
45
|
+
errs.add key, message if message.present?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,41 +1,3 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
module Mongoid
|
6
|
-
module EmbeddedErrors
|
7
|
-
|
8
|
-
def self.included(klass)
|
9
|
-
# make sure that the alias only happens once:
|
10
|
-
unless klass.instance_methods.include?(:errors_without_embedded_errors)
|
11
|
-
klass.alias_method_chain(:errors, :embedded_errors)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def errors_with_embedded_errors
|
16
|
-
errs = errors_without_embedded_errors
|
17
|
-
self.embedded_relations.each do |name, metadata|
|
18
|
-
# name is something like pages or sections
|
19
|
-
# if there is an 'is invalid' message for the relation then let's work it:
|
20
|
-
if errs[name]
|
21
|
-
# first delete the unless 'is invalid' error for the relation
|
22
|
-
errs.delete(name.to_sym)
|
23
|
-
# next, loop through each of the relations (pages, sections, etc...)
|
24
|
-
[self.send(name)].flatten.reject(&:nil?).each_with_index do |rel, i|
|
25
|
-
# get each of their individual message and add them to the parent's errors:
|
26
|
-
if rel.errors.any?
|
27
|
-
rel.errors.messages.each do |k, v|
|
28
|
-
key = (rel.metadata.relation == Mongoid::Relations::Embedded::Many ? "#{name}[#{i}].#{k}" : "#{name}.#{k}").to_sym
|
29
|
-
errs.delete(key)
|
30
|
-
errs[key] = v
|
31
|
-
errs[key].flatten!
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
return errs
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
1
|
+
# rubocop:disable Naming/FileName
|
2
|
+
require 'mongoid/embedded_errors'
|
3
|
+
# rubocop:enable Naming/FileName
|
@@ -1,21 +1,32 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'mongoid
|
5
|
+
require 'mongoid/embedded_errors/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |gem|
|
7
|
-
gem.name =
|
8
|
-
gem.version = Mongoid::EmbeddedErrors::VERSION
|
9
|
-
gem.authors = [
|
10
|
-
gem.email = [
|
11
|
-
gem.description =
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
gem.name = 'mongoid-embedded-errors'
|
9
|
+
gem.version = Mongoid::EmbeddedErrors::VERSION.dup
|
10
|
+
gem.authors = ['Mark Bates', 'Kristijan Novoselić']
|
11
|
+
gem.email = ['mark@markbates.com', 'kristijan@glooko.com']
|
12
|
+
gem.description = 'Embedded documents in Mongoid can be really useful. '\
|
13
|
+
'However, when one of those embedded documents is '\
|
14
|
+
'invalid, Mongoid does not say which validation has '\
|
15
|
+
'failed. Instead of just saying that an embedded '\
|
16
|
+
'document is invalid, this gem modifies Mongoid '\
|
17
|
+
'behavior so it explicitly provides validation errors '\
|
18
|
+
'on a per-field basis for embedded documents, the '\
|
19
|
+
'same way it does for parent documents.'
|
20
|
+
gem.summary = 'Easily bubble up errors from embedded '\
|
21
|
+
'documents in Mongoid.'
|
22
|
+
gem.homepage = 'https://github.com/glooko/mongoid-embedded-errors'
|
23
|
+
gem.licenses = ['MIT']
|
24
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
25
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
17
26
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.require_paths = [
|
27
|
+
gem.require_paths = ['lib']
|
19
28
|
|
20
|
-
gem.add_dependency
|
29
|
+
gem.add_dependency 'mongoid', '>=7.0', '<9.0.0'
|
30
|
+
gem.add_development_dependency 'rubocop', '~> 0.92'
|
31
|
+
gem.add_development_dependency 'rubocop-rspec', '~> 1.43'
|
21
32
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Mongoid::EmbeddedErrors do
|
4
|
+
describe '#errors_with_embedded_errors' do
|
5
|
+
subject(:article) { Article.new name: 'Test', summary: '-', pages: pages }
|
6
|
+
|
7
|
+
before { |spec| article.validate unless spec.metadata[:do_not_validate] }
|
8
|
+
|
9
|
+
context 'when module is already included in a class', :do_not_validate do
|
10
|
+
let(:dummy_class) do
|
11
|
+
Class.new do
|
12
|
+
include Mongoid::Document
|
13
|
+
include Mongoid::EmbeddedErrors
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'does not create errors_without_embedded_errors alias again' do
|
18
|
+
a = dummy_class.instance_method(:errors_without_embedded_errors)
|
19
|
+
dummy_class.include described_class
|
20
|
+
|
21
|
+
expect(
|
22
|
+
a
|
23
|
+
).to eq(dummy_class.instance_method(:errors_without_embedded_errors))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when article does not have any pages associated' do
|
28
|
+
let(:pages) { [] }
|
29
|
+
|
30
|
+
it { is_expected.not_to be_valid }
|
31
|
+
|
32
|
+
it "returns `can't be blank` error for pages" do
|
33
|
+
expect(article.errors[:pages]).to include "can't be blank"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when article has one or more invalid pages' do
|
38
|
+
let(:pages) { [Page.new] }
|
39
|
+
|
40
|
+
it { is_expected.not_to be_valid }
|
41
|
+
|
42
|
+
it 'does not have any errors under `:pages` key' do
|
43
|
+
expect(article.errors[:pages]).to be_empty
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns all errors for `pages[0]` object' do
|
47
|
+
expect(article.errors[:'pages[0].title']).to include "can't be blank"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when validated multiple times' do
|
52
|
+
let(:pages) { [Page.new] }
|
53
|
+
|
54
|
+
it 'does not have duplicated errors for the same object' do
|
55
|
+
article.valid?
|
56
|
+
expect(article.errors[:'pages[0].title']).to eq(["can't be blank"])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when embeds_many relation is invalid' do
|
61
|
+
let(:pages) { [Page.new(title: 'Test page', sections: sections)] }
|
62
|
+
let(:sections) { [Section.new] }
|
63
|
+
|
64
|
+
it 'returns all errors for `sections[0]` object' do
|
65
|
+
expect(article.errors[:'pages[0].sections[0].header']).to include "can't be blank"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when embeds_one relation is invalid' do
|
70
|
+
subject(:article) { Article.new name: 'Test', summary: '-', pages: pages, annotation: annotation }
|
71
|
+
|
72
|
+
let(:pages) { [Page.new(title: 'Test page')] }
|
73
|
+
let(:annotation) { Annotation.new }
|
74
|
+
|
75
|
+
it 'returns all errors for `annotation` object' do
|
76
|
+
expect(article.errors[:'annotation.text']).to include "can't be blank"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when embedded document has not been validated',
|
81
|
+
:do_not_validate do
|
82
|
+
let(:pages) { [Page.new] }
|
83
|
+
|
84
|
+
it 'does not trigger validations' do
|
85
|
+
expect(article.errors).to be_empty
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,18 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'mongoid-embedded-errors' # and any other gems you need
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
require '
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'mongoid-embedded-errors'
|
5
|
+
require 'database_cleaner-mongoid'
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
current_path = File.dirname(__FILE__)
|
8
|
+
SPEC_MODELS_PATH = File.join(current_path, 'support/**/*.rb').freeze
|
9
|
+
Dir[SPEC_MODELS_PATH].each { |f| require f }
|
9
10
|
|
10
|
-
|
11
|
+
Mongoid.load! File.join(current_path, 'support/mongoid.yml'), :test
|
11
12
|
|
12
13
|
RSpec.configure do |config|
|
14
|
+
config.run_all_when_everything_filtered = true
|
15
|
+
config.filter_run :focus
|
16
|
+
config.filter_run_excluding :skip
|
13
17
|
|
14
|
-
config.
|
15
|
-
|
18
|
+
config.expect_with :rspec do |expectations|
|
19
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
20
|
+
expectations.syntax = :expect
|
16
21
|
end
|
17
22
|
|
18
|
-
|
23
|
+
config.mock_with :rspec do |mocks|
|
24
|
+
mocks.verify_partial_doubles = true
|
25
|
+
end
|
26
|
+
config.disable_monkey_patching!
|
27
|
+
|
28
|
+
config.before do
|
29
|
+
# Need to manually reload spec models for mutant to work as expected
|
30
|
+
if ENV['MUTANT']
|
31
|
+
Dir[SPEC_MODELS_PATH].each do |filename|
|
32
|
+
Object.send(:remove_const, File.basename(filename, '.rb').capitalize)
|
33
|
+
load filename
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
DatabaseCleaner.strategy = :deletion
|
5
|
+
config.around do |example|
|
6
|
+
DatabaseCleaner.cleaning do
|
7
|
+
example.run
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
config.before(:all) do
|
12
|
+
DatabaseCleaner.start
|
13
|
+
end
|
14
|
+
|
15
|
+
config.after(:all) do
|
16
|
+
DatabaseCleaner.clean
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Article
|
4
|
+
include Mongoid::Document
|
5
|
+
include Mongoid::Timestamps
|
6
|
+
include Mongoid::EmbeddedErrors
|
7
|
+
|
8
|
+
embeds_many :pages
|
9
|
+
embeds_one :annotation
|
10
|
+
|
11
|
+
field :name, type: String
|
12
|
+
field :summary, type: String
|
13
|
+
|
14
|
+
validates :name, presence: true
|
15
|
+
validates :summary, presence: true
|
16
|
+
validates :pages, presence: true
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Section
|
4
|
+
include Mongoid::Document
|
5
|
+
include Mongoid::Timestamps
|
6
|
+
|
7
|
+
embedded_in :page, inverse_of: :sections
|
8
|
+
|
9
|
+
field :header, type: String
|
10
|
+
field :body, type: String
|
11
|
+
|
12
|
+
validates :header, presence: true
|
13
|
+
end
|
metadata
CHANGED
@@ -1,52 +1,110 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-embedded-errors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Bates
|
8
|
+
- Kristijan Novoselić
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2022-08-30 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: mongoid
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- -
|
18
|
+
- - ">="
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
+
version: '7.0'
|
21
|
+
- - "<"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 9.0.0
|
20
24
|
type: :runtime
|
21
25
|
prerelease: false
|
22
26
|
version_requirements: !ruby/object:Gem::Requirement
|
23
27
|
requirements:
|
24
|
-
- -
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '7.0'
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 9.0.0
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rubocop
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.92'
|
41
|
+
type: :development
|
42
|
+
prerelease: false
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.92'
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rubocop-rspec
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.43'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
25
60
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
description:
|
61
|
+
version: '1.43'
|
62
|
+
description: Embedded documents in Mongoid can be really useful. However, when one
|
63
|
+
of those embedded documents is invalid, Mongoid does not say which validation has
|
64
|
+
failed. Instead of just saying that an embedded document is invalid, this gem modifies
|
65
|
+
Mongoid behavior so it explicitly provides validation errors on a per-field basis
|
66
|
+
for embedded documents, the same way it does for parent documents.
|
28
67
|
email:
|
29
68
|
- mark@markbates.com
|
69
|
+
- kristijan@glooko.com
|
30
70
|
executables: []
|
31
71
|
extensions: []
|
32
72
|
extra_rdoc_files: []
|
33
73
|
files:
|
34
|
-
- .
|
74
|
+
- ".codeclimate.yml"
|
75
|
+
- ".gitignore"
|
76
|
+
- ".rspec"
|
77
|
+
- ".rubocop.yml"
|
78
|
+
- ".semaphore/semaphore.yml"
|
79
|
+
- Appraisals
|
80
|
+
- CHANGELOG.md
|
35
81
|
- Gemfile
|
36
|
-
-
|
82
|
+
- Guardfile
|
37
83
|
- LICENSE.txt
|
38
84
|
- README.md
|
39
85
|
- Rakefile
|
86
|
+
- gemfiles/.bundle/config
|
87
|
+
- gemfiles/mongoid_4.gemfile
|
88
|
+
- gemfiles/mongoid_5.gemfile
|
89
|
+
- gemfiles/mongoid_6.gemfile
|
90
|
+
- gemfiles/mongoid_7.gemfile
|
91
|
+
- gemfiles/mongoid_8.gemfile
|
40
92
|
- lib/mongoid-embedded-errors.rb
|
41
|
-
- lib/mongoid
|
42
|
-
- lib/mongoid
|
93
|
+
- lib/mongoid/embedded_errors.rb
|
94
|
+
- lib/mongoid/embedded_errors/embedded_in.rb
|
95
|
+
- lib/mongoid/embedded_errors/version.rb
|
43
96
|
- mongoid-embedded-errors.gemspec
|
44
|
-
- spec/
|
45
|
-
- spec/embedded_errors_spec.rb
|
97
|
+
- spec/lib/mongoid/embedded_errors_spec.rb
|
46
98
|
- spec/spec_helper.rb
|
47
|
-
- spec/support/
|
48
|
-
|
49
|
-
|
99
|
+
- spec/support/database_cleaner.rb
|
100
|
+
- spec/support/models/annotation.rb
|
101
|
+
- spec/support/models/article.rb
|
102
|
+
- spec/support/models/page.rb
|
103
|
+
- spec/support/models/section.rb
|
104
|
+
- spec/support/mongoid.yml
|
105
|
+
homepage: https://github.com/glooko/mongoid-embedded-errors
|
106
|
+
licenses:
|
107
|
+
- MIT
|
50
108
|
metadata: {}
|
51
109
|
post_install_message:
|
52
110
|
rdoc_options: []
|
@@ -54,23 +112,25 @@ require_paths:
|
|
54
112
|
- lib
|
55
113
|
required_ruby_version: !ruby/object:Gem::Requirement
|
56
114
|
requirements:
|
57
|
-
- -
|
115
|
+
- - ">="
|
58
116
|
- !ruby/object:Gem::Version
|
59
117
|
version: '0'
|
60
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
119
|
requirements:
|
62
|
-
- -
|
120
|
+
- - ">="
|
63
121
|
- !ruby/object:Gem::Version
|
64
122
|
version: '0'
|
65
123
|
requirements: []
|
66
|
-
|
67
|
-
rubygems_version: 2.0.3
|
124
|
+
rubygems_version: 3.1.6
|
68
125
|
signing_key:
|
69
126
|
specification_version: 4
|
70
127
|
summary: Easily bubble up errors from embedded documents in Mongoid.
|
71
128
|
test_files:
|
72
|
-
- spec/
|
73
|
-
- spec/embedded_errors_spec.rb
|
129
|
+
- spec/lib/mongoid/embedded_errors_spec.rb
|
74
130
|
- spec/spec_helper.rb
|
75
|
-
- spec/support/
|
76
|
-
|
131
|
+
- spec/support/database_cleaner.rb
|
132
|
+
- spec/support/models/annotation.rb
|
133
|
+
- spec/support/models/article.rb
|
134
|
+
- spec/support/models/page.rb
|
135
|
+
- spec/support/models/section.rb
|
136
|
+
- spec/support/mongoid.yml
|
data/Gemfile.lock
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
mongoid-embedded-errors (2.0.1)
|
5
|
-
mongoid (>= 3.0.0)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
activemodel (3.2.13)
|
11
|
-
activesupport (= 3.2.13)
|
12
|
-
builder (~> 3.0.0)
|
13
|
-
activesupport (3.2.13)
|
14
|
-
i18n (= 0.6.1)
|
15
|
-
multi_json (~> 1.0)
|
16
|
-
builder (3.0.4)
|
17
|
-
database_cleaner (0.9.1)
|
18
|
-
diff-lcs (1.1.3)
|
19
|
-
i18n (0.6.1)
|
20
|
-
mongoid (3.1.2)
|
21
|
-
activemodel (~> 3.2)
|
22
|
-
moped (~> 1.4.2)
|
23
|
-
origin (~> 1.0)
|
24
|
-
tzinfo (~> 0.3.22)
|
25
|
-
moped (1.4.5)
|
26
|
-
multi_json (1.7.7)
|
27
|
-
origin (1.1.0)
|
28
|
-
rspec (2.11.0)
|
29
|
-
rspec-core (~> 2.11.0)
|
30
|
-
rspec-expectations (~> 2.11.0)
|
31
|
-
rspec-mocks (~> 2.11.0)
|
32
|
-
rspec-core (2.11.1)
|
33
|
-
rspec-expectations (2.11.3)
|
34
|
-
diff-lcs (~> 1.1.3)
|
35
|
-
rspec-mocks (2.11.3)
|
36
|
-
tzinfo (0.3.37)
|
37
|
-
|
38
|
-
PLATFORMS
|
39
|
-
ruby
|
40
|
-
|
41
|
-
DEPENDENCIES
|
42
|
-
database_cleaner
|
43
|
-
mongoid-embedded-errors!
|
44
|
-
rspec
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require "mongoid/relations/embedded/in"
|
2
|
-
|
3
|
-
module Mongoid
|
4
|
-
module Relations
|
5
|
-
module Macros
|
6
|
-
module ClassMethods
|
7
|
-
alias :embedded_in_without_embedded_errors :embedded_in
|
8
|
-
def embedded_in(*args)
|
9
|
-
relation = embedded_in_without_embedded_errors(*args)
|
10
|
-
self.send(:include, Mongoid::EmbeddedErrors)
|
11
|
-
return relation
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/spec/config.yml
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mongoid::EmbeddedErrors do
|
4
|
-
|
5
|
-
let(:article) { Article.new }
|
6
|
-
let(:invalid_page) { Page.new }
|
7
|
-
let(:invalid_section) { Section.new }
|
8
|
-
let(:valid_section) { Section.new(header: "My Header") }
|
9
|
-
let(:invalid_annotation){ Annotation.new }
|
10
|
-
|
11
|
-
describe "errors" do
|
12
|
-
|
13
|
-
it "bubbles up errors from embedded documents" do
|
14
|
-
invalid_page.sections << valid_section
|
15
|
-
invalid_page.sections << invalid_section
|
16
|
-
article.pages << invalid_page
|
17
|
-
article.annotation = invalid_annotation
|
18
|
-
article.should_not be_valid
|
19
|
-
article.errors.messages.should eql({
|
20
|
-
name: ["can't be blank"],
|
21
|
-
summary: ["can't be blank"],
|
22
|
-
:"pages[0].title" => ["can't be blank"],
|
23
|
-
:"pages[0].sections[1].header" => ["can't be blank"],
|
24
|
-
:"annotation.text" => ["can't be blank"]
|
25
|
-
})
|
26
|
-
end
|
27
|
-
|
28
|
-
it "save works as before" do
|
29
|
-
article.save.should be_false
|
30
|
-
article.should_not be_persisted
|
31
|
-
article.errors.messages.should eql(name: ["can't be blank"], summary: ["can't be blank"])
|
32
|
-
end
|
33
|
-
|
34
|
-
it "handles errors on the main object" do
|
35
|
-
article.should_not be_valid
|
36
|
-
article.errors.messages.should eql(name: ["can't be blank"], summary: ["can't be blank"])
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
data/spec/support/models.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
class Article
|
2
|
-
include Mongoid::Document
|
3
|
-
include Mongoid::Timestamps
|
4
|
-
include Mongoid::EmbeddedErrors
|
5
|
-
|
6
|
-
field :name, type: String
|
7
|
-
field :summary, type: String
|
8
|
-
|
9
|
-
validates :name, presence: true
|
10
|
-
validates :summary, presence: true
|
11
|
-
|
12
|
-
embeds_many :pages
|
13
|
-
embeds_one :annotation
|
14
|
-
end
|
15
|
-
|
16
|
-
class Page
|
17
|
-
include Mongoid::Document
|
18
|
-
include Mongoid::Timestamps
|
19
|
-
|
20
|
-
field :title, type: String
|
21
|
-
|
22
|
-
validates :title, presence: true
|
23
|
-
|
24
|
-
embedded_in :article, inverse_of: :pages
|
25
|
-
embeds_many :sections
|
26
|
-
end
|
27
|
-
|
28
|
-
class Section
|
29
|
-
include Mongoid::Document
|
30
|
-
include Mongoid::Timestamps
|
31
|
-
|
32
|
-
field :header, type: String
|
33
|
-
field :body, type: String
|
34
|
-
|
35
|
-
validates :header, presence: true
|
36
|
-
|
37
|
-
embedded_in :page, inverse_of: :sections
|
38
|
-
end
|
39
|
-
|
40
|
-
class Annotation
|
41
|
-
include Mongoid::Document
|
42
|
-
|
43
|
-
embedded_in :article, inverse_of: :annotation
|
44
|
-
|
45
|
-
field :text, type: String
|
46
|
-
|
47
|
-
validates :text, presence: true
|
48
|
-
|
49
|
-
end
|