carlosbrando-remarkable 0.0.99 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/History.txt +5 -5
  2. data/Manifest.txt +53 -35
  3. data/PostInstall.txt +1 -6
  4. data/README.rdoc +109 -15
  5. data/Rakefile +29 -29
  6. data/lib/remarkable/active_record/README.markdown +378 -0
  7. data/lib/remarkable/active_record/active_record.rb +12 -11
  8. data/lib/remarkable/active_record/helpers.rb +215 -5
  9. data/lib/remarkable/active_record/macros/associations/association_matcher.rb +242 -0
  10. data/lib/remarkable/active_record/macros/callbacks/callback_matcher.rb +46 -0
  11. data/lib/remarkable/active_record/macros/database/column_matcher.rb +122 -0
  12. data/lib/remarkable/active_record/macros/database/index_matcher.rb +103 -0
  13. data/lib/remarkable/active_record/macros/validations/allow_mass_assignment_of_matcher.rb +52 -0
  14. data/lib/remarkable/active_record/macros/validations/ensure_value_in_list_matcher.rb +83 -0
  15. data/lib/remarkable/active_record/macros/validations/ensure_value_in_range_matcher.rb +172 -0
  16. data/lib/remarkable/active_record/macros/validations/have_class_methods_matcher.rb +54 -0
  17. data/lib/remarkable/active_record/macros/validations/have_instance_methods_matcher.rb +54 -0
  18. data/lib/remarkable/active_record/macros/validations/have_named_scope_matcher.rb +94 -0
  19. data/lib/remarkable/active_record/macros/validations/have_readonly_attributes_matcher.rb +48 -0
  20. data/lib/remarkable/active_record/macros/validations/protect_attributes_matcher.rb +51 -0
  21. data/lib/remarkable/active_record/macros/validations/validate_acceptance_of_matcher.rb +79 -0
  22. data/lib/remarkable/active_record/macros/validations/validate_associated_matcher.rb +177 -0
  23. data/lib/remarkable/active_record/macros/validations/validate_confirmation_of_matcher.rb +74 -0
  24. data/lib/remarkable/active_record/macros/validations/validate_exclusion_of_matcher.rb +38 -0
  25. data/lib/remarkable/active_record/macros/validations/validate_format_of_matcher.rb +33 -0
  26. data/lib/remarkable/active_record/macros/validations/validate_inclusion_of_matcher.rb +45 -0
  27. data/lib/remarkable/active_record/macros/validations/validate_length_of_matcher.rb +248 -0
  28. data/lib/remarkable/active_record/macros/validations/validate_numericality_of_matcher.rb +206 -0
  29. data/lib/remarkable/active_record/macros/validations/validate_presence_of_matcher.rb +72 -0
  30. data/lib/remarkable/active_record/macros/validations/validate_uniqueness_of_matcher.rb +222 -0
  31. data/lib/remarkable/active_record/macros.rb +52 -0
  32. data/lib/remarkable/assertions.rb +29 -0
  33. data/lib/remarkable/controller/README.markdown +147 -0
  34. data/lib/remarkable/controller/controller.rb +11 -6
  35. data/lib/remarkable/controller/helpers.rb +4 -38
  36. data/lib/remarkable/controller/macros/assign_matcher.rb +85 -0
  37. data/lib/remarkable/controller/macros/filter_params_matcher.rb +63 -0
  38. data/lib/remarkable/controller/macros/metadata_matcher.rb +63 -0
  39. data/lib/remarkable/controller/macros/render_with_layout_matcher.rb +75 -0
  40. data/lib/remarkable/controller/macros/respond_with_content_type_matcher.rb +60 -0
  41. data/lib/remarkable/controller/macros/respond_with_matcher.rb +62 -0
  42. data/lib/remarkable/controller/macros/return_from_session_matcher.rb +58 -0
  43. data/lib/remarkable/controller/macros/route_matcher.rb +75 -0
  44. data/lib/remarkable/controller/macros/set_the_flash_to_matcher.rb +60 -0
  45. data/lib/remarkable/controller/macros.rb +78 -0
  46. data/lib/remarkable/dsl.rb +239 -0
  47. data/lib/remarkable/example/example_methods.rb +27 -7
  48. data/lib/remarkable/helpers.rb +28 -0
  49. data/lib/remarkable/matcher_base.rb +64 -0
  50. data/lib/remarkable/private_helpers.rb +10 -115
  51. data/lib/remarkable/rails.rb +27 -0
  52. data/lib/remarkable.rb +13 -5
  53. data/remarkable.gemspec +43 -0
  54. data/spec/controllers/posts_controller_spec.rb +58 -4
  55. data/spec/controllers/users_controller_spec.rb +1 -0
  56. data/spec/fixtures/fleas.yml +10 -0
  57. data/spec/fixtures/users.yml +7 -0
  58. data/spec/models/address_spec.rb +44 -0
  59. data/spec/models/dog_spec.rb +64 -3
  60. data/spec/models/flea_spec.rb +30 -0
  61. data/spec/models/post_spec.rb +36 -2
  62. data/spec/models/product_spec.rb +73 -8
  63. data/spec/models/tag_spec.rb +2 -2
  64. data/spec/models/tagging_spec.rb +24 -0
  65. data/spec/models/user_spec.rb +206 -21
  66. data/spec/other/custom_macros_spec.rb +27 -0
  67. data/spec/other/my_own_matcher_spec.rb +11 -0
  68. data/spec/other/private_helpers_spec.rb +31 -0
  69. data/spec/rails_root/app/controllers/posts_controller.rb +2 -0
  70. data/spec/rails_root/app/models/address.rb +2 -2
  71. data/spec/rails_root/app/models/flea.rb +4 -0
  72. data/spec/rails_root/app/models/pets/dog.rb +12 -0
  73. data/spec/rails_root/app/models/product.rb +7 -5
  74. data/spec/rails_root/app/models/tagging.rb +2 -0
  75. data/spec/rails_root/app/models/user.rb +20 -5
  76. data/spec/rails_root/app/views/layouts/posts.rhtml +8 -6
  77. data/spec/rails_root/config/database.yml +1 -2
  78. data/spec/rails_root/config/environment.rb +3 -1
  79. data/spec/rails_root/config/environments/{sqlite3.rb → test.rb} +0 -0
  80. data/spec/rails_root/config/locales/en.yml +8 -0
  81. data/spec/rails_root/db/migrate/001_create_users.rb +2 -2
  82. data/spec/rails_root/db/migrate/005_create_dogs.rb +1 -0
  83. data/spec/rails_root/db/migrate/011_add_fleas_color.rb +10 -0
  84. data/spec/rails_root/db/migrate/012_add_fleas_address.rb +10 -0
  85. data/spec/rails_root/spec/remarkable_macros/.keep +0 -0
  86. data/spec/rails_root/vendor/plugins/my_plugin/remarkable_macros/.keep +0 -0
  87. data/spec/spec_helper.rb +0 -2
  88. metadata +63 -43
  89. data/lib/remarkable/active_record/macros/associations/belong_to.rb +0 -81
  90. data/lib/remarkable/active_record/macros/associations/have_and_belong_to_many.rb +0 -77
  91. data/lib/remarkable/active_record/macros/associations/have_many.rb +0 -160
  92. data/lib/remarkable/active_record/macros/associations/have_one.rb +0 -133
  93. data/lib/remarkable/active_record/macros/database/have_db_column.rb +0 -81
  94. data/lib/remarkable/active_record/macros/database/have_db_columns.rb +0 -73
  95. data/lib/remarkable/active_record/macros/database/have_indices.rb +0 -75
  96. data/lib/remarkable/active_record/macros/validations/allow_values_for.rb +0 -103
  97. data/lib/remarkable/active_record/macros/validations/ensure_length_at_least.rb +0 -97
  98. data/lib/remarkable/active_record/macros/validations/ensure_length_in_range.rb +0 -134
  99. data/lib/remarkable/active_record/macros/validations/ensure_length_is.rb +0 -106
  100. data/lib/remarkable/active_record/macros/validations/ensure_value_in_range.rb +0 -117
  101. data/lib/remarkable/active_record/macros/validations/have_class_methods.rb +0 -74
  102. data/lib/remarkable/active_record/macros/validations/have_instance_methods.rb +0 -74
  103. data/lib/remarkable/active_record/macros/validations/have_named_scope.rb +0 -148
  104. data/lib/remarkable/active_record/macros/validations/have_readonly_attributes.rb +0 -81
  105. data/lib/remarkable/active_record/macros/validations/only_allow_numeric_values_for.rb +0 -89
  106. data/lib/remarkable/active_record/macros/validations/protect_attributes.rb +0 -89
  107. data/lib/remarkable/active_record/macros/validations/require_acceptance_of.rb +0 -94
  108. data/lib/remarkable/active_record/macros/validations/require_attributes.rb +0 -94
  109. data/lib/remarkable/active_record/macros/validations/require_unique_attributes.rb +0 -146
  110. data/lib/remarkable/controller/macros/assign_to.rb +0 -110
  111. data/lib/remarkable/controller/macros/filter_params.rb +0 -52
  112. data/lib/remarkable/controller/macros/redirect_to.rb +0 -24
  113. data/lib/remarkable/controller/macros/render_a_form.rb +0 -23
  114. data/lib/remarkable/controller/macros/render_template.rb +0 -18
  115. data/lib/remarkable/controller/macros/render_with_layout.rb +0 -61
  116. data/lib/remarkable/controller/macros/respond_with.rb +0 -86
  117. data/lib/remarkable/controller/macros/respond_with_content_type.rb +0 -45
  118. data/lib/remarkable/controller/macros/return_from_session.rb +0 -45
  119. data/lib/remarkable/controller/macros/route.rb +0 -91
  120. data/lib/remarkable/controller/macros/set_the_flash_to.rb +0 -58
  121. data/spec/rails_root/app/models/dog.rb +0 -5
