mongoid-rspec 2.1.0 → 4.1.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.
Files changed (66) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +222 -102
  4. data/Rakefile +8 -5
  5. data/lib/matchers/accept_nested_attributes.rb +22 -23
  6. data/lib/matchers/allow_mass_assignment.rb +12 -12
  7. data/lib/matchers/associations.rb +85 -49
  8. data/lib/matchers/be_dynamic_document.rb +26 -0
  9. data/lib/matchers/be_mongoid_document.rb +26 -0
  10. data/lib/matchers/be_stored_in.rb +55 -0
  11. data/lib/matchers/have_field.rb +90 -0
  12. data/lib/matchers/have_timestamps.rb +61 -0
  13. data/lib/matchers/indexes/have_index_for.rb +16 -0
  14. data/lib/matchers/indexes/v3/have_index_for.rb +59 -0
  15. data/lib/matchers/indexes/v4/have_index_for.rb +54 -0
  16. data/lib/matchers/validations.rb +30 -11
  17. data/lib/matchers/validations/absence_of.rb +11 -0
  18. data/lib/matchers/validations/associated.rb +1 -1
  19. data/lib/matchers/validations/confirmation_of.rb +7 -1
  20. data/lib/matchers/validations/custom_validation_of.rb +1 -4
  21. data/lib/matchers/validations/exclusion_of.rb +5 -5
  22. data/lib/matchers/validations/format_of.rb +2 -2
  23. data/lib/matchers/validations/inclusion_of.rb +5 -5
  24. data/lib/matchers/validations/length_of.rb +13 -35
  25. data/lib/matchers/validations/numericality_of.rb +32 -16
  26. data/lib/matchers/validations/presence_of.rb +1 -1
  27. data/lib/matchers/validations/uniqueness_of.rb +7 -10
  28. data/lib/mongoid-rspec.rb +1 -33
  29. data/lib/mongoid/rspec.rb +46 -0
  30. data/lib/mongoid/rspec/version.rb +5 -0
  31. data/spec/models/article.rb +9 -6
  32. data/spec/models/comment.rb +1 -1
  33. data/spec/models/log.rb +3 -3
  34. data/spec/models/message.rb +17 -0
  35. data/spec/models/movie_article.rb +1 -2
  36. data/spec/models/person.rb +1 -1
  37. data/spec/models/profile.rb +2 -2
  38. data/spec/models/record.rb +1 -1
  39. data/spec/models/site.rb +5 -1
  40. data/spec/models/user.rb +12 -10
  41. data/spec/spec_helper.rb +12 -10
  42. data/spec/unit/accept_nested_attributes_spec.rb +1 -1
  43. data/spec/unit/associations_spec.rb +19 -7
  44. data/spec/unit/be_dynamic_document_spec.rb +21 -0
  45. data/spec/unit/be_mongoid_document_spec.rb +25 -0
  46. data/spec/unit/be_stored_in.rb +54 -0
  47. data/spec/unit/document_spec.rb +5 -14
  48. data/spec/unit/have_index_for_spec.rb +46 -0
  49. data/spec/unit/have_timestamps_spec.rb +71 -0
  50. data/spec/unit/validations_spec.rb +23 -14
  51. data/spec/validators/ssn_validator.rb +6 -6
  52. metadata +119 -43
  53. data/.document +0 -5
  54. data/.gitignore +0 -6
  55. data/.ruby-gemset +0 -1
  56. data/.ruby-version +0 -1
  57. data/.travis.yml +0 -10
  58. data/Gemfile +0 -4
  59. data/lib/matchers/collections.rb +0 -9
  60. data/lib/matchers/document.rb +0 -173
  61. data/lib/matchers/indexes.rb +0 -69
  62. data/lib/matchers/validations/with_message.rb +0 -27
  63. data/lib/mongoid-rspec/version.rb +0 -5
  64. data/mongoid-rspec.gemspec +0 -25
  65. data/spec/unit/collections_spec.rb +0 -7
  66. data/spec/unit/indexes_spec.rb +0 -17
