whyvalidationssuckin96 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.2.0
@@ -1,3 +1,2 @@
1
1
  module WhyValidationsSuckIn96
2
-
3
2
  end
@@ -0,0 +1,38 @@
1
+ require 'active_record/autosave_association'
2
+
3
+ module WhyValidationsSuckIn96
4
+ module ActiveRecord
5
+ module AssociationValidation
6
+
7
+ def self.included(klass_or_mod)
8
+ klass_or_mod.module_eval do
9
+ extend ClassMethods
10
+ end
11
+ end
12
+
13
+ module ClassMethods
14
+ def self.extended(klass_or_mod)
15
+ (class << klass_or_mod; self; end).instance_eval do
16
+ # FIXME - alias method chain my ass
17
+ alias_method_chain :add_autosave_association_callbacks, :validation_hooks
18
+ end
19
+ end
20
+
21
+ def add_autosave_association_callbacks_with_validation_hooks(reflection)
22
+ add_autosave_association_callbacks_without_validation_hooks(reflection)
23
+ setup_validations_for_association_reflection(reflection)
24
+ end
25
+
26
+ private
27
+
28
+ def setup_validations_for_association_reflection(reflection)
29
+ return false unless reflection.options[:validate] || reflection.options[:autosave]
30
+ setup_validations { validates_associated reflection.name.to_sym, :on => :save }
31
+ end
32
+
33
+ end # ClassMethods
34
+ end # AssociationValidation
35
+ end # ActiveRecord
36
+ end # WhyValidationsSuckIn96
37
+
38
+ ActiveRecord::Base.instance_eval { include WhyValidationsSuckIn96::ActiveRecord::AssociationValidation }
@@ -0,0 +1,124 @@
1
+ require 'active_record/base'
2
+ require 'active_record/callbacks'
3
+
4
+ module WhyValidationsSuckIn96
5
+ module ActiveRecord
6
+ class << self
7
+ attr_accessor :warn_on_deprecation
8
+ end
9
+ self.warn_on_deprecation = true
10
+
11
+ RemovableInstanceMethods = %w[invalid? validate_on_create validate_on_update validate errors]
12
+ RemovableClassMethods = %w[validate validate_on_create validate_on_update validates_format_of validates_each
13
+ validates_inclusion_of validates_size_of validates_confirmation_of validates_exclusion_of
14
+ validates_uniqueness_of validates_associated validates_acceptance_of
15
+ validates_numericality_of validates_presence_of validates_length_of]
16
+
17
+ def self.included(klass_or_mod)
18
+ remove_active_record_validation_related_methods_from(klass_or_mod)
19
+ klass_or_mod.instance_eval do
20
+ include WhyValidationsSuckIn96::ValidationSupport
21
+ include WhyValidationsSuckIn96::ActiveRecord::InstanceMethods
22
+ extend WhyValidationsSuckIn96::ActiveRecord::ClassMethods
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ # FIXME - holy mother of god is this a nasty method
29
+ def self.remove_active_record_validation_related_methods_from(klass_or_mod)
30
+ method_map = {klass_or_mod => RemovableInstanceMethods, (class<<klass_or_mod;self;end) => RemovableClassMethods}
31
+ method_map.each do |context, removable_methods|
32
+ context.instance_eval do
33
+ removable_methods.each do |removable_method|
34
+ begin
35
+ remove_method removable_method
36
+ rescue => e
37
+ undef_method removable_method
38
+ end
39
+ end # removable_methods.each
40
+ end # context.instance_eval
41
+ end # method_map.each
42
+ end
43
+
44
+ module ClassMethods
45
+
46
+ # FIXME - this is a seedy hack and i blame the entire contents of active_record/autosave_association.rb
47
+ # for it being necessary.
48
+ def validate(*args)
49
+ return false unless WhyValidationsSuckIn96::ActiveRecord.warn_on_deprecation
50
+ callstack = caller
51
+ warn(<<-EOW.gsub(/^\s{10}/, ""))
52
+ This is a friendly message from WhyValidationsSuckIn96. #{self.inspect} called 'validate' which is a
53
+ deprecated method. The arguments given were:
54
+
55
+ #{args.inspect} - #{block_given? ? 'block given' : 'no block given'}
56
+
57
+ and the caller was:
58
+
59
+ #{callstack.first}
60
+
61
+ If these warnings are coming from a call to 'add_autosave_association_callbacks', do not be alarmed, as
62
+ WhyValidationsSuckIn96 has implemented its own versions of the necessary validation callbacks.
63
+
64
+ These warnings can be silenced by setting 'WhyValidationsSuckIn96::ActiveRecord.warn_on_deprecation' to false.
65
+ You will now be returned to your regularly scheduled programming.
66
+ EOW
67
+ false
68
+ end
69
+
70
+ end # ClassMethods
71
+
72
+ module InstanceMethods
73
+
74
+ def self.included(klass_or_mod)
75
+ klass_or_mod.module_eval do
76
+ alias_method :valid_without_callbacks?, :valid_with_lifecycle_checking?
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def validations_for_current_lifecycle
83
+ validations_for_save + (new_record? ? validations_for_create : validations_for_update)
84
+ end
85
+
86
+ def valid_with_lifecycle_checking?
87
+ validations_for_current_lifecycle.collect do |validation|
88
+ validation.validates?
89
+ end.all?
90
+ end
91
+
92
+ def validations_for_update
93
+ all_validations.select do |validation|
94
+ validation.options[:on] == :update
95
+ end
96
+ end
97
+
98
+ def validations_for_create
99
+ all_validations.select do |validation|
100
+ validation.options[:on] == :create
101
+ end
102
+ end
103
+
104
+ def validations_for_save
105
+ all_validations.select do |validation|
106
+ validation.options[:on].nil? || validation.options[:on] == :save
107
+ end
108
+ end
109
+
110
+ end # InstanceMethods
111
+ end # ActiveRecord
112
+ end # WhyValidationsSuckIn96
113
+
114
+ module ActiveRecord
115
+ class RecordInvalid < ActiveRecordError
116
+ attr_reader :record
117
+ def initialize(record)
118
+ @record = record
119
+ super
120
+ end
121
+ end # RecordInvalid
122
+ end # ActiveRecord
123
+
124
+ ActiveRecord::Base.instance_eval { include WhyValidationsSuckIn96::ActiveRecord }
@@ -1,94 +1,5 @@
1
1
  require 'whyvalidationssuckin96'
