remarkable_activerecord 3.0.1 → 3.0.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.
Files changed (39) hide show
  1. data/CHANGELOG +46 -46
  2. data/LICENSE +1 -1
  3. data/README +64 -64
  4. data/lib/remarkable_activerecord.rb +1 -1
  5. data/lib/remarkable_activerecord/base.rb +40 -40
  6. data/lib/remarkable_activerecord/human_names.rb +24 -24
  7. data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +14 -14
  8. data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +70 -70
  9. data/lib/remarkable_activerecord/matchers/association_matcher.rb +197 -197
  10. data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +29 -29
  11. data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +20 -20
  12. data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +7 -7
  13. data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +34 -34
  14. data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +37 -37
  15. data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +75 -75
  16. data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +44 -44
  17. data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +17 -17
  18. data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +20 -20
  19. data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +14 -14
  20. data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +80 -61
  21. data/locale/en.yml +253 -253
  22. data/spec/allow_mass_assignment_of_matcher_spec.rb +50 -50
  23. data/spec/allow_values_for_matcher_spec.rb +45 -45
  24. data/spec/association_matcher_spec.rb +612 -612
  25. data/spec/have_column_matcher_spec.rb +67 -67
  26. data/spec/have_index_matcher_spec.rb +61 -61
  27. data/spec/have_readonly_attributes_matcher_spec.rb +40 -40
  28. data/spec/have_scope_matcher_spec.rb +60 -60
  29. data/spec/model_builder.rb +101 -101
  30. data/spec/spec_helper.rb +25 -25
  31. data/spec/validate_acceptance_of_matcher_spec.rb +64 -64
  32. data/spec/validate_associated_matcher_spec.rb +118 -118
  33. data/spec/validate_confirmation_of_matcher_spec.rb +54 -54
  34. data/spec/validate_exclusion_of_matcher_spec.rb +76 -76
  35. data/spec/validate_inclusion_of_matcher_spec.rb +72 -72
  36. data/spec/validate_numericality_of_matcher_spec.rb +100 -100
  37. data/spec/validate_presence_of_matcher_spec.rb +40 -40
  38. data/spec/validate_uniqueness_of_matcher_spec.rb +158 -139
  39. metadata +3 -3