@@ -2,8 +2,19 @@ module Mongoid
2
2
  module Matchers
3
3
  module Validations
4
4
  class ValidateNumericalityOfMatcher < HaveValidationMatcher
5
- @@allowed_options = [:equal_to, :greater_than, :greater_than_or_equal_to, :less_than, :less_than_or_equal_to,
6
- :even, :odd, :only_integer, :allow_nil, :nil]
5
+ ALLOWED_OPTIONS =
6
+ %i[
7
+ allow_nil
8
+ equal_to
9
+ even
10
+ greater_than
11
+ greater_than_or_equal_to
12
+ less_than
13
+ less_than_or_equal_to
14
+ nil
15
+ odd
16
+ only_integer
17
+ ].freeze
7
18
 
8
19
  def initialize(field)
9
20
  super(field, :numericality)
@@ -12,9 +23,15 @@ module Mongoid
12
23
 
13
24
  def to_allow(options)
14
25
  options[:equal_to] = options if options.is_a?(Numeric)
15
- options[:allow_nil] = options.delete(:nil) if options.has_key?(:nil)
16
- raise ArgumentError, "validate_numericality_of#to_allow requires a Hash parameter containing any of the following keys: " <<
17
- @@allowed_options.map(&:inspect).join(", ") if !options.is_a?(Hash) or options.empty? or (options.keys - @@allowed_options).any?
26
+ options[:allow_nil] = options.delete(:nil) if options.key?(:nil)
27
+
28
+ if !options.is_a?(Hash) || options.empty? || (options.keys - ALLOWED_OPTIONS).any?
29
+ message =
30
+ 'validate_numericality_of#to_allow requires a Hash parameter containing' \
31
+ "any of the following keys: #{ALLOWED_OPTIONS.map(&:inspect).join(', ')}"
32
+ raise ArgumentError, message
33
+ end
34
+
18
35
  @options.merge!(options)
19
36
  self
20
37
  end
@@ -22,11 +39,10 @@ module Mongoid
22
39
  def matches?(actual)
23
40
  return false unless result = super(actual)
24
41
 
25
- @@allowed_options.each do |comparator|
26
- if @options.has_key?(comparator) and !([:even, :odd, :only_integer].include?(comparator) and !@validator.options.include?(comparator))
27
- result &= (@validator.options[comparator] == @options[comparator])
28
- end
42
+ @options.each do |comparator, expected_value|
43
+ result &= (@validator.options[comparator] == expected_value)
29
44
  end
45
+
30
46
  @positive_result_message <<= options_message(@validator.options)
31
47
  @negative_result_message <<= options_message(@validator.options)
32
48
  result
@@ -45,19 +61,19 @@ module Mongoid
45
61
  case key
46
62
  when :allow_nil
47
63
  when :only_integer
48
- type_msg << "integer" if value
64
+ type_msg << 'integer' if value
49
65
  when :odd, :even
50
- type_msg << "#{key.to_s}-numbered" if value
66
+ type_msg << "#{key}-numbered" if value
51
67
  else
52
- comp_msg << "#{key.to_s.gsub("_", " ")} #{value.inspect}"
68
+ comp_msg << "#{key.to_s.tr('_', ' ')} #{value.inspect}"
53
69
  end
54
70
  end
55
- allow_nil = (options[:allow_nil] ? "nil" : "non-nil") if options.has_key?(:allow_nil)
56
- ["", "allowing", allow_nil, type_msg.any? ? type_msg.to_sentence : nil, "values", comp_msg.any? ? comp_msg.to_sentence : nil].compact.join(" ")
71
+ allow_nil = (options[:allow_nil] ? 'nil' : 'non-nil') if options.key?(:allow_nil)
72
+ ['', 'allowing', allow_nil, type_msg.any? ? type_msg.to_sentence : nil, 'values', comp_msg.any? ? comp_msg.to_sentence : nil].compact.join(' ')
57
73
  end
58
74
 
59
75
  def method_missing(m, *args, &block)