@@ -7,14 +7,37 @@ describe Post do
7
7
  it { should belong_to(:owner) }
8
8
  it { should belong_to(:user, :owner) }
9
9
 
10
+ it { should have_many(:tags).through(:taggings) }
10
11
  it { should have_many(:tags, :through => :taggings) }
12
+
13
+ it { should have_many(:through_tags).through(:taggings) }
11
14
  it { should have_many(:through_tags, :through => :taggings) }
15
+
16
+ it { should have_many(:tags, :through_tags).through(:taggings) }
12
17
  it { should have_many(:tags, :through_tags, :through => :taggings) }
13
18
 
14
19
  it { should require_unique_attributes(:title) }
20
+ it { should_not require_unique_attributes(:body) }
21
+ it { should_not require_unique_attributes(:title).scoped_to(:user_id) }
22
+ it { should_not require_unique_attributes(:title, :scoped_to => :user_id) }
23
+
15
24
  it { should require_attributes(:body, :message => /wtf/) }
25
+ it { should require_attributes(:body).message(/wtf/) }
26
+ it { should_not require_attributes(:body) }
16
27
  it { should require_attributes(:title) }
28
+ it { should_not require_attributes(:user_id) }
29
+
17
30
  it { should only_allow_numeric_values_for(:user_id) }
