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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 96ef455929fe07047621a0d5a2e33c576ee05926
4
- data.tar.gz: dff154361af3fac2c963cd4ba7652902b8190441
2
+ SHA256:
3
+ metadata.gz: 5a086d5eabe3e2746bbf05833787ee55f8e4b838f666e3aea1c5780e860aa58c
4
+ data.tar.gz: 1f8a09d1d856795631b53f6cbfe1bf832f385a350ff9e8a4e6f7cc0f4c0815c5
5
5
  SHA512:
6
- metadata.gz: b70add5efeb3f66dd603edd5104537cbead19775fe643afa265b7fc1aef6ff2f308dcba412f0aafb5ae67256bdf86318917bb5a2632f910b254f4f4cd39054a0
7
- data.tar.gz: fd0881ccee8b5243333a6f8e3219c5002d9c2772267db2f438f66c7975c495896edaa66f7da8c2491ba5f67a6fe7c77c0bf16c8fc05ebc47e14336e76f3d450c
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
@@ -17,3 +17,5 @@ profile
17
17
  .rake_tasks~
18
18
  *.log.lck
19
19
  solr/
20
+ bin/
21
+ *.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format documentation
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
@@ -0,0 +1,7 @@
1
+ appraise 'mongoid-7' do
2
+ gem 'mongoid', '~> 7.0'
3
+ end
4
+
5
+ appraise 'mongoid-8' do
6
+ gem 'mongoid', '~> 8.0'
7
+ end
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 mongoid_delorean.gemspec
3
+ # Specify your gem's dependencies in mongoid-embedded-errors.gemspec
4
4
  gemspec
5
5
 
6
- gem "rspec"
7
- gem 'database_cleaner'
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
+ [![Code Climate](https://codeclimate.com/github/glooko/mongoid-embedded-errors/badges/gpa.svg)](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.error.messages
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.error.messages
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
- ## Contributers
106
+ ## Contributors
106
107
 
107
- * Mark Bates
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
- require 'bundler'
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+
2
6
  Bundler::GemHelper.install_tasks
3
7
 
4
- desc "Run tests"
5
- task :default => [:test]
8
+ desc 'Run tests'
9
+ task default: [:test]
6
10
 
7
- task :spec => [:test]
11
+ desc 'Run tests'
12
+ task spec: [:test]
8
13
 
9
- task :test do
10
- system "bundle exec rspec"
11
- end
14
+ desc 'Run tests'
15
+ task(:test) { system 'bundle exec rspec' }
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_RETRY: "1"
@@ -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,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid; end
4
+ module Mongoid::EmbeddedErrors
5
+ VERSION = '4.0.0'
6
+ 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
- require 'mongoid'
2
- require "mongoid-embedded-errors/version"
3
- require "mongoid-embedded-errors/embedded_in"
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
- # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
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-embedded-errors/version'
5
+ require 'mongoid/embedded_errors/version'
5
6
 
6
7
  Gem::Specification.new do |gem|
7
- gem.name = "mongoid-embedded-errors"
8
- gem.version = Mongoid::EmbeddedErrors::VERSION
9
- gem.authors = ["Mark Bates"]
10
- gem.email = ["mark@markbates.com"]
11
- gem.description = %q{Easily bubble up errors from embedded documents in Mongoid.}
12
- gem.summary = %q{Easily bubble up errors from embedded documents in Mongoid.}
13
- gem.homepage = ""
14
-
15
- gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
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 = ["lib"]
27
+ gem.require_paths = ['lib']
19
28
 
20
- gem.add_dependency("mongoid", ">=3.0.0")
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
- require 'bundler/setup'
2
-
3
- require 'mongoid-embedded-errors' # and any other gems you need
1
+ # frozen_string_literal: true
4
2
 
5
- require 'database_cleaner'
3
+ require 'bundler/setup'
4
+ require 'mongoid-embedded-errors'
5
+ require 'database_cleaner-mongoid'
6
6
 
7
- Mongoid.load!(File.join(File.dirname(__FILE__), "config.yml"), :test)
8
- require File.join(File.dirname(__FILE__), "support", "models")
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
- DatabaseCleaner[:mongoid].strategy = :truncation
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.before(:each) do
15
- DatabaseCleaner.clean
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
- end
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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Annotation
4
+ include Mongoid::Document
5
+
6
+ embedded_in :article, inverse_of: :annotation
7
+
8
+ field :text, type: String
9
+
10
+ validates :text, presence: true
11
+ 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 Page
4
+ include Mongoid::Document
5
+ include Mongoid::Timestamps
6
+
7
+ embedded_in :article, inverse_of: :pages
8
+ embeds_many :sections
9
+
10
+ field :title, type: String
11
+
12
+ validates :title, presence: true
13
+ 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
@@ -0,0 +1,13 @@
1
+ test:
2
+ # mongoid 4
3
+ sessions:
4
+ default:
5
+ database: mongoid_embedded_errors_test
6
+ hosts:
7
+ - localhost:27017
8
+ # mongoid 5 and newer
9
+ clients:
10
+ default:
11
+ database: mongoid_embedded_errors_test
12
+ hosts:
13
+ - localhost:27017
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: 2.0.1
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: 2013-07-18 00:00:00.000000000 Z
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: 3.0.0
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: 3.0.0
27
- description: Easily bubble up errors from embedded documents in Mongoid.
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
- - .gitignore
74
+ - ".codeclimate.yml"
75
+ - ".gitignore"
76
+ - ".rspec"
77
+ - ".rubocop.yml"
78
+ - ".semaphore/semaphore.yml"
79
+ - Appraisals
80
+ - CHANGELOG.md
35
81
  - Gemfile
36
- - Gemfile.lock
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-embedded-errors/embedded_in.rb
42
- - lib/mongoid-embedded-errors/version.rb
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/config.yml
45
- - spec/embedded_errors_spec.rb
97
+ - spec/lib/mongoid/embedded_errors_spec.rb
46
98
  - spec/spec_helper.rb
47
- - spec/support/models.rb
48
- homepage: ''
49
- licenses: []
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
- rubyforge_project:
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/config.yml
73
- - spec/embedded_errors_spec.rb
129
+ - spec/lib/mongoid/embedded_errors_spec.rb
74
130
  - spec/spec_helper.rb
75
- - spec/support/models.rb
76
- has_rdoc:
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
@@ -1,5 +0,0 @@
1
- module Mongoid
2
- module EmbeddedErrors
3
- VERSION = "2.0.1"
4
- end
5
- end
data/spec/config.yml DELETED
@@ -1,6 +0,0 @@
1
- test:
2
- sessions:
3
- default:
4
- database: mongoid_embedded_errors_test
5
- hosts:
6
- - localhost:27017
@@ -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
@@ -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