60
- if @@allowed_options.include?(m.to_sym)
76
+ if ALLOWED_OPTIONS.include?(m.to_sym)
61
77
  raise ArgumentError, "wrong number of arguments (#{args.length} for 1)" if args.length > 1
62
78
  send :to_allow, m.to_sym => args.first
63
79
  else
@@ -71,4 +87,4 @@ module Mongoid
71
87
  end
72
88
  end
73
89
  end
74
- end
90
+ end
@@ -6,4 +6,4 @@ module Mongoid
6
6
  end
7
7
  end
8
8
  end
9
- end
9
+ end
@@ -2,7 +2,6 @@ module Mongoid
2
2
  module Matchers
3
3
  module Validations
4
4
  class ValidateUniquenessOfMatcher < HaveValidationMatcher
5
- include WithMessage
6
5
  def initialize(field)
7
6
  super(field, :uniqueness)
8
7
  end
@@ -11,7 +10,7 @@ module Mongoid
11
10
  @scope = [scope].flatten.map(&:to_sym)
12
11
  self
13
12
  end
14
- alias_method :scoped_on, :scoped_to
13
+ alias scoped_on scoped_to
15
14
 
16
15
  def case_insensitive
17
16
  @case_insensitive = true
@@ -29,7 +28,6 @@ module Mongoid
29
28
  check_scope if @scope
30
29
  check_allow_blank if @allow_blank
31
30
  check_case_sensitivity if @case_insensitive
32
- check_expected_message if @expected_message
33
31
 
34
32
  @result
35
33
  end
@@ -37,9 +35,8 @@ module Mongoid
37
35
  def description
38
36
  options_desc = []
39
37
  options_desc << " scoped to #{@scope.inspect}" if @scope
40
- options_desc << " allowing blank values" if @allow_blank
41
- options_desc << " allowing case insensitive values" if @case_insensitive
42
- options_desc << " with message '#{@expected_message}'" if @expected_message
38
+ options_desc << ' allowing blank values' if @allow_blank
39
+ options_desc << ' allowing case insensitive values' if @case_insensitive
43
40
  super << options_desc.to_sentence
44
41
  end
45
42
 
@@ -47,9 +44,9 @@ module Mongoid
47
44
 
48
45
  def check_allow_blank
49
46
  if @validator.options[:allow_blank] == @allow_blank
50
- @positive_result_message << " with blank values allowed"
47
+ @positive_result_message << ' with blank values allowed'
51
48
  else
52
- @negative_result_message << " with no blank values allowed"
49
+ @negative_result_message << ' with no blank values allowed'
53
50
  @result = false
54
51
  end
55
52
  end
@@ -66,9 +63,9 @@ module Mongoid
66
63
 
67
64
  def check_case_sensitivity
68
65
  if @validator.options[:case_sensitive] == false
69
- @positive_result_message << " with case insensitive values"
66
+ @positive_result_message << ' with case insensitive values'
70
67
  else
71
- @negative_result_message << " without case insensitive values"
68
+ @negative_result_message << ' without case insensitive values'
72
69
  @result = false
73
70
  end
74
71
  end