@@ -1,101 +1,101 @@
1
- # This is based on Shoulda model builder for Test::Unit.
2
- #
3
- module ModelBuilder
4
- def self.included(base)
5
- return unless base.name =~ /^Spec/
6
-
7
- base.class_eval do
8
- after(:each) do
9
- if @defined_constants
10
- @defined_constants.each do |class_name|
11
- Object.send(:remove_const, class_name)
12
- end
13
- end
14
-
15
- if @created_tables
16
- @created_tables.each do |table_name|
17
- ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{table_name}")
18
- end
19
- end
20
- end
21
- end
22
-
23
- base.extend ClassMethods
24
- end
25
-
26
- def create_table(table_name, &block)
27
- connection = ActiveRecord::Base.connection
28
-
29
- begin
30
- connection.execute("DROP TABLE IF EXISTS #{table_name}")
31
- connection.create_table(table_name, &block)
32
- @created_tables ||= []
33
- @created_tables << table_name
34
- connection
35
- rescue Exception => e
36
- connection.execute("DROP TABLE IF EXISTS #{table_name}")
37
- raise e
38
- end
39
- end
40
-
41
- def define_constant(class_name, base, &block)
42
- class_name = class_name.to_s.camelize
43
-
44
- klass = Class.new(base)
45
- Object.const_set(class_name, klass)
46
-
47
- klass.class_eval(&block) if block_given?
48
-
49
- @defined_constants ||= []
50
- @defined_constants << class_name
51
-
52
- klass
53
- end
54
-
55
- def define_model_class(class_name, &block)
56
- define_constant(class_name, ActiveRecord::Base, &block)
57
- end
58
-
59
- def define_model(name, columns = {}, &block)
60
- class_name = name.to_s.pluralize.classify
61
- table_name = class_name.tableize
62
-
63
- table = columns.delete(:table) || lambda {|table|
64
- columns.each do |name, type|
65
- table.column name, type
66
- end
67
- }
68
-
69
- create_table(table_name, &table)
70
-
71
- klass = define_model_class(class_name, &block)
72
- instance = klass.new
73
-
74
- self.class.subject { instance } if self.class.respond_to?(:subject)
75
- instance
76
- end
77
-
78
- module ClassMethods
79
- # This is a macro to run validations of boolean optionals such as :allow_nil
80
- # and :allow_blank. This macro tests all scenarios. The specs must have a
81
- # define_and_validate method defined.
82
- #
83
- def create_optional_boolean_specs(optional, base, options={})
84
- base.describe "with #{optional} option" do
85
- it { should define_and_validate(options.merge(optional => true)).send(optional) }
86
- it { should define_and_validate(options.merge(optional => false)).send(optional, false) }
87
- it { should_not define_and_validate(options.merge(optional => true)).send(optional, false) }
88
- it { should_not define_and_validate(options.merge(optional => false)).send(optional) }
89
- end
90
- end
91
-
92
- def create_message_specs(base)
93
- base.describe "with message option" do
94
- it { should define_and_validate(:message => 'valid_message').message('valid_message') }
95
- it { should_not define_and_validate(:message => 'not_valid').message('valid_message') }
96
- end
97
- end
98
- end
99
-
100
- end
101
-
1
+ # This is based on Shoulda model builder for Test::Unit.
2
+ #
3
+ module ModelBuilder
4
+ def self.included(base)
5
+ return unless base.name =~ /^Spec/
6
+
7
+ base.class_eval do
8
+ after(:each) do
9
+ if @defined_constants
10
+ @defined_constants.each do |class_name|
11
+ Object.send(:remove_const, class_name)
12
+ end
13
+ end
14
+
15
+ if @created_tables
16
+ @created_tables.each do |table_name|
17
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{table_name}")
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ base.extend ClassMethods
24
+ end
25
+
26
+ def create_table(table_name, &block)
27
+ connection = ActiveRecord::Base.connection
28
+
29
+ begin
30
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
31
+ connection.create_table(table_name, &block)
32
+ @created_tables ||= []
33
+ @created_tables << table_name
34
+ connection
35
+ rescue Exception => e
36
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
37
+ raise e
38
+ end
39
+ end
40
+
41
+ def define_constant(class_name, base, &block)
42
+ class_name = class_name.to_s.camelize
43
+
44
+ klass = Class.new(base)
45
+ Object.const_set(class_name, klass)
46
+
47
+ klass.class_eval(&block) if block_given?
48
+
49
+ @defined_constants ||= []
50
+ @defined_constants << class_name
51
+
52
+ klass
53
+ end
54
+
55
+ def define_model_class(class_name, &block)
56
+ define_constant(class_name, ActiveRecord::Base, &block)
57
+ end
58
+
59
+ def define_model(name, columns = {}, &block)
60
+ class_name = name.to_s.pluralize.classify
61
+ table_name = class_name.tableize
62
+
63
+ table = columns.delete(:table) || lambda {|table|
64
+ columns.each do |name, type|
65
+ table.column name, *type
66
+ end
67
+ }
68
+
69
+ create_table(table_name, &table)
70
+
71
+ klass = define_model_class(class_name, &block)
72
+ instance = klass.new
73
+
74
+ self.class.subject { instance } if self.class.respond_to?(:subject)
75
+ instance
76
+ end
77
+
78
+ module ClassMethods
79
+ # This is a macro to run validations of boolean optionals such as :allow_nil
80
+ # and :allow_blank. This macro tests all scenarios. The specs must have a
81
+ # define_and_validate method defined.
82
+ #
83
+ def create_optional_boolean_specs(optional, base, options={})
84
+ base.describe "with #{optional} option" do
85
+ it { should define_and_validate(options.merge(optional => true)).send(optional) }
86
+ it { should define_and_validate(options.merge(optional => false)).send(optional, false) }
87
+ it { should_not define_and_validate(options.merge(optional => true)).send(optional, false) }
88
+ it { should_not define_and_validate(options.merge(optional => false)).send(optional) }
89
+ end
90
+ end
91
+
92
+ def create_message_specs(base)
93
+ base.describe "with message option" do
94
+ it { should define_and_validate(:message => 'valid_message').message('valid_message') }
95
+ it { should_not define_and_validate(:message => 'not_valid').message('valid_message') }
96
+ end
97
+ end
98
+ end
99
+
100
+ end
101
+
@@ -1,27 +1,27 @@
1
- require 'rubygems'
2
- require 'ruby-debug'
3
-
4
- RAILS_VERSION = ENV['RAILS_VERSION'] || '=2.2.2'
5
-
6
- gem 'activesupport', RAILS_VERSION
7
- require 'active_support'
8
-
9
- gem 'activerecord', RAILS_VERSION
10
- require 'active_record'
11
-
12
- # Configure ActiveRecord connection
1
+ require 'rubygems'
2
+ require 'ruby-debug'
3
+
4
+ RAILS_VERSION = ENV['RAILS_VERSION'] || '=2.2.2'
5
+
6
+ gem 'activesupport', RAILS_VERSION
7
+ require 'active_support'
8
+
9
+ gem 'activerecord', RAILS_VERSION
10
+ require 'active_record'
11
+
12
+ # Configure ActiveRecord connection
13
13
  ActiveRecord::Base.establish_connection(
14
- :adapter => 'sqlite3',
15
- :dbfile => 'memory'
16
- )
17
-
14
+ :adapter => 'sqlite3',
15
+ :dbfile => 'memory'
16
+ )
17
+
18
18
  # Load Remarkable core on place to avoid gem to be loaded
