remarkable_mongo 0.1.2

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.
@@ -0,0 +1,37 @@
1
+ if defined?(Spec)
2
+ module Spec #:nodoc:
3
+ module Example #:nodoc:
4
+ module ExampleGroupMethods #:nodoc:
5
+
6
+ # This allows "describe User" to use the I18n human name of User.
7
+ #
8
+ def self.build_description_with_i18n(*args)
9
+ args.inject("") do |description, arg|
10
+ arg = if arg.respond_to?(:human_name)
11
+ arg.human_name(:locale => Remarkable.locale)
12
+ else
13
+ arg.to_s
14
+ end
15
+
16
+ description << " " unless (description == "" || arg =~ /^(\s|\.|#)/)
17
+ description << arg
18
+ end
19
+ end
20
+
21
+ # This is for rspec <= 1.1.12.
22
+ #
23
+ def self.description_text(*args)
24
+ self.build_description_with_i18n(*args)
25
+ end
26
+
27
+ # This is for rspec >= 1.2.0.
28
+ #
29
+ def self.build_description_from(*args)
30
+ text = ExampleGroupMethods.build_description_with_i18n(*args)
31
+ text == "" ? nil : text
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,86 @@
1
+ module Remarkable
2
+ module MongoMapper
3
+ module Matchers
4
+ class AllowValuesForMatcher < Remarkable::MongoMapper::Base #:nodoc:
5
+ include Remarkable::Negative
6
+ arguments :collection => :attributes, :as => :attribute
7
+
8
+ optional :message
9
+ optional :in, :splat => true
10
+ optional :allow_nil, :allow_blank, :default => true
11
+
12
+ collection_assertions :is_valid?, :is_invalid?, :allow_nil?, :allow_blank?
13
+
14
+ default_options :message => "is invalid"
15
+
16
+ before_assert do
17
+ first_value = @options[:in].is_a?(Array) ? @options[:in].first : @options[:in]
18
+ @in_range = first_value.is_a?(Range)
19
+
20
+ @options[:in] = if @in_range
21
+ first_value.to_a[0,2] + first_value.to_a[-2,2]
22
+ else
23
+ [*@options[:in]].compact
24
+ end
25
+
26
+ @options[:in].uniq!
27
+ end
28
+
29
+ protected
30
+
31
+ def is_valid?
32
+ assert_collection :value, valid_values do |value|
33
+ good?(value)
34
+ end
35
+ end
36
+
37
+ def is_invalid?
38
+ assert_collection :value, invalid_values do |value|
39
+ bad?(value)
40
+ end
41
+ end
42
+
43
+ def valid_values
44
+ @options[:in]
45
+ end
46
+
47
+ def invalid_values
48
+ []
49
+ end
50
+
51
+ def interpolation_options
52
+ options = if @in_range
53
+ { :in => (@options[:in].first..@options[:in].last).inspect }
54
+ elsif @options[:in].is_a?(Array)
55
+ { :in => array_to_sentence(@options[:in], true, '[]') }
56
+ else
57
+ { :in => @options[:in].inspect }
58
+ end
59
+
60
+ options.merge!(:behavior => @behavior.to_s)
61
+ end
62
+
63
+ end
64
+
65
+ # Ensures that the attribute can be set to the given values.
66
+ #
67
+ # == Options
68
+ #
69
+ # * <tt>:allow_nil</tt> - when supplied, validates if it allows nil or not.
70
+ # * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
71
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
72
+ # Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.invalid')</tt>
73
+ #
74
+ # == Examples
75
+ #
76
+ # should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
77
+ # it { should allow_values_for(:isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0") }
78
+ #
79
+ def allow_values_for(attribute, *args, &block)
80
+ options = args.extract_options!
81
+ AllowValuesForMatcher.new(attribute, options.merge!(:in => args), &block).spec(self)
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,105 @@
1
+ module Remarkable
2
+ module MongoMapper
3
+ module Matchers
4
+ class AssociationMatcher < Remarkable::MongoMapper::Base
5
+ arguments :type, :collection => :associations, :as => :association
6
+
7
+ optionals :class_name
8
+
9
+ collection_assertions :association_exists?, :type_matches?, :klass_exists?, :options_match?
10
+
11
+ protected
12
+
13
+ def association_exists?
14
+ reflection
15
+ end
16
+
17
+ def type_matches?
18
+ reflection.type == @type
19
+ end
20
+
21
+ def klass_exists?
22
+ return true if @options[:polymorphic]
23
+ reflection.klass rescue nil
24
+ end
25
+
26
+ def options_match?
27
+ actual_options = {}
28
+
29
+ @options.keys.each do |key|
30
+ method = :"reflection_#{key}"
31
+
32
+ @options[key] = @options[key].to_s
33
+ actual_options[key] = (respond_to?(method, true) ? send(method) : reflection.options[key]).to_s
34
+ end
35
+
36
+ return @options == actual_options, :actual => actual_options.inspect
37
+ end
38
+
39
+ private
40
+
41
+ def reflection
42
+ @reflection ||= subject_class.associations[@association]
43
+ end
44
+
45
+ def interpolation_options
46
+ options = {}
47
+ options[:type] = Remarkable.t(@type, :scope => matcher_i18n_scope, :default => @type.to_s.gsub("_", ""))
48
+ options[:options] = @options.inspect
49
+
50
+ if @subject && reflection
51
+ options.merge!(
52
+ :actual_type => Remarkable.t(reflection.type, :scope => matcher_i18n_scope, :default => reflection.type.to_s)
53
+ )
54
+ end
55
+
56
+ options
57
+ end
58
+
59
+ end
60
+
61
+ # Ensures that the many relationship exists. Will also test that the
62
+ # associated table has the required columns.
63
+ #
64
+ # == Options
65
+ #
66
+ # * <tt>:class_name</tt> - the expected associted class name.
67
+ # * <tt>:polymorphic</tt> - if the association should be polymorphic or not.
68
+ # When true it also checks for the association_type column in the subject table.
69
+ #
70
+ # == Examples
71
+ #
72
+ # should_have_many :addresses
73
+ # should_have_many :users, :class_name => 'Person'
74
+ #
75
+ # it { should have_many(:addresses) }
76
+ # it { should have_many(:users, :class_name => 'Person') }
77
+ #
78
+ def have_many(*associations, &block)
79
+ AssociationMatcher.new(:many, *associations, &block).spec(self)
80
+ end
81
+
82
+ # Ensures that the many relationship exists. Will also test that the
83
+ # associated table has the required columns.
84
+ #
85
+ # == Options
86
+ #
87
+ # * <tt>:class_name</tt> - the expected associted class name.
88
+ # * <tt>:polymorphic</tt> - if the association should be polymorphic or not.
89
+ # When true it also checks for the association_type column in the subject table.
90
+ #
91
+ # == Examples
92
+ #
93
+ # should_belong_to :user
94
+ # should_belong_to :user, :class_name => 'Person'
95
+ #
96
+ # it { should belong_to(:user) }
97
+ # it { should belong_to(:user, :class_name => 'Person') }
98
+ #
99
+ def belong_to(*associations, &block)
100
+ AssociationMatcher.new(:belongs_to, *associations, &block).spec(self)
101
+ end
102
+
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,38 @@
1
+ module Remarkable
2
+ module MongoMapper
3
+ module Matchers
4
+ class HaveKeyMatcher < Remarkable::MongoMapper::Base
5
+
6
+ arguments :type, :collection => :attributes, :as => :attribute
7
+
8
+ collection_assertions :has_key?
9
+
10
+ # before_assert do
11
+ # @type = @options[:type]
12
+ # end
13
+
14
+ protected
15
+
16
+ def has_key?
17
+ @subject.respond_to?(@attribute) && @subject.class.keys[@attribute] == ::MongoMapper::Key.new(@attribute, @type)
18
+ end
19
+
20
+ end
21
+
22
+ # Ensures that a key of the database actually exists.
23
+ #
24
+ # == Examples
25
+ #
26
+ # should_have_key :name, String
27
+ #
28
+ # it { should have_key(:name, String) }
29
+ # it { should have_keys(:name, :phone_number, String) }
30
+ #
31
+ def have_key(*args, &block)
32
+ HaveKeyMatcher.new(args.pop, *args, &block).spec(self)
33
+ end
34
+ alias :have_keys :have_key
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,44 @@
1
+ module Remarkable
2
+ module MongoMapper
3
+ module Matchers
4
+ class ValidateConfirmationOfMatcher < Remarkable::MongoMapper::Base #:nodoc:
5
+ arguments :collection => :attributes, :as => :attribute
6
+
7
+ optional :message
8
+ collection_assertions :responds_to_confirmation?, :confirms?
9
+
10
+ default_options :message => "doesn't match confirmation"
11
+
12
+ protected
13
+
14
+ def responds_to_confirmation?
15
+ @subject.respond_to?(:"#{@attribute}_confirmation=")
16
+ end
17
+
18
+ def confirms?
19
+ @subject.send(:"#{@attribute}_confirmation=", 'something')
20
+ bad?('different')
21
+ end
22
+
23
+ end
24
+
25
+ # Ensures that the model cannot be saved if one of the attributes is not confirmed.
26
+ #
27
+ # == Options
28
+ #
29
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
30
+ # Regexp, string or symbol. Default = "doesn't match confirmation"
31
+ #
32
+ # == Examples
33
+ #
34
+ # should_validate_confirmation_of :email, :password
35
+ #
36
+ # it { should validate_confirmation_of(:email, :password) }
37
+ #
38
+ def validate_confirmation_of(*attributes, &block)
39
+ ValidateConfirmationOfMatcher.new(*attributes, &block).spec(self)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,106 @@
1
+ module Remarkable
2
+ module MongoMapper
3
+ module Matchers
4
+ class ValidateLengthOfMatcher < Remarkable::MongoMapper::Base #:nodoc:
5
+ arguments :collection => :attributes, :as => :attribute
6
+
7
+ optional :within, :minimum, :maximum, :is
8
+ optional :allow_nil, :allow_blank, :default => true
9
+ optional :message
10
+
11
+ default_options :message => "is invalid"
12
+
13
+ collection_assertions :less_than_min_length?, :exactly_min_length?,
14
+ :more_than_max_length?, :exactly_max_length?,
15
+ :allow_nil?, :allow_blank?
16
+
17
+ before_assert do
18
+ if @options[:is]
19
+ @min_value, @max_value = @options[:is], @options[:is]
20
+ elsif @options[:within]
21
+ @min_value, @max_value = @options[:within].first, @options[:within].last
22
+ elsif @options[:maximum]
23
+ @min_value, @max_value = nil, @options[:maximum]
24
+ elsif @options[:minimum]
25
+ @min_value, @max_value = @options[:minimum], nil
26
+ end
27
+ end
28
+
29
+ protected
30
+ def allow_nil?
31
+ super(default_message_for(:too_short))
32
+ end
33
+
34
+ def allow_blank?
35
+ super(default_message_for(:too_short))
36
+ end
37
+
38
+ def less_than_min_length?
39
+ @min_value.nil? || @min_value <= 1 || bad?(@min_value - 1, default_message_for(:too_short))
40
+ end
41
+
42
+ def exactly_min_length?
43
+ @min_value.nil? || @min_value <= 0 || good?(@min_value, default_message_for(:too_short))
44
+ end
45
+
46
+ def more_than_max_length?
47
+ @max_value.nil? || bad?(@max_value + 1, default_message_for(:too_long))
48
+ end
49
+
50
+ def exactly_max_length?
51
+ @max_value.nil? || @min_value == @max_value || good?(@max_value, default_message_for(:too_long))
52
+ end
53
+
54
+ def interpolation_options
55
+ { :minimum => @min_value, :maximum => @max_value }
56
+ end
57
+
58
+ # Returns the default message for the validation type.
59
+ # If user supplied :message, it will return it. Otherwise it will return
60
+ # wrong_length on :is validation and :too_short or :too_long in the other
61
+ # types.
62
+ #
63
+ def default_message_for(validation_type)
64
+ return :message if @options[:message]
65
+ end
66
+ end
67
+
68
+ # Validates the length of the given attributes. You have also to supply
69
+ # one of the following options: minimum, maximum, is or within.
70
+ #
71
+ # Note: this method is also aliased as <tt>validate_size_of</tt>.
72
+ #
73
+ # == Options
74
+ #
75
+ # * <tt>:minimum</tt> - The minimum size of the attribute.
76
+ # * <tt>:maximum</tt> - The maximum size of the attribute.
77
+ # * <tt>:is</tt> - The exact size of the attribute.
78
+ # * <tt>:within</tt> - A range specifying the minimum and maximum size of the attribute.
79
+ # * <tt>:allow_nil</tt> - when supplied, validates if it allows nil or not.
80
+ # * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
81
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
82
+ # Regexp, string or symbol. Default = "is invalid"</tt>
83
+ #
84
+ # == Examples
85
+ #
86
+ # it { should validate_length_of(:password).within(6..20) }
87
+ # it { should validate_length_of(:password).maximum(20) }
88
+ # it { should validate_length_of(:password).minimum(6) }
89
+ # it { should validate_length_of(:age).is(18) }
90
+ #
91
+ # should_validate_length_of :password, :within => 6..20
92
+ # should_validate_length_of :password, :maximum => 20
93
+ # should_validate_length_of :password, :minimum => 6
94
+ # should_validate_length_of :age, :is => 18
95
+ #
96
+ # should_validate_length_of :password do |m|
97
+ # m.minimum 6
98
+ # m.maximum 20
99
+ # end
100
+ #
101
+ def validate_length_of(*attributes, &block)
102
+ ValidateLengthOfMatcher.new(*attributes, &block).spec(self)
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,37 @@
1
+ module Remarkable
2
+ module MongoMapper
3
+ module Matchers
4
+ class ValidatePresenceOfMatcher < Remarkable::MongoMapper::Base
5
+ arguments :collection => :attributes, :as => :attribute
6
+ optional :message
7
+
8
+ collection_assertions :allow_nil?
9
+ default_options :message => "can't be empty"
10
+
11
+ protected
12
+
13
+ def allow_nil?
14
+ bad?(nil, :message)
15
+ end
16
+
17
+ end
18
+
19
+ # Ensures that the model cannot be saved if one of the attributes listed is not present.
20
+ #
21
+ # == Options
22
+ #
23
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
24
+ # Regexp, string or symbol. Default = "can't be empty"
25
+ #
26
+ # == Examples
27
+ #
28
+ # should_validate_presence_of :name, :phone_number
29
+ # it { should validate_presence_of(:name, :phone_number) }
30
+ #
31
+ def validate_presence_of(*args, &block)
32
+ ValidatePresenceOfMatcher.new(*args, &block).spec(self)
33
+ end
34
+
35
+ end
36
+ end
37
+ end