@@ -1,33 +1 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
-
3
- require 'mongoid'
4
- require 'rspec/core'
5
- require 'rspec/expectations'
6
- require 'rspec/mocks'
7
- require "active_model"
8
- require 'matchers/document'
9
- require 'matchers/associations'
10
- require 'matchers/collections'
11
- require 'matchers/indexes'
12
- require 'matchers/allow_mass_assignment'
13
- require 'matchers/accept_nested_attributes'
14
- require 'matchers/validations'
15
- require 'matchers/validations/with_message'
16
- require 'matchers/validations/associated'
17
- require 'matchers/validations/confirmation_of'
18
- require 'matchers/validations/exclusion_of'
19
- require 'matchers/validations/format_of'
20
- require 'matchers/validations/inclusion_of'
21
- require 'matchers/validations/length_of'
22
- require 'matchers/validations/numericality_of'
23
- require 'matchers/validations/presence_of'
24
- require 'matchers/validations/uniqueness_of'
25
- require 'matchers/validations/acceptance_of'
26
- require 'matchers/validations/custom_validation_of'
27
-
28
- module Mongoid
29
- module Matchers
30
- include Mongoid::Matchers::Associations
31
- include Mongoid::Matchers::Validations
32
- end
33
- end
1
+ require 'mongoid/rspec'
@@ -0,0 +1,46 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+
3
+ require 'mongoid'
4
+ require 'mongoid-compatibility'
5
+ require 'rspec/core'
6
+ require 'rspec/expectations'
7
+ require 'rspec/mocks'
8
+ require 'active_support/core_ext/hash/keys'
9
+ require 'active_support/core_ext/hash/transform_values' if Mongoid::Compatibility::Version.mongoid4_or_newer? && ActiveSupport.version < Gem::Version.new('6')
10
+ require 'active_support/core_ext/object/blank'
11
+ require 'active_support/core_ext/string/inflections'
12
+
13
+ require 'matchers/associations'
14
+ require 'matchers/allow_mass_assignment'
15
+ require 'matchers/accept_nested_attributes'
16
+ require 'matchers/validations'
17
+ require 'matchers/validations/associated'
18
+ require 'matchers/validations/confirmation_of'
19
+ require 'matchers/validations/exclusion_of'
20
+ require 'matchers/validations/format_of'
21
+ require 'matchers/validations/inclusion_of'
22
+ require 'matchers/validations/length_of'
23
+ require 'matchers/validations/numericality_of'
24
+ require 'matchers/validations/presence_of'
25
+ require 'matchers/validations/uniqueness_of'
26
+ require 'matchers/validations/acceptance_of'
27
+ require 'matchers/validations/custom_validation_of'
28
+ require 'matchers/validations/absence_of'
29
+ require 'matchers/be_mongoid_document'
30
+ require 'matchers/be_dynamic_document'
31
+ require 'matchers/be_stored_in'
32
+ require 'matchers/have_field'
33
+ require 'matchers/indexes/have_index_for'
34
+ if Mongoid::Compatibility::Version.mongoid3?
35
+ require 'matchers/indexes/v3/have_index_for'
36
+ else
37
+ require 'matchers/indexes/v4/have_index_for'
38
+ end
39
+ require 'matchers/have_timestamps'
40
+
41
+ module Mongoid
42
+ module Matchers
43
+ include Mongoid::Matchers::Associations
44
+ include Mongoid::Matchers::Validations
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ module Mongoid
2
+ module RSpec
3
+ VERSION = '4.1.0'.freeze
4
+ end
5
+ end
@@ -8,22 +8,25 @@ class Article
8
8
  field :allow_comments, type: Boolean, default: true
9
9
  field :number_of_comments, type: Integer
10
10
  field :status, type: Symbol
11
+ field :deletion_date, type: DateTime, default: nil
11
12
 
12
- embeds_many :comments, cascade_callbacks: true
13
- embeds_one :permalink
13
+ embeds_many :comments, cascade_callbacks: true, inverse_of: :article
14
+ embeds_one :permalink, inverse_of: :linkable
14
15
  belongs_to :author, class_name: 'User', inverse_of: :articles, index: true
15
16
 
16
17
  validates :title, presence: true
17
18
 
18
19
  validates_inclusion_of :status, in: [:pending], on: :create
19
- validates_inclusion_of :status, in: [:approved, :rejected ], on: :update
20
+ validates_inclusion_of :status, in: %i[approved rejected], on: :update
20
21
 
21
22
  validates_length_of :title, within: 8..16
22
23
  validates_length_of :content, minimum: 200
23
24
 
24
- index({ title: 1 }, { unique: true, background: true, drop_dups: true })
25
- index({ published: 1 })
26
- index({ 'permalink._id' => 1 })
25
+ validates_absence_of :deletion_date if Mongoid::Compatibility::Version.mongoid4_or_newer?
26
+
27
+ index({ title: 1 }, unique: true, background: true, drop_dups: true)
28
+ index(published: 1)
29
+ index('permalink._id' => 1)
27
30
 