19
- dir = File.dirname(__FILE__)
20
- require File.join(dir, '..', '..', 'remarkable', 'lib', 'remarkable')
21
-
22
- # Load Remarkable ActiveRecord
23
- require File.join(dir, 'model_builder')
24
- require File.join(dir, '..', 'lib', 'remarkable_activerecord')
25
-
26
- # Include matchers
27
- Remarkable.include_matchers!(Remarkable::ActiveRecord, Spec::Example::ExampleGroup)
19
+ dir = File.dirname(__FILE__)
20
+ require File.join(dir, '..', '..', 'remarkable', 'lib', 'remarkable')
21
+
22
+ # Load Remarkable ActiveRecord
23
+ require File.join(dir, 'model_builder')
24
+ require File.join(dir, '..', 'lib', 'remarkable_activerecord')
25
+
26
+ # Include matchers
27
+ Remarkable.include_matchers!(Remarkable::ActiveRecord, Spec::Example::ExampleGroup)
@@ -1,68 +1,68 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe 'validate_acceptance_of' do
3
+ describe 'validate_acceptance_of' do
4
4
  include ModelBuilder
5
-
6
- # Defines a model, create a validation and returns a raw matcher
7
- def define_and_validate(options={})
8
- @model = define_model :user, :eula => :string, :terms => :string, :name => :string do
9
- validates_acceptance_of :eula, :terms, options
10
- end
11
-
12
- validate_acceptance_of(:eula, :terms)
13
- end
14
-
15
- describe 'messages' do
16
- before(:each){ @matcher = define_and_validate }
17
-
18
- it 'should contain a description' do
19
- @matcher.description.should == 'require eula and terms to be accepted'
20
-
21
- @matcher.accept('true')
22
- @matcher.description.should == 'require eula and terms to be accepted with value "true"'
23
-
24
- @matcher.allow_nil
25
- @matcher.description.should == 'require eula and terms to be accepted with value "true" and allowing nil values'
26
- end
27
-
28
- it 'should set requires_acceptance? message' do
29
- @matcher = validate_acceptance_of(:name)
30
- @matcher.matches?(@model)
31
- @matcher.failure_message.should == 'Expected User to be invalid if name is not accepted'
32
- end
33
-
34
- it 'should set accept_is_valid? message' do
35
- @matcher.accept('accept_value').matches?(@model)
36
- @matcher.failure_message.should == 'Expected User to be valid when eula is accepted with value "accept_value"'
37
- end
38
-
39
- end
40
-
41
- describe 'matchers' do
42
-
43
- describe 'without options' do
44
- before(:each){ define_and_validate }
45
-
46
- it { should validate_acceptance_of(:eula) }
47
- it { should validate_acceptance_of(:eula, :terms) }
48
- it { should_not validate_acceptance_of(:eula, :name) }
49
- end
50
-
51
- describe 'with accept as option' do
52
- it { should define_and_validate(:accept => 'accept_value').accept('accept_value') }
53
- it { should_not define_and_validate(:accept => 'another_value').accept('a_value') }
54
- end
55
-
56
- create_message_specs(self)
57
- create_optional_boolean_specs(:allow_nil, self)
58
- end
59
-
60
- describe 'macros' do
61
- before(:each){ define_and_validate }
62
-
63
- should_validate_acceptance_of :eula
64
- should_validate_acceptance_of :eula, :terms
65
- should_not_validate_acceptance_of :eula, :name
66
- end
67
-
5
+
6
+ # Defines a model, create a validation and returns a raw matcher
7
+ def define_and_validate(options={})
8
+ @model = define_model :user, :eula => :string, :terms => :string, :name => :string do
9
+ validates_acceptance_of :eula, :terms, options
10
+ end
11
+
12
+ validate_acceptance_of(:eula, :terms)
13
+ end
14
+
15
+ describe 'messages' do
16
+ before(:each){ @matcher = define_and_validate }
17
+
18
+ it 'should contain a description' do
19
+ @matcher.description.should == 'require eula and terms to be accepted'
20
+
21
+ @matcher.accept('true')
22
+ @matcher.description.should == 'require eula and terms to be accepted with value "true"'
23
+
24
+ @matcher.allow_nil
25
+ @matcher.description.should == 'require eula and terms to be accepted with value "true" and allowing nil values'
26
+ end
27
+
28
+ it 'should set requires_acceptance? message' do
29
+ @matcher = validate_acceptance_of(:name)
30
+ @matcher.matches?(@model)
31
+ @matcher.failure_message.should == 'Expected User to be invalid if name is not accepted'
32
+ end
33
+
34
+ it 'should set accept_is_valid? message' do
35
+ @matcher.accept('accept_value').matches?(@model)
36
+ @matcher.failure_message.should == 'Expected User to be valid when eula is accepted with value "accept_value"'
37
+ end
38
+
39
+ end
40
+
41
+ describe 'matchers' do
42
+
43
+ describe 'without options' do
44
+ before(:each){ define_and_validate }
45
+
46
+ it { should validate_acceptance_of(:eula) }
47
+ it { should validate_acceptance_of(:eula, :terms) }
48
+ it { should_not validate_acceptance_of(:eula, :name) }
49
+ end
50
+
51
+ describe 'with accept as option' do
52
+ it { should define_and_validate(:accept => 'accept_value').accept('accept_value') }
53
+ it { should_not define_and_validate(:accept => 'another_value').accept('a_value') }
54
+ end
55
+
56
+ create_message_specs(self)
57
+ create_optional_boolean_specs(:allow_nil, self)
58
+ end
59
+
60
+ describe 'macros' do
61
+ before(:each){ define_and_validate }
62
+
63
+ should_validate_acceptance_of :eula
64
+ should_validate_acceptance_of :eula, :terms
65
+ should_not_validate_acceptance_of :eula, :name
66
+ end
67
+
68
68
  end