2
2
  require 'active_record'
3
- require 'active_record/base'
4
- require 'active_record/callbacks'
5
- require 'whyvalidationssuckin96/rails/macros'
6
-
7
- module WhyValidationsSuckIn96
8
-
9
- module ActiveRecord
10
- RemovableInstanceMethods = %w[invalid? validate_on_create validate_on_update validate errors]
11
- RemovableClassMethods = %w[validate validate_on_create validate_on_update validates_format_of validates_each
12
- validates_inclusion_of validates_size_of validates_confirmation_of validates_exclusion_of
13
- validates_uniqueness_of validates_associated validates_acceptance_of
14
- validates_numericality_of validates_presence_of validates_length_of]
15
-
16
- def self.included(klass_or_mod)
17
- remove_active_record_validation_related_methods_from(klass_or_mod)
18
- klass_or_mod.instance_eval do
19
- include WhyValidationsSuckIn96::ValidationSupport
20
- include WhyValidationsSuckIn96::ActiveRecord::InstanceMethods
21
- end
22
- end
23
-
24
- private
25
-
26
- # FIXME - holy mother of god is this a nasty method
27
- def self.remove_active_record_validation_related_methods_from(klass_or_mod)
28
- method_map = {klass_or_mod => RemovableInstanceMethods, (class<<klass_or_mod;self;end) => RemovableClassMethods}
29
- method_map.each do |context, removable_methods|
30
- context.instance_eval do
31
- removable_methods.each do |removable_method|
32
- begin
33
- remove_method removable_method
34
- rescue => e
35
- undef_method removable_method
36
- end
37
- end # removable_methods.each
38
- end # context.instance_eval
39
- end # method_map.each
40
- end
41
-
42
- module InstanceMethods
43
-
44
- def self.included(klass_or_mod)
45
- klass_or_mod.module_eval do
46
- alias_method :valid_without_callbacks?, :valid_with_lifecycle_checking?
47
- end
48
- end
49
-
50
- private
51
-
52
- def validations_for_current_lifecycle
53
- validations_for_save + (new_record? ? validations_for_create : validations_for_update)
54
- end
55
-
56
- def valid_with_lifecycle_checking?
57
- validations_for_current_lifecycle.collect do |validation|
58
- validation.validates?
59
- end.all?
60
- end
61
-
62
- def validations_for_update
63
- all_validations.select do |validation|
64
- validation.options[:on] == :update
65
- end
66
- end
67
-
68
- def validations_for_create
69
- all_validations.select do |validation|
70
- validation.options[:on] == :create
71
- end
72
- end
73
-
74
- def validations_for_save
75
- all_validations.select do |validation|
76
- validation.options[:on].nil? || validation.options[:on] == :save
77
- end
78
- end
79
-
80
- end # InstanceMethods
81
- end # ActiveRecord
82
- end # WhyValidationsSuckIn96
83
-
84
- module ActiveRecord
85
- class RecordInvalid < ActiveRecordError
86
- attr_reader :record
87
- def initialize(record)
88
- @record = record
89
- super
90
- end
91
- end # RecordInvalid
92
- end # ActiveRecord
93
-
94
- ActiveRecord::Base.instance_eval { include WhyValidationsSuckIn96::ActiveRecord }
3
+ require 'whyvalidationssuckin96/rails/active_record/base_validation_overrides'
4
+ require 'whyvalidationssuckin96/rails/active_record/association_validation'
5
+ require 'whyvalidationssuckin96/rails/macros'
@@ -1,4 +1,5 @@
1
1
  require 'whyvalidationssuckin96/rails/active_record'