28
31
  accepts_nested_attributes_for :permalink
29
32
  end
@@ -3,4 +3,4 @@ class Comment
3
3
 
4
4
  embedded_in :article, inverse_of: :comments, polymorphic: true
5
5
  belongs_to :user, inverse_of: :comments
6
- end
6
+ end
@@ -1,9 +1,9 @@
1
1
  class Log
2
2
  include Mongoid::Document
3
3
  include Mongoid::Timestamps
4
- include Mongoid::Attributes::Dynamic
4
+ include Mongoid::Attributes::Dynamic if Mongoid::Compatibility::Version.mongoid4_or_newer?
5
5
 
6
- store_in collection: "logs"
6
+ store_in collection: 'logs'
7
7
 
8
- index({ created_at: 1 }, { bucket_size: 100, expire_after_seconds: 3600 } )
8
+ index({ created_at: 1 }, bucket_size: 100, expire_after_seconds: 3600)
9
9
  end
@@ -0,0 +1,17 @@
1
+ class Message
2
+ include Mongoid::Document
3
+
4
+ field :identifier
5
+ field :from
6
+ field :to
7
+
8
+ if Mongoid::Compatibility::Version.mongoid6_or_newer?
9
+ belongs_to :user, optional: true
10
+ else
11
+ belongs_to :user
12
+ end
13
+
14
+ validates :identifier, uniqueness: { message: 'uniqueness' }
15
+ validates :from, presence: { message: 'required' }
16
+ validates :to, format: { with: /[a-z]+/, message: 'format' }
17
+ end
@@ -1,8 +1,7 @@
1
1
  class MovieArticle < Article
2
-
3
2
  field :rating, type: Float
4
3
  field :classification, type: Integer
5
4
 
6
5
  validates :rating, numericality: { greater_than: 0, less_than_or_equal_to: 5 }
7
6
  validates :classification, numericality: { even: true, only_integer: true, allow_nil: false }
8
- end
7
+ end
@@ -7,4 +7,4 @@ class Person
7
7
  field :ssn
8
8
 
9
9
  validates :ssn, ssn: true
10
- end
10
+ end
@@ -10,7 +10,7 @@ class Profile
10
10
 
11
11
  validates :age, numericality: { greater_than: 0 }
12
12
  validates :terms_of_service, acceptance: true
13
- validates :hobbies, length: { minimum: 1, message: "requires at least one hobby" }
13
+ validates :hobbies, length: { minimum: 1, message: 'requires at least one hobby' }
14
14
 
15
- index({ first_name: 1, last_name: 1 })
15
+ index(first_name: 1, last_name: 1)
16
16
  end
@@ -2,4 +2,4 @@ class Record
2
2
  include Mongoid::Document
3
3
 
4
4
  belongs_to :user, inverse_of: :record
5
- end
5
+ end
@@ -3,7 +3,11 @@ class Site
3
3
 
4
4
  field :name
5
5
 
6
- has_many :users, inverse_of: :site, order: :email.desc, counter_cache: true
6
+ if Mongoid::Compatibility::Version.mongoid6_or_older?
7
+ has_many :users, inverse_of: :site, order: :email.desc, counter_cache: true
8
+ else
9
+ has_many :users, inverse_of: :site, order: :email.desc
10
+ end
7
11
 
8
12
  validates :name, presence: true, uniqueness: true
9
13
  end
@@ -13,20 +13,22 @@ class User
13
13
  belongs_to :site, inverse_of: :users
14
14
  has_many :articles, foreign_key: :author_id, order: :title
15
15
  has_many :comments, dependent: :destroy, autosave: true
16
- has_and_belongs_to_many :children, class_name: "User"
17
- has_one :record, autobuild: true
16
+ has_many :messages, dependent: :destroy
17
+ has_and_belongs_to_many :children, class_name: 'User'
18
+ has_one :record, autobuild: true, inverse_of: :user
18
19
 
