mongoid-rspec 2.1.0 → 4.1.0

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