31
+
32
+ it { should validate_numericality_of(:user_id) }
33
+ it { should validate_numericality_of(:user_id).allow_nil(false) }
34
+ it { should validate_numericality_of(:user_id).allow_blank(false) }
35
+
36
+ it { should_not validate_numericality_of(:user_id, :allow_nil => true) }
37
+ it { should_not validate_numericality_of(:user_id, :allow_blank => true) }
38
+
39
+ it { should_not validate_numericality_of(:title) }
40
+ it { should_not only_allow_numeric_values_for(:title) }
18
41
  end
19
42
 
20
43
  describe Post do
@@ -23,13 +46,24 @@ describe Post do
23
46
  should_belong_to :user
24
47
  should_belong_to :owner
25
48
  should_belong_to :user, :owner
26
-
49
+
27
50
  should_have_many :tags, :through => :taggings
28
51
  should_have_many :through_tags, :through => :taggings
29
52
  should_have_many :tags, :through_tags, :through => :taggings
30
-
53
+
31
54
  should_require_unique_attributes :title
32
55
  should_require_attributes :body, :message => /wtf/
33
56
  should_require_attributes :title
57
+
34
58
  should_only_allow_numeric_values_for :user_id
59
+
60
+ should_validate_numericality_of :user_id
61
+ should_validate_numericality_of :user_id, :allow_nil => false
62
+ should_validate_numericality_of :user_id, :allow_blank => false
63
+
64
+ should_not_validate_numericality_of :user_id, :allow_nil => true
65
+ should_not_validate_numericality_of :user_id, :allow_blank => true
66
+
67
+ should_not_validate_numericality_of :title
68
+ should_not_only_allow_numeric_values_for :title
35
69
  end
@@ -1,6 +1,9 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe Product do
4
+ it { should require_attributes(:title) }
5
+ it { should_not require_attributes(:price) }
6
+
4
7
  describe "An intangible product" do
5
8
  before(:all) do
6
9
  @product = Product.new(:tangible => false)
@@ -9,8 +12,27 @@ describe Product do
9
12
  it { @product.should_not allow_values_for(:size, "22") }
10
13
  it { @product.should allow_values_for(:size, "22kb") }
11
14
 
15
+ it { @product.should_not validate_format_of(:size, "22") }
16
+ it { @product.should validate_format_of(:size, "22kb") }
17
+
18
+ it { @product.should validate_exclusion_of(:weight, 10..100) }
19
+ it { @product.should_not validate_exclusion_of(:weight, 1..9) }
20
+
12
21
  it { @product.should require_attributes(:title) }
22
+ it { @product.should_not require_attributes(:price) }
23
+
24
+ it { @product.should validate_presence_of(:title) }
25
+ it { @product.should_not validate_presence_of(:price) }
26
+
13
27
  it { @product.should ensure_value_in_range(:price, 0..99) }
28
+ it { @product.should validate_inclusion_of(:price, 0..99) }
29
+ it { @product.should validate_inclusion_of(:price, 0..99).allow_nil(false) }
30
+ it { @product.should validate_inclusion_of(:price, 0..99).allow_blank(false) }
31
+
32
+ it { @product.should_not ensure_value_in_range(:price, 2..80) }
33
+ it { @product.should_not validate_inclusion_of(:price, 2..80) }
34
+ it { @product.should_not validate_inclusion_of(:price, 0..99, :allow_nil => true) }
35
+ it { @product.should_not validate_inclusion_of(:price, 0..99, :allow_blank => true) }
14
36
  end
15
37
 
16
38
  describe "A tangible product" do
@@ -18,13 +40,32 @@ describe Product do
18
40
  @product = Product.new(:tangible => true)
19
41
  end
20
42
 
21
- it { @product.should_not allow_values_for(:size, "22", "10x15") }
22
- it { @product.should allow_values_for(:size, "12x12x1") }
43
+ it { @product.should validate_inclusion_of(:size, "S", "M", "L", "XL") }
44
+ it { @product.should validate_inclusion_of(:size, "S", "M", "L", "XL").allow_blank }
45
+ it { @product.should_not validate_inclusion_of(:size, "XXXL", "XXL") }
46
+ it { @product.should_not validate_inclusion_of(:size, "S", "M", "L", "XL", :allow_blank => false) }
47
+
48
+ it { @product.should validate_exclusion_of(:size, "XS", "XM") }
49
+ it { @product.should_not validate_exclusion_of(:size, "S", "M", "L", "XL") }
50
+
51
+ it { @product.should require_attributes(:price, :title) }
52
+ it { @product.should validate_presence_of(:price, :title) }
23
53
 