19
- embeds_one :profile
20
+ embeds_one :profile, inverse_of: :user
20
21
 
21
- validates :login, presence: true, uniqueness: { scope: :site }, format: { with: /\A[\w\-]+\z/ }, exclusion: { in: ["super", "index", "edit"] }
22
- validates :email, uniqueness: { case_sensitive: false, scope: :site, message: "is already taken" }, confirmation: true
23
- validates :role, presence: true, inclusion: { in: ["admin", "moderator", "member"] }
22
+ validates :login, presence: true, uniqueness: { scope: :site }, format: { with: /\A[\w\-]+\z/ }, exclusion: { in: %w[super index edit] }
23
+ validates :email, uniqueness: { case_sensitive: false, scope: :site, message: 'is already taken' }, confirmation: true
24
+ validates :role, presence: true, inclusion: { in: %w[admin moderator member] }
24
25
  validates :profile, presence: true, associated: true
25
- validates :age, presence: true, numericality: true, inclusion: { in: 23..42 }, on: [:create, :update]
26
- validates :password, presence: true, on: [:create, :update]
27
- validates :password, exclusion: { in: ->(user) { ['password'] } }
26
+ validates :age, presence: true, numericality: true, inclusion: { in: 23..42 }, on: %i[create update]
27
+ validates :password, presence: true, on: %i[create update]
28
+ validates :password, exclusion: { in: ->(_user) { ['password'] } }
29
+ validates :password, confirmation: { message: 'Password confirmation must match given password' }
28
30
  validates :provider_uid, presence: true
29
- validates :locale, inclusion: { in: ->(user) { [:en, :ru] } }
31
+ validates :locale, inclusion: { in: ->(_user) { %i[en ru] } }
30
32
 
31
33
  accepts_nested_attributes_for :articles, :comments
32
34
 
@@ -1,24 +1,23 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
3
- MODELS = File.join(File.dirname(__FILE__), "models")
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
3
+ MODELS = File.join(File.dirname(__FILE__), 'models')
4
4
  $LOAD_PATH.unshift(MODELS)
5
- VALIDATORS = File.join(File.dirname(__FILE__), "validators")
5
+ VALIDATORS = File.join(File.dirname(__FILE__), 'validators')
6
6
  $LOAD_PATH.unshift(VALIDATORS)
7
7
 
8
- require "rubygems"
9
- require "bundler"
8
+ require 'rubygems'
9
+ require 'bundler'
10
10
  Bundler.setup
11
11
 
12
12
  require 'mongoid'
13
- require 'rspec'
14
13
  require 'rspec/core'
15
14
  require 'rspec/expectations'
15
+ require 'mongoid/compatibility'
16
16
 
17
- Mongoid.configure do |config|
18
- config.connect_to("mongoid-rspec-test")
19
- end
17
+ Mongoid::Config.connect_to('mongoid-rspec-test') if Mongoid::Compatibility::Version.mongoid3_or_newer?
18
+ Mongo::Logger.logger.level = ::Logger::INFO if Mongoid::Compatibility::Version.mongoid5_or_newer?
20
19
 
21
- Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
20
+ Dir[File.join(MODELS, '*.rb')].sort.each { |file| require File.basename(file) }
22
21
 
23
22
  require 'mongoid-rspec'
24
23
 
@@ -29,5 +28,8 @@ RSpec.configure do |config|
29
28
  config.after :all do
30
29
  Mongoid::Config.purge!
31
30
  end
31
+ config.after :suite do
32
+ print "\n# Mongoid v#{Mongoid::VERSION}"
33
+ end
32
34
  config.disable_monkey_patching!
33
35
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe "AcceptsNestedAttributes" do
3
+ RSpec.describe 'AcceptsNestedAttributes' do
4
4
  describe User do
5
5
  it { is_expected.to accept_nested_attributes_for(:articles) }
6
6
  it { is_expected.to accept_nested_attributes_for(:comments) }