mongoid-embedded-errors 2.0.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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