24
- it { @product.should require_attributes(:price) }
25
54
  it { @product.should ensure_value_in_range(:price, 1..9999) }
26
55
  it { @product.should ensure_value_in_range(:weight, 1..100) }
56
+
57
+ it { @product.should validate_inclusion_of(:price, 1..9999) }
58
+ it { @product.should validate_inclusion_of(:price, 1..9999).allow_nil }
59
+ it { @product.should_not validate_inclusion_of(:price, 1..9999, :allow_nil => false) }
60
+
61
+ it { @product.should validate_inclusion_of(:weight, 1..100) }
62
+ it { @product.should validate_inclusion_of(:weight, 1..100).allow_blank(true) }
63
+ it { @product.should_not validate_inclusion_of(:weight, 1..100, :allow_blank => false) }
64
+
27
65
  it { @product.should ensure_length_in_range(:size, 5..20) }
66
+ it { @product.should validate_length_of(:size, :in => 5..20).allow_blank }
67
+ it { @product.should_not validate_length_of(:size, :in => 1..10) }
68
+ it { @product.should_not validate_length_of(:size, :within => 5..20, :allow_blank => false) }
28
69
  end
29
70
  end
30
71
 
@@ -36,9 +77,14 @@ describe Product do
36
77
 
37
78
  should_not_allow_values_for :size, "22"
38
79
  should_allow_values_for :size, "22kb"
39
-
40
- should_require_attributes :title
80
+
41
81
  should_ensure_value_in_range :price, 0..99
82
+
83
+ should_require_attributes(:title)
84
+ should_not_require_attributes(:price)
85
+
86
+ should_validate_presence_of(:title)
87
+ should_not_validate_presence_of(:price)
42
88
  end
43
89
 
44
90
  describe "A tangible product" do
@@ -46,12 +92,31 @@ describe Product do
46
92
  @product = Product.new(:tangible => true)
47
93
  end
48
94
 
49
- should_not_allow_values_for :size, "22", "10x15"
50
- should_allow_values_for :size, "12x12x1"
95
+ should_validate_inclusion_of :size, "S", "M", "L", "XL"
96
+ should_validate_inclusion_of :size, :allow_blank => true
97
+ should_not_validate_inclusion_of :size, "XXXL", "XXL"
98
+ should_not_validate_inclusion_of :size, "S", "M", "L", "XL", :allow_blank => false
99
+
100
+ should_validate_exclusion_of :size, "XS", "XM"
101
+ should_not_validate_exclusion_of :size, "S", "M", "L", "XL"
102
+
103
+ should_require_attributes :price, :title
104
+ should_validate_presence_of :price, :title
51
105
 
52
- should_require_attributes :price
53
106
  should_ensure_value_in_range :price, 1..9999
54
107
  should_ensure_value_in_range :weight, 1..100
108
+
109
+ should_validate_inclusion_of :price, 1..9999
110
+ should_validate_inclusion_of :price, 1..9999, :allow_nil => true
111
+ should_not_validate_inclusion_of :price, 1..9999, :allow_nil => false
112
+
113
+ should_validate_inclusion_of :weight, 1..100
114
+ should_validate_inclusion_of :weight, 1..100, :allow_blank => true
115
+ should_not_validate_inclusion_of :weight, 1..100, :allow_blank => false
116
+
55
117
  should_ensure_length_in_range :size, 5..20
118
+ should_validate_length_of :size, :in => 5..20, :allow_blank => true
119
+ should_not_validate_length_of :size, :in => 1..10
120
+ should_not_validate_length_of :size, :within =>5..20, :allow_blank => false
56
121
  end
57
122
  end
@@ -1,13 +1,13 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe Tag do
4
+ it { should have_many(:taggings).dependent(:destroy) }
4
5
  it { should have_many(:taggings, :dependent => :destroy) }
5
6
  it { should have_many(:posts) }
6
7
 
7
8
  it { should ensure_length_at_least(:name, 2) }
8
-
9
+
9
10
  it { should protect_attributes(:secret) }
10
-
11
11
  it { should_not protect_attributes(:name) }
12
12
  end
13
13
 
@@ -4,10 +4,34 @@ describe Tagging do
4
4
  it { should belong_to(:post) }
5
5
  it { should belong_to(:tag) }
6
6
  it { should belong_to(:post, :tag) }
7
+
8
+ it { should validate_associated(:post) }
9
+ it { should validate_associated(:tag) }
10
+ it { should validate_associated(:tag, :post) }
11
+
12
+ it do
13
+ # Create a Post mock that will return true when saving.
14
+ # This means that the object Post is always valid, then it can not be validated.
15
+ @post = mock_model(Post, :save => true, :valid? => true)
16
+ should_not validate_associated(:post)
17
+ end
18
+
19
+ it do
20
+ # Create a Tagging mock that will return true when saving.
21
+ # This means that even the association :post is not valid, :tagging will be valid.
22
+ # Then the association is not validated.
23
+ @tagging = Tagging.new
24
+ @tagging.stub!(:save).and_return(true)
25
+ should_not validate_associated(:post)
26
+ end
7
27
  end
8
28
 
9
29
  describe Tagging do