@@ -1,122 +1,122 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe 'validate_associated' do
3
+ describe 'validate_associated' do
4
4
  include ModelBuilder
5
-
6
- # Defines a model, create a validation and returns a raw matcher
7
- def define_and_validate(macro, association, options={})
8
- define_model association, :name => :string do
9
- if options[:with_builder]
10
- validates_acceptance_of :name
11
- else
12
- validates_presence_of :name
13
- end
14
- end
15
-
16
- options[:message] ||= :invalid
17
-
18
- @model = define_model :project do
19
- send(macro, association, :validate => false) unless options[:skip_association]
20
- validates_associated association, options.slice(:message) unless options[:skip_validation]
21
- end
22
-
23
- validate_associated association
24
- end
25
-
26
- describe 'messages' do
27
- it 'should contain a description' do
28
- define_and_validate(:belongs_to, :company).description.should == 'require associated company to be valid'
29
- end
30
-
31
- it 'should set is_valid? message' do
32
- matcher = define_and_validate(:belongs_to, :company, :skip_validation => true)
33
- matcher.matches?(@model)
34
- matcher.failure_message.should == 'Expected Project to be invalid when company is invalid'
35
- end
36
- end
37
-
38
- describe 'error' do
39
- it 'should raise an error if the association does not exist' do
40
- lambda {
41
- should define_and_validate(:belongs_to, :company, :skip_association => true)
42
- }.should raise_error(ScriptError, 'Could not find association company on Project.')
43
- end
44
-
45
- it 'should raise an error if a singular association cannot be built' do
46
- lambda {
47
- matcher = define_and_validate(:belongs_to, :company)
48
- @model.should_receive(:build_company).and_raise(NoMethodError)
49
- should matcher
50
- }.should raise_error(ScriptError, 'The association object company could not be built. ' <<
51
- 'You can give me :builder as option or a block which ' <<
52
- 'returns an association.')
53
- end
54
-
55
- it 'should raise an error if a plural association cannot be built' do
56
- lambda {
57
- matcher = define_and_validate(:has_many, :tasks)
58
- @model.should_receive(:tasks).and_return(mock=mock('proxy'))
59
- mock.should_receive(:build).and_raise(NoMethodError)
60
- should matcher
61
- }.should raise_error(ScriptError, 'The association object tasks could not be built. ' <<
62
- 'You can give me :builder as option or a block which ' <<
63
- 'returns an association.')
64
- end
65
-
66
- it 'should raise an error if the associated object cannot be saved as invalid' do
67
- lambda {
68
- should define_and_validate(:belongs_to, :company, :with_builder => true)
69
- }.should raise_error(ScriptError, 'The associated object company is not invalid. ' <<
70
- 'You can give me :builder as option or a block which ' <<
71
- 'returns an invalid association.')
72
- end
73
-
74
- it 'should raise an error if the associated object cannot be saved even when a build is supplied' do
75
- lambda {
76
- should define_and_validate(:belongs_to, :company, :with_builder => true).builder(proc{ |p| p.build_company })
77
- }.should raise_error(ScriptError, 'The associated object company is not invalid. ' <<
78
- 'You can give me :builder as option or a block which ' <<
79
- 'returns an invalid association.')
80
- end
81
- end
82
-
83
- describe 'matchers' do
84
- it { should define_and_validate(:belongs_to, :company) }
85
- it { should define_and_validate(:has_one, :manager) }
86
- it { should define_and_validate(:has_many, :tasks) }
87
- it { should define_and_validate(:has_and_belongs_to_many, :tags) }
88
-
89
- it { should define_and_validate(:belongs_to, :company, :with_builder => true).builder(proc{|p| p.build_company(:name => true)}) }
90
- it { should define_and_validate(:has_one, :manager, :with_builder => true).builder(proc{|p| p.build_manager(:name => true)}) }
91
- it { should define_and_validate(:has_many, :tasks, :with_builder => true).builder(proc{|p| p.tasks.build(:name => true)}) }
92
- it { should define_and_validate(:has_and_belongs_to_many, :tags, :with_builder => true).builder(proc{|p| p.tags.build(:name => true)}) }
93
-
94
- it { should_not define_and_validate(:belongs_to, :company, :skip_validation => true) }
95
- it { should_not define_and_validate(:has_one, :manager, :skip_validation => true) }
96
- it { should_not define_and_validate(:has_many, :tasks, :skip_validation => true) }
97
- it { should_not define_and_validate(:has_and_belongs_to_many, :tags, :skip_validation => true) }
98
-
99
- describe "with message option" do
100
- it { should define_and_validate(:belongs_to, :company, :message => 'valid_message').message('valid_message') }
101
- it { should_not define_and_validate(:belongs_to, :company, :message => 'not_valid').message('valid_message') }
102
- end
103
- end
104
-
105
- describe 'macros' do
106
- describe 'belongs to' do
107
- before(:each){ define_and_validate(:belongs_to, :company) }
108
- should_validate_associated(:company)
109
- end
110
-
111
- describe 'has_many with builder' do
112
- before(:each){ define_and_validate(:has_many, :tasks, :with_builder => true) }
113
- should_validate_associated(:tasks){ |p| p.tasks.build(:name => true) }
114
- end
115
-
116
- describe 'has_and_belongs_to_many with skip validation' do
117
- before(:each){ define_and_validate(:has_and_belongs_to_many, :tags, :skip_validation => true) }
118
- should_not_validate_associated(:tags)
119
- end
120
- end
121
-
5
+
6
+ # Defines a model, create a validation and returns a raw matcher
7
+ def define_and_validate(macro, association, options={})
8
+ define_model association, :name => :string do
9
+ if options[:with_builder]
10
+ validates_acceptance_of :name
11
+ else
12
+ validates_presence_of :name
13
+ end
14
+ end
15
+
16
+ options[:message] ||= :invalid
17
+
18
+ @model = define_model :project do
19
+ send(macro, association, :validate => false) unless options[:skip_association]
20
+ validates_associated association, options.slice(:message) unless options[:skip_validation]
21
+ end
22
+
23
+ validate_associated association
24
+ end
25
+
26
+ describe 'messages' do
27
+ it 'should contain a description' do
28
+ define_and_validate(:belongs_to, :company).description.should == 'require associated company to be valid'
29
+ end
30
+
31
+ it 'should set is_valid? message' do
32
+ matcher = define_and_validate(:belongs_to, :company, :skip_validation => true)
33
+ matcher.matches?(@model)
34
+ matcher.failure_message.should == 'Expected Project to be invalid when company is invalid'
35
+ end
36
+ end
37
+
38
+ describe 'error' do
39
+ it 'should raise an error if the association does not exist' do
40
+ lambda {
41
+ should define_and_validate(:belongs_to, :company, :skip_association => true)
42
+ }.should raise_error(ScriptError, 'Could not find association company on Project.')
43
+ end
44
+
45
+ it 'should raise an error if a singular association cannot be built' do
46
+ lambda {
47
+ matcher = define_and_validate(:belongs_to, :company)
48
+ @model.should_receive(:build_company).and_raise(NoMethodError)
49
+ should matcher
50
+ }.should raise_error(ScriptError, 'The association object company could not be built. ' <<
51
+ 'You can give me :builder as option or a block which ' <<
52
+ 'returns an association.')
53
+ end
54
+
55
+ it 'should raise an error if a plural association cannot be built' do
56
+ lambda {
57
+ matcher = define_and_validate(:has_many, :tasks)
58
+ @model.should_receive(:tasks).and_return(mock=mock('proxy'))
59
+ mock.should_receive(:build).and_raise(NoMethodError)
60
+ should matcher
61
+ }.should raise_error(ScriptError, 'The association object tasks could not be built. ' <<
62
+ 'You can give me :builder as option or a block which ' <<
63
+ 'returns an association.')
64
+ end
65
+
66
+ it 'should raise an error if the associated object cannot be saved as invalid' do
67
+ lambda {
68
+ should define_and_validate(:belongs_to, :company, :with_builder => true)
69
+ }.should raise_error(ScriptError, 'The associated object company is not invalid. ' <<
70
+ 'You can give me :builder as option or a block which ' <<
71
+ 'returns an invalid association.')
72
+ end
73
+
74
+ it 'should raise an error if the associated object cannot be saved even when a build is supplied' do
75
+ lambda {
76
+ should define_and_validate(:belongs_to, :company, :with_builder => true).builder(proc{ |p| p.build_company })
77
+ }.should raise_error(ScriptError, 'The associated object company is not invalid. ' <<
78
+ 'You can give me :builder as option or a block which ' <<
79
+ 'returns an invalid association.')
80
+ end
81
+ end
82
+
83
+ describe 'matchers' do
84
+ it { should define_and_validate(:belongs_to, :company) }
85
+ it { should define_and_validate(:has_one, :manager) }
86
+ it { should define_and_validate(:has_many, :tasks) }
87
+ it { should define_and_validate(:has_and_belongs_to_many, :tags) }
88
+
89
+ it { should define_and_validate(:belongs_to, :company, :with_builder => true).builder(proc{|p| p.build_company(:name => true)}) }
90
+ it { should define_and_validate(:has_one, :manager, :with_builder => true).builder(proc{|p| p.build_manager(:name => true)}) }
91
+ it { should define_and_validate(:has_many, :tasks, :with_builder => true).builder(proc{|p| p.tasks.build(:name => true)}) }
92
+ it { should define_and_validate(:has_and_belongs_to_many, :tags, :with_builder => true).builder(proc{|p| p.tags.build(:name => true)}) }
93
+
94
+ it { should_not define_and_validate(:belongs_to, :company, :skip_validation => true) }
95
+ it { should_not define_and_validate(:has_one, :manager, :skip_validation => true) }
96
+ it { should_not define_and_validate(:has_many, :tasks, :skip_validation => true) }
97
+ it { should_not define_and_validate(:has_and_belongs_to_many, :tags, :skip_validation => true) }
98
+
99
+ describe "with message option" do
100
+ it { should define_and_validate(:belongs_to, :company, :message => 'valid_message').message('valid_message') }
101
+ it { should_not define_and_validate(:belongs_to, :company, :message => 'not_valid').message('valid_message') }
102
+ end
103
+ end
104
+
105
+ describe 'macros' do
106
+ describe 'belongs to' do
107
+ before(:each){ define_and_validate(:belongs_to, :company) }
108
+ should_validate_associated(:company)
109
+ end
110
+
111
+ describe 'has_many with builder' do
112
+ before(:each){ define_and_validate(:has_many, :tasks, :with_builder => true) }
113
+ should_validate_associated(:tasks){ |p| p.tasks.build(:name => true) }
114
+ end
115
+
116
+ describe 'has_and_belongs_to_many with skip validation' do
117
+ before(:each){ define_and_validate(:has_and_belongs_to_many, :tags, :skip_validation => true) }
118
+ should_not_validate_associated(:tags)
119
+ end
120
+ end
121
+
122
122
  end