public
Description: Adds a depends_on class method to your ActiveRecord model so that you can define requisite objects. e.g. User.depends_on :profile, :attrs => [:first_name, :last_name, :email]
Homepage: http://stonean.com/wiki/classy-inheritance
Clone URL: git://github.com/stonean/classy-inheritance.git
changed validates_presence_of_if to validates_presence_if
stonean (author)
Tue Jul 08 15:51:12 -0700 2008
commit  0b5ecf02c674d67df597c8bb62f132b4c8ab9f76
tree    6c3bd0ad5ea2054d208f1104b5ddacd5984786f8
parent  daecd676ebc0a4b7284acc274dcef7c113922a88
...
1
 
2
3
4
...
 
1
2
3
4
0
@@ -1,4 +1,4 @@
0
-== 4ab0b0 2008-07-07
0
+== 0.4.5 2008-07-08
0
   * Add: support for optional dependencies through the :required option. Default (true).
0
   * Add: Basic test cases of classy-inheritance depends_on functionality.
0
 == 0.4.4 2008-06-24
...
27
28
29
30
31
32
 
 
 
33
34
35
36
37
38
 
 
 
 
 
 
 
39
40
41
...
71
72
73
 
 
 
 
 
 
 
 
 
 
 
74
75
76
 
77
78
79
...
85
86
87
 
 
 
 
88
89
90
91
92
93
 
94
95
96
...
27
28
29
 
 
 
30
31
32
33
34
35
36
37
 
38
39
40
41
42
43
44
45
46
47
...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
 
 
92
93
94
95
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
0
@@ -27,15 +27,21 @@ module Stonean
0
         define_relationship(model_sym,options)
0
 
0
         # Optional presence of handling
0
-        if options.has_key?(:required) && options[:required] != true
0
-          if [Symbol, String, Proc].include?(options[:required].class)
0
-            validates_presence_of model_sym, :if => options[:required]
0
+        if options.has_key?(:validates_presence_if) && options[:validates_presence_if] != true
0
+          if [Symbol, String, Proc].include?(options[:validates_presence_if].class)
0
+            validates_presence_of model_sym, :if => options[:validates_presence_if]
0
           end
0
         else
0
           validates_presence_of model_sym
0
         end
0
 
0
-        validates_associated model_sym
0
+        if options.has_key?(:validates_associated_if) && options[:validates_associated_if] != true
0
+          if [Symbol, String, Proc].include?(options[:validates_assoicated_if].class)
0
+            validates_associated model_sym, :if => options[:validates_associated_if]
0
+          end
0
+        else
0
+          validates_associated model_sym
0
+        end
0
 
0
         # Before save functionality to create/update the requisite object
0
         define_save_method(model_sym, options[:as])
0
@@ -71,9 +77,19 @@ module Stonean
0
 
0
       private
0
 
0
+      def classy_options
0
+        [:as, :attrs, :prefix, :validates_presence_if, :validates_associated_if]
0
+      end
0
+
0
+      def delete_classy_options(options, *keepers)
0
+        options.delete_if do |key,value|
0
+          classy_options.include?(key) && !keepers.include?(key)
0
+        end
0
+        options
0
+      end
0
+
0
       def define_relationship(model_sym, options)
0
-        opts = options.dup
0
-        [:attrs, :prefix, :required].each{|key| opts.delete(key)}
0
+        opts = delete_classy_options(options.dup, :as)
0
         if opts[:as]
0
           as_opt = opts.delete(:as)
0
           opts = polymorphic_constraints(as_opt).merge(opts)
0
@@ -85,12 +101,17 @@ module Stonean
0
 
0
       def define_save_method(model_sym, polymorphic_name = nil)
0
         define_method "save_requisite_#{model_sym}" do
0
+          # Return unless the association exists
0
+          eval("return unless self.#{model_sym}")
0
+
0
+          # Set the polymorphic type and id before saving
0
           if polymorphic_name
0
             eval("self.#{model_sym}.#{polymorphic_name}_type = self.class.name")
0
             eval("self.#{model_sym}.#{polymorphic_name}_id = self.id")
0
           end
0
 
0
           if polymorphic_name
0
+            # Save only if it's an update, has_one creates automatically
0
             eval <<-SAVEIT
0
               unless self.#{model_sym}.new_record?
0
                 self.#{model_sym}.save
...
16
17
18
 
 
 
 
19
20
21
...
16
17
18
19
20
21
22
23
24
25
0
@@ -16,6 +16,10 @@ class TestClassyInheritance < Test::Unit::TestCase
0
     assert ActiveRecord::Base.respond_to?(:depends_on)
0
   end
0
   