10
30
  should_belong_to :post
11
31
  should_belong_to :tag
12
32
  should_belong_to :post, :tag
33
+
34
+ should_validate_associated :tag
35
+ should_validate_associated :post
36
+ should_validate_associated :tag, :post
13
37
  end
@@ -8,50 +8,180 @@ describe User do
8
8
  it { should have_many(:friendships) }
9
9
  it { should have_many(:friends) }
10
10
  it { should have_many(:posts, :dogs, :friendships, :friends) }
11
+
12
+ it { should validate_associated(:posts) }
13
+ it { should validate_associated(:address) }
14
+ it { should validate_associated(:posts, :address) }
15
+ it { should_not validate_associated(:dogs) }
11
16
 
12
17
  it { should have_one(:address) }
18
+ it { should have_one(:address).dependent(:destroy) }
13
19
  it { should have_one(:address, :dependent => :destroy) }
14
20
 
15
- it { should have_indices(:email, :name, [:email, :name]) }
21
+ it { should_not have_index(:foo, :bar) }
22
+
23
+ it { should have_indices(:email, :name) }
24
+ it { should have_index([:email, :name]).unique }
25
+ it { should have_index([:email, :name]).unique(true) }
26
+ it { should have_index([:email, :name], :unique => true) }
27
+ it { should have_index(:age, :unique => false) }
28
+
29
+ it { should_not have_index(:phone) }
30
+ it { should_not have_index(:email, :unique => false) }
31
+ it { should_not have_index(:age, :unique => true) }
32
+
16
33
  it { should have_index(:age) }
17
-
34
+ it { should_not have_index(:aged) }
35
+
36
+ it { should have_named_scope(:old)}
18
37
  it { should have_named_scope(:old, :conditions => "age > 50") }
38
+ it { should_not have_named_scope(:old, :conditions => "age > 49") }
19
39
  it { should have_named_scope(:eighteen, :conditions => { :age => 18 }) }
20
-
40
+ it { should_not have_named_scope(:eighteen, :conditions => { :age => 17 }) }
41
+
42
+ it { should have_named_scope('recent(5)') }
21
43
  it { should have_named_scope('recent(5)', :limit => 5) }
44
+ it { should_not have_named_scope('recent(5)', :limit => 4) }
22
45
  it { should have_named_scope('recent(1)', :limit => 1) }
46
+ it { should_not have_named_scope('recent(1)', :limit => 2) }
23
47
  it { should have_named_scope('recent_via_method(7)', :limit => 7) }
24
-
48
+ it { should_not have_named_scope('recent_via_method(7)', :limit => 8) }
49
+
25
50
  describe "when given an instance variable" do
26
51
  before(:each) do
27
52
  @count = 2
28
53
  end
29
54
  it { should have_named_scope("recent(#{@count})", :limit => 2) }
55
+ it { should_not have_named_scope("recent(#{@count})", :limit => 1) }
30
56
  end
31
57
 
58
+ it { should have_after_create_callback(:send_welcome_email) }
59
+ it { should_not have_after_save_callback(:send_welcome_email) }
60
+ it { should_not have_after_destroy_callback(:goodbye_jerk) }
61
+ it { should have_before_validation_on_update_callback(:some_weird_callback) }
62
+
32
63
  it { should_not allow_values_for(:email, "blah", "b lah") }
33
64
  it { should allow_values_for(:email, "a@b.com", "asdf@asdf.com") }
34
- it { should ensure_length_in_range(:email, 1..100) }
35
- it { should ensure_value_in_range(:age, 1..100) }
65
+ it { should_not allow_values_for(:email, "a@b.com", "asdf@asdf.com").allow_nil }
66
+ it { should_not allow_values_for(:email, "a@b.com", "asdf@asdf.com").allow_nil(true) }
67
+ it { should allow_values_for(:email, "a@b.com", "asdf@asdf.com").allow_nil(false) }
68
+
69
+ it { should validate_confirmation_of(:username, :email) }
70
+ it { should_not validate_confirmation_of(:ssn) }
71
+
72
+ it { should ensure_length_in_range(:email, 2..100) }
73
+ it { should_not ensure_length_in_range(:email, 1..100) }
74
+ it { should_not ensure_length_in_range(:email, 2..101) }
75
+ it { should_not ensure_length_in_range(:email, 3..100) }
76
+ it { should_not ensure_length_in_range(:email, 2..99) }
77
+
78
+ it { should validate_size_of(:email, :minimum => 2) }
79
+ it { should validate_size_of(:email, :maximum => 100) }
80
+ it { should validate_length_of(:email, :in => 2..100) }
81
+ it { should validate_length_of(:email, :within => 2..100).allow_nil(false) }
82
+ it { should validate_length_of(:email, :within => 2..100).allow_blank(false) }
83
+
84
+ it { should_not validate_length_of(:email, :is => 2) }
85
+ it { should_not validate_length_of(:email, :is => 100) }
86
+ it { should_not validate_length_of(:email, :within => 0..200) }
87
+ it { should_not validate_length_of(:email, :in => 2..100, :allow_nil => true) }
88
+ it { should_not validate_length_of(:email, :in => 2..100, :allow_blank => true) }
89
+
90
+ it { should ensure_value_in_range(:age, 2..100) }
91
+ it { should_not ensure_value_in_range(:age, 1..100) }
92
+ it { should_not ensure_value_in_range(:age, 2..101) }
93
+ it { should_not ensure_value_in_range(:age, 3..100) }
94
+ it { should_not ensure_value_in_range(:age, 2..99) }
95
+
36
96
  it { should protect_attributes(:password) }