2
+ WhyValidationsSuckIn96::ActiveRecord.warn_on_deprecation = false
2
3
 
3
4
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
4
5
  ActiveRecord::Schema.define(:version => 1) do
@@ -11,8 +12,44 @@ ActiveRecord::Schema.define(:version => 1) do
11
12
  t.string :author
12
13
  t.string :type
13
14
  end
15
+
16
+ create_table :books do |t|
17
+ t.string :name
18
+ t.has_one :glossary
19
+ t.has_many :chapters
20
+ end
21
+
22
+ create_table :glossaries do |t|
23
+ t.belongs_to :book
24
+ end
25
+
26
+ create_table :chapters do |t|
27
+ t.string :name
28
+ t.belongs_to :book
29
+ end
30
+
31
+ create_table :genres do |t|
32
+ t.string :name
33
+ end
34
+
35
+ create_table :books_genres, :id => false do |t|
36
+ t.belongs_to :book
37
+ t.belongs_to :genre
38
+ end
14
39
  end
15
40
 
41
+ class Glossary < ActiveRecord::Base
42
+ end
43
+
44
+ class Book < ActiveRecord::Base
45
+ end
46
+
47
+ class Chapter < ActiveRecord::Base
48
+ end
49
+
50
+ class Genre < ActiveRecord::Base
51
+ end
52
+
16
53
  class MusicalWork < ActiveRecord::Base
17
54
  attr_accessor :state, :callbacks_run, :validations_run
18
55
 
@@ -0,0 +1,114 @@
1
+ require 'teststrap'
2
+ require 'rails/active_record_test_helper'
3
+
4
+ context "association validation" do
5
+ has_association_validation = lambda do |klass,assoc|
6
+ !klass.validation_collection.detect do |(validation_klass,opts)|
7
+ validation_klass == WhyValidationsSuckIn96::ValidatesAssociated && opts[:attribute] == assoc && opts[:on] == :save
8
+ end.nil?
9
+ end
10
+
11
+ context "against has_many" do
12
+ context "with :validate set to true" do
13
+ setup do
14
+ Class.new(Book) do
15
+ has_many :chapters, :validate => true
16
+ end
17
+ end
18
+
19
+ should "set up an association validation" do
20
+ has_association_validation[topic, :chapters]
21
+ end
22
+ end # with :validate set to true
23
+
24
+ context "with :validate set to false" do
25
+ setup do
26
+ Class.new(Book) do
27
+ has_many :chapters, :validate => false
28
+ end
29
+ end
30
+
31
+ should "not set up an association validation" do
32
+ has_association_validation[topic, :chapters]
33
+ end.equals(false)
34
+ end # with :validate set to false
35
+ end # against has_many
36
+
37
+ context "against has_and_belongs_to_many" do
38
+ context "with :validate set to true" do
39
+ setup do
40
+ Class.new(Genre) do
41
+ has_and_belongs_to_many :books, :validate => true
42
+ end
43
+ end
44
+
45
+ should "set up an association validation" do
46
+ has_association_validation[topic, :books]
47
+ end
48
+ end # with :validate set to true
49
+
50
+ context "with :validate set to false" do
51
+ setup do
52
+ Class.new(Genre) do
53
+ has_and_belongs_to_many :books, :validate => false
54
+ end
55
+ end
56
+
57
+ should "not set up an association validation" do
58
+ has_association_validation[topic, :books]
59
+ end.equals(false)
60
+ end # with :validate set to false
61
+ end # against has_and_belongs_to_many
62
+
63
+ context "against has_one" do
64
+ context "with :validate set to true" do
65
+ setup do
66
+ Class.new(Book) do
67
+ has_one :glossary, :validate => true
68
+ end
69
+ end
70
+
71
+ should "set up an association validation" do
72
+ has_association_validation[topic, :glossary]
73
+ end
74
+ end # with :validate set to true
75
+
76
+ context "with :validate set to false" do
77
+ setup do
78
+ Class.new(Book) do
79
+ has_one :glossary, :validate => false
80
+ end
81
+ end
82
+
83
+ should "not set up an association validation" do
84
+ has_association_validation[topic, :glossary]
85
+ end.equals(false)
86
+ end # with :validate set to false
87
+ end # against has_one
88
+
89
+ context "against belongs_to" do
90
+ context "with :validate set to true" do
91
+ setup do
92
+ Class.new(Chapter) do
93
+ belongs_to :book, :validate => true
94
+ end
95
+ end
96
+
97
+ should "set up an association validation" do
98
+ has_association_validation[topic, :book]
99
+ end
100
+ end # with :validate set to true
101
+
102
+ context "with :validate set to false" do
103
+ setup do
104
+ Class.new(Chapter) do
105
+ belongs_to :book, :validate => false
106
+ end
107
+ end
108
+
109
+ should "not set up an association validation" do
110
+ has_association_validation[topic, :book]
111
+ end.equals(false)
112
+ end # with :validate set to false
113
+ end # against belongs_to
114
+ end # association validation
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{whyvalidationssuckin96}
8
- s.version = "1.1.0"
8
+ s.version = "1.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["gabrielg", "douglasmeyer"]
@@ -81,6 +81,8 @@ Gem::Specification.new do |s|
81
81
  "lib/whyvalidationssuckin96/macros/validates_presence.rb",
