mongoid-embedded-errors 1.0.1 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 129c9a68d1921837c6cd5942d64272049bbc8fd8f756c29b0a825faa4c1d1527
4
+ data.tar.gz: 57c35bcc8813866051d60d5139e5901169b8478ce4d5be291e862e0bb0604e17
5
+ SHA512:
6
+ metadata.gz: 857c87ef479cc4eb0ea15462f9c6386d2eff11987d0a0f895bc3429f14ffd9242fcbce2292bb7de04f2588481fa76bbdc1d0d9874bd2b6a4bcffc02b5149f22a
7
+ data.tar.gz: 3935c4a3d82f9e343b21f2272c05d4e8cf642191d79be7b89e82116220c76ba73b56b1e24885824e5fe6c9f17312a4f083cf2714a8356cb2768c0f1b4b57b488
@@ -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
@@ -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
+
@@ -0,0 +1,15 @@
1
+ appraise 'mongoid-4' do
2
+ gem 'mongoid', '~> 4.0'
3
+ end
4
+
5
+ appraise 'mongoid-5' do
6
+ gem 'mongoid', '~> 5.0'
7
+ end
8
+
9
+ appraise 'mongoid-6' do
10
+ gem 'mongoid', '~> 6.0'
11
+ end
12
+
13
+ appraise 'mongoid-7' do
14
+ gem 'mongoid', '~> 7.0'
15
+ end
@@ -0,0 +1,27 @@
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
+ ## [v3.0.1] - 2020-09-29
10
+ ### Added
11
+ - Started 🔎 tracking changes in a changelog!
12
+ - Mongoid 7 support
13
+ - Ruby 2.4 support by using `send` instead of `public_send` [#18]
14
+
15
+ ### Removed
16
+ - Mongoid 3 support
17
+
18
+ ### Fixed
19
+ - Updated style to fix Rubocop issues (as per included .rubocop.yml configuration file)
20
+ - Removed .lock files as these are not supposed to be included with gem source code
21
+
22
+ ## [v3.0.0] - 2020-09-29 [YANKED]
23
+ - Yanked due to wrong dependencies in gemspec.
24
+
25
+ [Unreleased]: https://github.com/glooko/mongoid-embedded-errors/compare/v3.0.1...HEAD
26
+ [v3.0.1]: https://github.com/glooko/mongoid-embedded-errors/compare/v3.0.0...v3.0.1
27
+ [v3.0.0]: https://github.com/glooko/mongoid-embedded-errors/compare/f1ce0d8ed140de86c894b2fad7ad197504fefd5a...v3.0.0
data/Gemfile CHANGED
@@ -1,7 +1,13 @@
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 'appraisal'
8
+ gem 'database_cleaner'
9
+ gem 'guard-rspec'
10
+ gem 'mutant-rspec'
11
+ gem 'rake'
12
+ gem 'rspec'
13
+ end
@@ -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,8 +84,13 @@ end
83
84
  article = Article.new(pages: [Page.new(sections: [Section.new])])
84
85
  article.valid? # => false
85
86
 
86
- article.error.messages
87
- # => {:name=>["can't be blank"], :summary=>["can't be blank"], :pages=>[{"5086ec0d421aa94f0f000002"=>{:title=>["can't be blank"], :sections=>[{"5086ec0d421aa94f0f000001"=>{:header=>["can't be blank"]}}]}}]}
87
+ article.errors.messages
88
+ {
89
+ :name => ["can't be blank"],
90
+ :summary => ["can't be blank"],
91
+ :"pages[0].title" => ["can't be blank"],
92
+ :"pages[0].sections[0].header" => ["can't be blank"]
93
+ }
88
94
  ```
89
95
 
90
96
  Now, isn't that much nicer? Yeah, I think so to.
@@ -96,3 +102,7 @@ Now, isn't that much nicer? Yeah, I think so to.
96
102
  3. Commit your changes (`git commit -am 'Add some feature'`)
97
103
  4. Push to the branch (`git push origin my-new-feature`)
98
104
  5. Create new Pull Request
105
+
106
+ ## Contributors
107
+
108
+ [See here](https://github.com/glooko/mongoid-embedded-errors/graphs/contributors)
data/Rakefile CHANGED
@@ -1,9 +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 => [:ruby]
8
+ desc 'Run tests'
9
+ task default: [:test]
10
+
11
+ desc 'Run tests'
12
+ task spec: [:test]
6
13
 
7
- task :ruby do
8
- system "bundle exec rspec"
9
- 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,16 @@
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 "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: "../"
@@ -1,29 +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
- if errs[name]
19
- errs.delete(name.to_sym)
20
- self.send(name).each do |rel|
21
- errs[name] = {rel.id.to_s => rel.errors.messages} if rel.errors.any?
22
- end
23
- end
24
- end
25
- return errs
26
- end
27
-
28
- end
29
- end
1
+ # rubocop:disable Naming/FileName
2
+ require 'mongoid/embedded_errors'
3
+ # rubocop:enable Naming/FileName
@@ -0,0 +1,49 @@
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 unless 'is invalid' error for the relation
23
+ errs[name].delete 'is 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 |k, v|
32
+ relation = if Gem::Version.new(Mongoid::VERSION) >= Gem::Version.new('7.0.0')
33
+ metadata.class
34
+ else
35
+ metadata.relation
36
+ end
37
+ key = if relation.equal? EMBEDS_MANY
38
+ "#{name}[#{i}].#{k}"
39
+ else
40
+ "#{name}.#{k}"
41
+ end.to_sym
42
+ errs.delete(key)
43
+ errs.add key, v if v.present?
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -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 = '3.0.1'
6
+ end
@@ -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', '>=4.0', '<8.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
@@ -1,18 +1,45 @@
1
- require 'bundler/setup'
2
-
3
- require 'mongoid-embedded-errors' # and any other gems you need
1
+ # frozen_string_literal: true
4
2
 
3
+ require 'bundler/setup'
4
+ require 'mongoid-embedded-errors'
5
5
  require 'database_cleaner'
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
17
+
18
+ config.expect_with :rspec do |expectations|
19
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
20
+ expectations.syntax = :expect
21
+ end
13
22
 
14
- config.before(:each) do
15
- DatabaseCleaner.clean
23
+ config.mock_with :rspec do |mocks|
24
+ mocks.verify_partial_doubles = true
16
25
  end
26
+ config.disable_monkey_patching!
17
27
 
18
- end
28
+ config.before(:suite) do
29
+ DatabaseCleaner.strategy = :truncation
30
+ end
31
+
32
+ config.around do |example|
33
+ DatabaseCleaner.cleaning { example.run }
34
+ end
35
+
36
+ config.before do
37
+ # Need to manually reload spec models for mutant to work as expected
38
+ if ENV['MUTANT']
39
+ Dir[SPEC_MODELS_PATH].each do |filename|
40
+ Object.send(:remove_const, File.basename(filename, '.rb').capitalize)
41
+ load filename
42
+ end
43
+ end
44
+ end
45
+ 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,79 +1,133 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-embedded-errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
5
- prerelease:
4
+ version: 3.0.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Mark Bates
9
- autorequire:
8
+ - Kristijan Novoselić
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-29 00:00:00.000000000 Z
12
+ date: 2020-09-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongoid
16
16
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
17
  requirements:
19
- - - ! '>='
18
+ - - ">="
20
19
  - !ruby/object:Gem::Version
21
- version: 3.0.0
20
+ version: '4.0'
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: 8.0.0
22
24
  type: :runtime
23
25
  prerelease: false
24
26
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
27
  requirements:
27
- - - ! '>='
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: '4.0'
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: 8.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
+ - - "~>"
28
60
  - !ruby/object:Gem::Version
29
- version: 3.0.0
30
- 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.
31
67
  email:
32
68
  - mark@markbates.com
69
+ - kristijan@glooko.com
33
70
  executables: []
34
71
  extensions: []
35
72
  extra_rdoc_files: []
36
73
  files:
37
- - .gitignore
74
+ - ".codeclimate.yml"
75
+ - ".gitignore"
76
+ - ".rspec"
77
+ - ".rubocop.yml"
78
+ - ".semaphore/semaphore.yml"
79
+ - Appraisals
80
+ - CHANGELOG.md
38
81
  - Gemfile
39
- - Gemfile.lock
82
+ - Guardfile
40
83
  - LICENSE.txt
41
84
  - README.md
42
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
43
91
  - lib/mongoid-embedded-errors.rb
44
- - lib/mongoid-embedded-errors/embedded_in.rb
45
- - lib/mongoid-embedded-errors/version.rb
92
+ - lib/mongoid/embedded_errors.rb
93
+ - lib/mongoid/embedded_errors/embedded_in.rb
94
+ - lib/mongoid/embedded_errors/version.rb
46
95
  - mongoid-embedded-errors.gemspec
47
- - spec/config.yml
48
- - spec/embedded_errors_spec.rb
96
+ - spec/lib/mongoid/embedded_errors_spec.rb
49
97
  - spec/spec_helper.rb
50
- - spec/support/models.rb
51
- homepage: ''
52
- licenses: []
53
- post_install_message:
98
+ - spec/support/models/annotation.rb
99
+ - spec/support/models/article.rb
100
+ - spec/support/models/page.rb
101
+ - spec/support/models/section.rb
102
+ - spec/support/mongoid.yml
103
+ homepage: https://github.com/glooko/mongoid-embedded-errors
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
54
108
  rdoc_options: []
55
109
  require_paths:
56
110
  - lib
57
111
  required_ruby_version: !ruby/object:Gem::Requirement
58
- none: false
59
112
  requirements:
60
- - - ! '>='
113
+ - - ">="
61
114
  - !ruby/object:Gem::Version
62
115
  version: '0'
63
116
  required_rubygems_version: !ruby/object:Gem::Requirement
64
- none: false
65
117
  requirements:
66
- - - ! '>='
118
+ - - ">="
67
119
  - !ruby/object:Gem::Version
68
120
  version: '0'
69
121
  requirements: []
70
- rubyforge_project:
71
- rubygems_version: 1.8.24
72
- signing_key:
73
- specification_version: 3
122
+ rubygems_version: 3.1.4
123
+ signing_key:
124
+ specification_version: 4
74
125
  summary: Easily bubble up errors from embedded documents in Mongoid.
75
126
  test_files:
76
- - spec/config.yml
77
- - spec/embedded_errors_spec.rb
127
+ - spec/lib/mongoid/embedded_errors_spec.rb
78
128
  - spec/spec_helper.rb
79
- - spec/support/models.rb
129
+ - spec/support/models/annotation.rb
130
+ - spec/support/models/article.rb
131
+ - spec/support/models/page.rb
132
+ - spec/support/models/section.rb
133
+ - spec/support/mongoid.yml
@@ -1,44 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- mongoid-embedded-errors (1.0.1)
5
- mongoid (>= 3.0.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (3.2.9)
11
- activesupport (= 3.2.9)
12
- builder (~> 3.0.0)
13
- activesupport (3.2.9)
14
- i18n (~> 0.6)
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.0.9)
21
- activemodel (~> 3.1)
22
- moped (~> 1.1)
23
- origin (~> 1.0)
24
- tzinfo (~> 0.3.22)
25
- moped (1.2.7)
26
- multi_json (1.3.7)
27
- origin (1.0.9)
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.35)
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 = "1.0.1"
4
- end
5
- end
@@ -1,6 +0,0 @@
1
- test:
2
- sessions:
3
- default:
4
- database: mongoid_embedded_errors_test
5
- hosts:
6
- - localhost:27017
@@ -1,46 +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
-
10
- describe "errors" do
11
-
12
- it "bubbles up errors from embedded documents" do
13
- invalid_page.sections << invalid_section
14
- article.pages << invalid_page
15
- article.should_not be_valid
16
- puts article.errors.messages
17
- article.errors.messages.should eql({
18
- name: ["can't be blank"],
19
- summary: ["can't be blank"],
20
- pages: [{
21
- invalid_page.id.to_s => {
22
- title: ["can't be blank"],
23
- sections: [{
24
- invalid_section.id.to_s => {
25
- header: ["can't be blank"]
26
- }
27
- }]
28
- }
29
- }]
30
- })
31
- end
32
-
33
- it "save works as before" do
34
- article.save.should be_false
35
- article.should_not be_persisted
36
- article.errors.messages.should eql(name: ["can't be blank"], summary: ["can't be blank"])
37
- end
38
-
39
- it "handles errors on the main object" do
40
- article.should_not be_valid
41
- article.errors.messages.should eql(name: ["can't be blank"], summary: ["can't be blank"])
42
- end
43
-
44
- end
45
-
46
- end
@@ -1,37 +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
- end
14
-
15
- class Page
16
- include Mongoid::Document
17
- include Mongoid::Timestamps
18
-
19
- field :title, type: String
20
-
21
- validates :title, presence: true
22
-
23
- embedded_in :article, inverse_of: :pages
24
- embeds_many :sections
25
- end
26
-
27
- class Section
28
- include Mongoid::Document
29
- include Mongoid::Timestamps
30
-
31
- field :header, type: String
32
- field :body, type: String
33
-
34
- validates :header, presence: true
35
-
36
- embedded_in :page, inverse_of: :sections
37
- end