97
+ it { should_not protect_attributes(:name, :age) }
98
+
99
+ it { should allow_mass_assignment_of(:name, :age) }
100
+ it { should_not allow_mass_assignment_of(:password) }
101
+
102
+ it { should have_class_methods(:find) }
103
+ it { should_not have_class_methods(:foo) }
37
104
  it { should have_class_methods(:find, :destroy) }
105
+ it { should_not have_class_methods(:foo, :bar) }
106
+
107
+ it { should have_instance_methods(:email) }
108
+ it { should_not have_instance_methods(:foo) }
38
109
  it { should have_instance_methods(:email, :age, :email=, :valid?) }
110
+ it { should_not have_instance_methods(:foo, :bar) }
39
111
 
112
+ it { should_not have_db_column(:foo) }
113
+ it { should_not have_db_columns(:foo, :bar) }
40
114
  it { should have_db_columns(:name, :email, :age) }
41
- it { should have_db_column(:name) }
42
- it { should have_db_column(:id, :type => "integer", :primary => true) }
43
- it { should have_db_column(:email, :type => "string", :default => nil, :precision => nil, :limit => 255,
44
- :null => true, :primary => false, :scale => nil, :sql_type => 'varchar(255)') }
115
+ it { should have_db_columns(:name, :email, :type => "string") }
116
+ it { should_not have_db_columns(:name, :email, :type => "integer") }
117
+ it { should have_db_columns(:name, :email).type("string") }
118
+ it { should_not have_db_columns(:foo, :bar).type("string") }
45
119
 
120
+ it { should have_db_column(:name) }
121
+ it { should have_db_column(:id).type("integer").primary(true) }
122
+ it { should have_db_column(:id).type("integer").primary }
123
+ it { should have_db_column(:email).type("string").default(nil).precision(nil).limit(255).null(true).primary(false).scale(nil).sql_type('varchar(255)') }
124
+ it { should have_db_column(:email).type("string") }
125
+ it { should_not have_db_column(:email).type("integer") }
126
+ it { should have_db_column(:email).default(nil) }
127
+ it { should_not have_db_column(:email).default('foo') }
128
+ it { should have_db_column(:email).precision(nil) }
129
+ it { should_not have_db_column(:email).precision(10) }
130
+ it { should have_db_column(:email).limit(255) }
131
+ it { should_not have_db_column(:email).limit(254) }
132
+ it { should have_db_column(:email).null(true) }
133
+ it { should have_db_column(:email).null }
134
+ it { should_not have_db_column(:email).null(false) }
135
+ it { should have_db_column(:email).primary(false) }
136
+ it { should_not have_db_column(:email).primary }
137
+ it { should_not have_db_column(:email).primary(true) }
138
+ it { should have_db_column(:email).scale(nil) }
139
+ it { should_not have_db_column(:email).scale(2) }
140
+ it { should have_db_column(:email).sql_type('varchar(255)') }
141
+ it { should_not have_db_column(:email).sql_type('varchar(254)') }
142
+ it { should have_db_column(:email, :type => "string").limit(255) }
143
+ it { should_not have_db_column(:email, :type => "integer").limit(255) }
144
+ it { should have_db_column(:email, :type => "string", :default => nil, :precision => nil, :limit => 255,
145
+ :null => true, :primary => false, :scale => nil, :sql_type => 'varchar(255)') }
146
+
46
147
  it { should require_acceptance_of(:eula) }
148
+ it { should_not require_acceptance_of(:name) }
149
+ it { should_not validate_acceptance_of(:name) }
150
+
151
+ it { should validate_acceptance_of(:eula) }
152
+ it { should validate_acceptance_of(:eula, :allow_nil => true) }
153
+ it { should_not validate_acceptance_of(:eula, :allow_nil => false) }
154
+
155
+ it { should validate_acceptance_of(:terms).accept(true) }
156
+ it { should validate_acceptance_of(:terms).allow_nil(false) }
157
+ it { should_not validate_acceptance_of(:terms).allow_nil }
158
+ it { should_not validate_acceptance_of(:terms, :accept => false) }
159
+
160
+ it "should rails error when calling allow_blank on validate_acceptance_of matcher" do
161
+ proc{ should validate_acceptance_of(:terms).allow_nil.allow_blank }.should raise_error(NoMethodError)
162
+ end
163
+
164
+ it { should validate_uniqueness_of(:email, :scoped_to => :name) }
47
165
  it { should require_unique_attributes(:email, :scoped_to => :name) }
48
-
166
+
49
167
  it { should ensure_length_is(:ssn, 9, :message => "Social Security Number is not the right length") }
168
+ it { should ensure_length_is(:ssn, 9).message("Social Security Number is not the right length") }
169
+ it { should_not ensure_length_is(:ssn, 9) }
170
+ it { should_not ensure_length_is(:ssn, 8).message("Social Security Number is not the right length") }
171
+ it { should_not ensure_length_is(:ssn, 10).message("Social Security Number is not the right length") }
172
+
173
+ it { should validate_length_of(:ssn, :is => 9).message("Social Security Number is not the right length") }
174
+ it { should validate_length_of(:ssn, :is => 9, :message => "Social Security Number is not the right length") }
175
+
50
176
  it { should only_allow_numeric_values_for(:ssn) }