0
+  def test_user_should_respond_to_find_with_profile
0
+    assert User.respond_to?(:find_with_profile)
0
+  end
0
+
0
   def test_user_should_respond_to_first_name
0
     assert @user.respond_to?(:first_name)
0
   end
...
32
33
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
36
37
38
 
39
40
 
 
 
 
 
41
42
43
...
54
55
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
0
@@ -32,12 +32,65 @@ class SetupTestTables < ActiveRecord::Migration
0
 
0
       t.timestamps
0
     end
0
+
0
+    create_table :artists, :force => true do |t|
0
+      t.string :login
0
+      t.integer :profile_id
0
+
0
+      t.timestamps
0
+    end
0
+
0
+    create_table :addresses, :force => true do |t|
0
+      t.string :line_one
0
+      t.string :line_two
0
+      t.string :city
0
+      t.string :state_code
0
+      t.string :postal_code
0
+
0
+      t.timestamps
0
+    end
0
+
0
+    create_table :offices, :force => true do |t|
0
+      t.string :name
0
+      t.integer :billing_address_id
0
+      t.integer :shipping_address_id
0
+
0
+      t.timestamps
0
+    end
0
+
0
+    create_table :contents, :force => true do |t|
0
+      t.string :name
0
+      t.string :presentable_type 
0
+      t.integer :presentable_id
0
+
0
+      t.timestamps
0
+    end
0
+
0
+    create_table :pages, :force => true do |t|
0
+      t.text :body
0
+
0
+      t.timestamps
0
+    end
0
+
0
+    create_table :documents, :force => true do |t|
0
+      t.string :version_file_name
0
+      t.string :version_content_type
0
+      t.integer :version_file_size
0
+
0
+      t.timestamps
0
+    end
0
   end
0
   
0
   def self.down
0
     drop_table :authors
0
+    drop_table :artists
0
     drop_table :users
0
     drop_table :profiles
0
+    drop_table :offices
0
+    drop_table :addresses
0
+    drop_table :pages
0
+    drop_table :documents
0
+    drop_table :contents
0
   end
0
 end
0
 
0
@@ -54,3 +107,30 @@ end
0
 class Author < ActiveRecord::Base
0
   validates_presence_of :login
0
 end
0
+
0
+# to test optional dependency
0
+class Artist < ActiveRecord::Base
0
+  validates_presence_of :login
0
+end
0
+
0
+# to test using standard relationship options (class_name, etc..)
0
+class Address < ActiveRecord::Base
0
+  validates_presence_of :line_one, :city, :postal_code
0
+end
0
+
0
+class Office < ActiveRecord::Base
0
+  validates_presence_of :name
0
+end
0
+
0
+# Polymorphic classes
0
+class Content < ActiveRecord::Base
0
+  validates_presence_of :name
0
+end
0
+
0
+class Page < ActiveRecord::Base
0
+  validates_presence_of :body
0
+end
0
+
0
+# Would typically use PaperClip for this...
0
+class Document < ActiveRecord::Base
0
+end
...
1
2
3
4
 
 
5
6
 
 
 
 
 
7
8
 
9
10
11
...
32
33
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
36
...
1
2
3
 
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
0
@@ -1,11 +1,18 @@
0
 require File.dirname(__FILE__) + '/test_helper.rb'
0
 
0
 class TestWithOptionalDependency < Test::Unit::TestCase
0
-  Author.depends_on :profile, :required => false, 
0
+  # Turn off the validates_presence_of call
0
+  Author.depends_on :profile, :validates_presence_if => false, 
0
     :attrs => [:first_name, :last_name, :email]
0
   
0
+  # Turn off the validates_presence_of and the validates_associated calls
0
+  Artist.depends_on :profile, :validates_presence_if => false, 
0
+    :validates_associated_if => false,
0
+    :attrs => [:first_name, :last_name, :email]
0
+
0
   def setup
0
     @author = Author.new
0
+    @artist = Artist.new
0
   end
0
   
0
   def test_author_should_be_valid_without_profile
0
@@ -32,5 +39,21 @@ class TestWithOptionalDependency < Test::Unit::TestCase
0
     
0
     assert @author.valid?
0
   end
0
+
0
+  def test_artist_should_not_save_with_invalid_profile
0
+    @artist.login = 'joe'
0
+    @artist.first_name = 'joe'
0
+    
0
+    assert !@artist.save
0
+  end
0
+
0
+  def test_artist_should_save_with_valid_profile
0
+    @artist.login = 'joe'
0
+    @artist.first_name = 'joe'
0
+    @artist.last_name = 'bloggs'
0
+    @artist.email = 'joe@bloggs.co.uk'
0
+    
0
+    assert @artist.save
0
+  end
0
   
0
 end

Comments