82
82
  "lib/whyvalidationssuckin96/macros/validates_url.rb",
83
83
  "lib/whyvalidationssuckin96/rails/active_record.rb",
84
+ "lib/whyvalidationssuckin96/rails/active_record/association_validation.rb",
85
+ "lib/whyvalidationssuckin96/rails/active_record/base_validation_overrides.rb",
84
86
  "lib/whyvalidationssuckin96/rails/macros.rb",
85
87
  "lib/whyvalidationssuckin96/rails/macros/validates_uniqueness.rb",
86
88
  "lib/whyvalidationssuckin96/skippable_validation.rb",
@@ -98,8 +100,9 @@ Gem::Specification.new do |s|
98
100
  "test/macros/validates_numericality_test.rb",
99
101
  "test/macros/validates_presence_test.rb",
100
102
  "test/macros/validates_url_test.rb",
101
- "test/rails/active_record_test.rb",
102
103
  "test/rails/active_record_test_helper.rb",
104
+ "test/rails/association_validation_test.rb",
105
+ "test/rails/base_validation_overrides_test.rb",
103
106
  "test/rails/macros/validates_uniqueness_test.rb",
104
107
  "test/skippable_validation_test.rb",
105
108
  "test/teststrap.rb",
@@ -125,8 +128,9 @@ Gem::Specification.new do |s|
125
128
  "test/macros/validates_numericality_test.rb",
126
129
  "test/macros/validates_presence_test.rb",
127
130
  "test/macros/validates_url_test.rb",
128
- "test/rails/active_record_test.rb",
129
131
  "test/rails/active_record_test_helper.rb",
132
+ "test/rails/association_validation_test.rb",
133
+ "test/rails/base_validation_overrides_test.rb",
130
134
  "test/rails/macros/validates_uniqueness_test.rb",
131
135
  "test/skippable_validation_test.rb",
132
136
  "test/teststrap.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whyvalidationssuckin96
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gabrielg
@@ -117,6 +117,8 @@ files:
117
117
  - lib/whyvalidationssuckin96/macros/validates_presence.rb
118
118
  - lib/whyvalidationssuckin96/macros/validates_url.rb
119
119
  - lib/whyvalidationssuckin96/rails/active_record.rb
120
+ - lib/whyvalidationssuckin96/rails/active_record/association_validation.rb
121
+ - lib/whyvalidationssuckin96/rails/active_record/base_validation_overrides.rb
120
122
  - lib/whyvalidationssuckin96/rails/macros.rb
121
123
  - lib/whyvalidationssuckin96/rails/macros/validates_uniqueness.rb
122
124
  - lib/whyvalidationssuckin96/skippable_validation.rb
@@ -134,8 +136,9 @@ files:
134
136
  - test/macros/validates_numericality_test.rb
135
137
  - test/macros/validates_presence_test.rb
136
138
  - test/macros/validates_url_test.rb
137
- - test/rails/active_record_test.rb
138
139
  - test/rails/active_record_test_helper.rb
140
+ - test/rails/association_validation_test.rb
141
+ - test/rails/base_validation_overrides_test.rb
139
142
  - test/rails/macros/validates_uniqueness_test.rb
140
143
  - test/skippable_validation_test.rb
141
144
  - test/teststrap.rb
@@ -183,8 +186,9 @@ test_files:
183
186
  - test/macros/validates_numericality_test.rb
184
187
  - test/macros/validates_presence_test.rb
185
188
  - test/macros/validates_url_test.rb
186
- - test/rails/active_record_test.rb
187
189
  - test/rails/active_record_test_helper.rb
190
+ - test/rails/association_validation_test.rb
191
+ - test/rails/base_validation_overrides_test.rb
188
192
  - test/rails/macros/validates_uniqueness_test.rb
189
193
  - test/skippable_validation_test.rb
190
194
  - test/teststrap.rb