51
-
177
+
178
+ it { should validate_numericality_of(:ssn) }
179
+ it { should validate_numericality_of(:ssn).equal_to(123456789) }
180
+ it { should_not validate_numericality_of(:ssn, :equal_to => 123456780) }
181
+
52
182
  it { should have_readonly_attributes(:name) }
53
-
54
- it { should_not protect_attributes(:name, :age) }
183
+ it { should_not have_readonly_attributes(:foo) }
184
+ it { should_not have_readonly_attributes(:ssn) }
55
185
  end
56
186
 
57
187
  describe User do
@@ -65,9 +195,20 @@ describe User do
65
195
 
66
196
  should_have_one :address
67
197
  should_have_one :address, :dependent => :destroy
198
+
199
+ should_validate_associated(:posts)
200
+ should_validate_associated(:address)
201
+ should_validate_associated(:posts, :address)
202
+ should_not_validate_associated(:dogs)
68
203
 
69
- should_have_indices :email, :name, [:email, :name]
204
+ should_have_indices :email, :name
70
205
  should_have_index :age
206
+ should_have_index [:email, :name], :unique => true
207
+ should_have_index :age, :unique => false
208
+
209
+ should_not_have_index :phone
210
+ should_not_have_index :email, :unique => false
211
+ should_not_have_index :age, :unique => true
71
212
 
72
213
  should_have_named_scope :old, :conditions => "age > 50"
73
214
  should_have_named_scope :eighteen, :conditions => { :age => 18 }
@@ -80,28 +221,72 @@ describe User do
80
221
  before(:each) do
81
222
  @count = 2
82
223
  end
83
- should_have_named_scope "recent(@count)", :limit => 2
224
+ # should_have_named_scope "recent(@count)", :limit => 2
84
225
  end
226
+
227
+ should_have_after_create_callback(:send_welcome_email)
228
+ should_not_have_after_save_callback(:send_welcome_email)
229
+ should_not_have_after_destroy_callback(:goodbye_jerk)
230
+ should_have_before_validation_on_update_callback(:some_weird_callback)
85
231
 
86
232
  should_not_allow_values_for :email, "blah", "b lah"
87
233
  should_allow_values_for :email, "a@b.com", "asdf@asdf.com"
88
- should_ensure_length_in_range :email, 1..100
89
- should_ensure_value_in_range :age, 1..100
234
+ should_ensure_value_in_range :age, 2..100
90
235
  should_protect_attributes :password
91
236
  should_have_class_methods :find, :destroy
92
237
  should_have_instance_methods :email, :age, :email=, :valid?
238
+
239
+ should_allow_mass_assignment_of :email
240
+ should_not_allow_mass_assignment_of :password
241
+
242
+ should_ensure_length_in_range :email, 2..100
243
+
244
+ should_validate_size_of :email, :minimum => 2
245
+ should_validate_size_of :email, :maximum => 100
246
+ should_validate_length_of :email, :in => 2..100
247
+ should_validate_length_of :email, :within => 2..100 , :allow_nil => false
248
+ should_validate_length_of :email, :within => 2..100, :allow_blank => false
249
+
250
+ should_not_validate_length_of :email, :is => 2
251
+ should_not_validate_length_of :email, :is => 100
252
+ should_not_validate_length_of :email, :within => 0..200
253
+ should_not_validate_length_of :email, :in => 2..100, :allow_nil => true
254
+ should_not_validate_length_of :email, :in => 2..100, :allow_blank => true
255
+
256
+ should_validate_confirmation_of :username, :email
257
+ should_not_validate_confirmation_of :ssn
93
258
 
94
259
  should_have_db_columns :name, :email, :age
260
+ should_have_db_columns :name, :email, :type => "string"
261
+
95
262
  should_have_db_column :name
96
263
  should_have_db_column :id, :type => "integer", :primary => true
97
264
  should_have_db_column :email, :type => "string", :default => nil, :precision => nil, :limit => 255,
98
265
  :null => true, :primary => false, :scale => nil, :sql_type => 'varchar(255)'
99
-
266
+
100
267
  should_require_acceptance_of :eula
268
+ should_validate_acceptance_of :eula
269
+ should_validate_acceptance_of :eula, :allow_nil => true
270
+ should_not_validate_acceptance_of :eula, :allow_nil => false
271
+
272
+ should_validate_acceptance_of :terms
273
+ should_validate_acceptance_of :terms, :accept => true
274
+ should_validate_acceptance_of :terms, :allow_nil => false
275
+ should_not_validate_acceptance_of :terms, :allow_nil => true
276
+ should_not_validate_acceptance_of :terms, :accept => false
277
+
278
+ should_not_validate_acceptance_of :name
279
+ should_not_require_acceptance_of :name
280
+
281
+ should_validate_uniqueness_of :email, :scoped_to => :name
101
282
  should_require_unique_attributes :email, :scoped_to => :name
102
-
283
+
103
284
  should_ensure_length_is :ssn, 9, :message => "Social Security Number is not the right length"
104
285
  should_only_allow_numeric_values_for :ssn
105
-
286
+
287
+ should_validate_numericality_of :ssn
288
+ should_validate_numericality_of :ssn, :equal_to => 123456789
289
+ should_not_validate_numericality_of :ssn, :equal_to => 123456780
290
+
106
291
  should_have_readonly_attributes :name
107
292
  end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Custom Macros" do
4
+ before(:all) do
5
+ custom_macro = File.join(RAILS_ROOT, "spec", "remarkable_macros", "run_my_custom_macro.rb")
6
+ plugin_macro = File.join(RAILS_ROOT, "vendor", "plugins", "my_plugin", "remarkable_macros", "run_my_plugin_macro.rb")
7
+
8
+ [custom_macro, plugin_macro].each do |macro_file|
9
+ File.open(macro_file, "w") do |f|
10
+ f.puts("it 'should run my macro' do\t true.should be_true\tend")
11
+ end
12
+ end
13
+
14
+ load File.expand_path(File.dirname(__FILE__) + '/../../lib/remarkable/rails.rb')
15
+ end
16
+
17
+ it { self.class.should respond_to(:should_run_my_custom_macro) }
18
+ it { should run_my_custom_macro }
19
+
20
+ it { self.class.should respond_to(:should_run_my_plugin_macro) }
21
+ it { should run_my_plugin_macro }
22
+
23
+ after(:all) do
24
+ FileUtils.rm(File.join(RAILS_ROOT, "spec", "remarkable_macros", "run_my_custom_macro.rb"), :force => true)
25
+ FileUtils.rm(File.join(RAILS_ROOT, "vendor", "plugins", "my_plugin", "remarkable_macros", "run_my_plugin_macro.rb"), :force => true)
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "my own matcher" do
4
+ it { "abc".should first_three_letters_of_alphabet }
5
+ end
6
+
7
+ def first_three_letters_of_alphabet
8
+ simple_matcher "be the first three letters of alphabet" do |spec|
9
+ spec.should == "abc"
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ # require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ #
3
+ # describe "PrivateHelpers" do
4
+ # describe "get_options!" do
5
+ # it "remove opts from args" do
6
+ # args = [:a, :b, {}]
7
+ # get_options!(args)
8
+ # args.should == [:a, :b]
9
+ # end
10
+ #
11
+ # it "return wanted opts in order" do
12
+ # args = [{:one => 1, :two => 2}]
13
+ # one, two = get_options!(args, :one, :two)
14
+ # one.should == 1
15
+ # two.should == 2
16
+ # end
17
+ #
18
+ # it "raise ArgumentError if given unwanted option" do
19
+ # args = [{:one => 1, :two => 2}]
20
+ # lambda { get_options!(args, :one) }.should raise_error(ArgumentError)
21
+ # end
22
+ # end
23
+ #
24
+ # class ::SomeModel; end
25
+ # describe "subject_class" do
26
+ # it "sniff the class constant from the test class" do
27
+ # self.should_receive(:described_type).and_return(SomeModel)
28
+ # subject_class.should == SomeModel
29
+ # end
30
+ # end
31
+ # end
@@ -4,6 +4,7 @@ class PostsController < ApplicationController
4
4
 
5
5
  def index
6
6
  @posts = @user.posts
7
+ @some_text = "foo bar"
7
8
 
8
9
  respond_to do |format|
9
10
  format.html # index.rhtml
@@ -19,6 +20,7 @@ class PostsController < ApplicationController
19
20
 
20
21
  def show
21
22
  @post = @user.posts.find(params[:id])
23
+ @false_flag = false
22
24
 
23
25
  respond_to do |format|
24
26
  format.html { render :layout => 'wide' }
@@ -2,6 +2,6 @@ class Address < ActiveRecord::Base
2
2
  belongs_to :addressable, :polymorphic => true
3
3
  validates_uniqueness_of :title, :scope => [:addressable_type, :addressable_id]
4
4
 
5
- validates_length_of :zip, :minimum => 5
6
- validates_numericality_of :zip
5
+ validates_length_of :zip, :minimum => 5, :allow_nil => true
6
+ validates_numericality_of :zip, :less_than => 20, :greater_than => 10
7
7
  end
@@ -1,3 +1,7 @@
1
1
  class Flea < ActiveRecord::Base
2
2
  has_and_belongs_to_many :dogs
3
+ validates_presence_of :name
4
+ validates_uniqueness_of :name, :case_sensitive => false
5
+ validates_uniqueness_of :color, :allow_nil => true
6
+ validates_uniqueness_of :address, :allow_blank => true
3
7
  end
@@ -0,0 +1,12 @@
1
+ module Pets
2
+ class Dog < ActiveRecord::Base
3
+ belongs_to :user, :foreign_key => :owner_id
4
+ belongs_to :address
5
+ has_and_belongs_to_many :fleas, :join_table => :fleas
6
+
7
+ validates_numericality_of :age, :allow_blank => true, :only_integer => true, :odd => true, :greater_than_or_equal_to => 10
8
+ validates_numericality_of :owner_id, :allow_nil => true, :even => true, :less_than_or_equal_to => 10
9
+
10
+ validates_presence_of :owner_id
11
+ end
12
+ end