public
Description: All the extra stuff you could want for the Mack Framework.
Homepage: http://www.mackframework.com
Clone URL: git://github.com/markbates/mack-more.git
Mack Data Factory [#14 state:resolved]
dsutedja (author)
Wed Jul 30 07:00:20 -0700 2008
commit  7c4fa2fa4bbb54aa24792c544e2a72cb47722ea7
tree    d4632acc5017f96db4d1d0eaf49ab566dbc27041
parent  13fd05b1694d921fb72e75647e91bf5e2606a5e0
...
16
17
18
19
20
21
22
...
24
25
26
27
28
29
30
...
61
62
63
64
 
65
66
67
...
82
83
84
85
86
87
88
...
97
98
99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
101
102
...
16
17
18
 
19
20
21
...
23
24
25
 
26
27
28
...
59
60
61
 
62
63
64
65
...
80
81
82
 
83
84
85
...
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
0
@@ -16,7 +16,6 @@ Let's say that I have 2 models: Item and User, and Item belongs to user.  So the
0
     class ItemFactory
0
         include Mack::Data::Factory
0
         
0
-        field :id, 10, :content => :numeric, :num_start => 0, :num_end => 100000
0
         field :title, "MyItem"
0
         field :owner_id, {:user => 'id'}
0
     end
0
@@ -24,7 +23,6 @@ Let's say that I have 2 models: Item and User, and Item belongs to user.  So the
0
     class UserFactory
0
         include Mack::Data::Factory
0
         
0
-        field :id, 10, :content => :numeric, :num_start => 10, :num_end => 100000
0
         field :username, "planters", :length => 25, :content => :alpha
0
         field :password, "roastedPeanuts", :immutable => true
0
     end
0
@@ -61,7 +59,7 @@ you want to create.
0
 Note that if your factory has dependencies to other model (like the ItemFactory in the example), then make sure you
0
 have created the model that it's depending on first.
0
 
0
-** Creating Factory Chains
0
+** Creating Factories Execution Chain
0
 In some instances, you may want to create an execution chain of a bunch of factories.  In the above example: the UserFactory
0
 has to be run before the ItemFactory.  
0
 If that's the case, you can create factory chain that you can execute later.
0
@@ -82,7 +80,6 @@ the following:
0
     class UserFactory
0
         include Mack::Data::Factory
0
     
0
-        field :id, 10, :content => :numeric, :num_start => 10, :num_end => 100000
0
         field :username, "planters", :length => 25, :content => :alpha
0
         field :password, "roastedPeanuts", :immutable => true
0
         
0
@@ -97,6 +94,23 @@ The above example defined a scoping for "long_username", which you can use by ca
0
 When a scope is defined and called, the field defined in the block will overwrite the default field listing 
0
 in that class.  Scopes in the factory is independent to each other, and one scope cannot affect the others.
0
 
0
+** Custom content generator
0
+In some cases, the default content generators that are provided by this framework don't fit your needs.
0
+To accommodate this situation, you can provide a custom content generator for each field you defined by 
0
+passing in a proc.  
0
+
0
+Example:
0
+I'm creating a users, but I don't want the username be totally random, instead I want it to use the default
0
+name I provide, and append 0-n at the end of the string to represent the Nth user in the list.  Here's how to
0
+accomplish that:
0
+    class UserFactory
0
+        include Mack::Data::Factory
0
+        
0
+        field :username, "planters" { |def_value, rules, index| "#{def_value}#{index}" }
0
+        field :password, "roastedPeanuts", :immutable => true
0
+        
0
+    end
0
+
0
 == Contact
0
 Please mail bugs, suggestions, and patches to darsono.sutedja@gmail.com
0
 
...
5
6
7
8
 
9
10
11
...
45
46
47
48
 
49
50
51
...
85
86
87
88
 
89
90
91
...
96
97
98
99
 
100
101
102
103
104
105
106
 
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
137
138
139
140
141
 
142
143
144
...
151
152
153
154
 
155
156
157
...
5
6
7
 
8
9
10
11
...
45
46
47
 
48
49
50
51
...
85
86
87
 
88
89
90
91
...
96
97
98
 
99
100
101
102
103
104
105
 
106
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
137
138
139
140
 
141
142
143
144
...
151
152
153
 
154
155
156
157
0
@@ -5,7 +5,7 @@ module Mack
0
       class FieldContentGenerator
0
         class << self
0
           def alpha_generator
0
-            @alpha_gen = Proc.new do |def_value, rules|
0
+            @alpha_gen = Proc.new do |def_value, rules, index|
0
               words = %w(alias consequatur aut perferendis sit voluptatem accusantium doloremque aperiam eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo aspernatur aut odit aut fugit sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt neque dolorem ipsum quia dolor sit amet consectetur adipisci velit sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem ut enim ad minima veniam quis nostrum exercitationem ullam corporis nemo enim ipsam voluptatem quia voluptas sit suscipit laboriosam nisi ut aliquid ex ea commodi consequatur quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae et iusto odio dignissimos ducimus qui blanditiis praesentium laudantium totam rem voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident sed ut perspiciatis unde omnis iste natus error similique sunt in culpa qui officia deserunt mollitia animi id est laborum et dolorum fuga et harum quidem rerum facilis est et expedita distinctio nam libero tempore cum soluta nobis est eligendi optio cumque nihil impedit quo porro quisquam est qui minus id quod maxime placeat facere possimus omnis voluptas assumenda est omnis dolor repellendus temporibus autem quibusdam et aut consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur at vero eos et accusamus officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae itaque earum rerum hic tenetur a sapiente delectus ut aut reiciendis voluptatibus maiores doloribus asperiores repellat)
0
 
0
               length = 128
0
@@ -45,7 +45,7 @@ module Mack
0
           end
0
 
0
           def alpha_numeric_generator
0
-            @alpha_numeric_gen = Proc.new do |def_value, rules|
0
+            @alpha_numeric_gen = Proc.new do |def_value, rules, index|
0
               words = %w(alias consequatur aut perferendis sit voluptatem accusantium doloremque aperiam eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo aspernatur aut odit aut fugit sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt neque dolorem ipsum quia dolor sit amet consectetur adipisci velit sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem ut enim ad minima veniam quis nostrum exercitationem ullam corporis nemo enim ipsam voluptatem quia voluptas sit suscipit laboriosam nisi ut aliquid ex ea commodi consequatur quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae et iusto odio dignissimos ducimus qui blanditiis praesentium laudantium totam rem voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident sed ut perspiciatis unde omnis iste natus error similique sunt in culpa qui officia deserunt mollitia animi id est laborum et dolorum fuga et harum quidem rerum facilis est et expedita distinctio nam libero tempore cum soluta nobis est eligendi optio cumque nihil impedit quo porro quisquam est qui minus id quod maxime placeat facere possimus omnis voluptas assumenda est omnis dolor repellendus temporibus autem quibusdam et aut consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur at vero eos et accusamus officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae itaque earum rerum hic tenetur a sapiente delectus ut aut reiciendis voluptatibus maiores doloribus asperiores repellat)
0
 
0
               length = 128
0
@@ -85,7 +85,7 @@ module Mack
0
           end
0
 
0
           def numeric_generator
0
-            @numeric_gen = Proc.new do |def_value, rules|
0
+            @numeric_gen = Proc.new do |def_value, rules, index|
0
               n_start = rules[:start_num] || 0
0
               n_end   = rules[:end_num] || 1000
0
 
0
@@ -96,49 +96,49 @@ module Mack
0
           end
0
 
0
           def date_generator
0
-            @date_gen = Proc.new do |def_value, rules|
0
+            @date_gen = Proc.new do |def_value, rules, index|
0
               Time.now.to_s
0
             end
0
             return @date_gen
0
           end
0
 
0
           def date_time_generator
0
-            @date_time_gen = Proc.new do |def_value, rules|
0
+            @date_time_gen = Proc.new do |def_value, rules, index|
0
               Time.now.to_s
0
             end
0
             return @date_time_gen
0
           end
0
 
0
           def email_generator
0
-            @email_gen = Proc.new do |def_value, rules|
0
+            @email_gen = Proc.new do |def_value, rules, index|
0
               Faker::Internet.free_email
0
             end
0
             return @email_gen
0
           end
0
 
0
           def firstname_generator
0
-            @fn_gen = Proc.new do |def_value, rules|
0
+            @fn_gen = Proc.new do |def_value, rules, index|
0
               Faker::Name.first_name
0
             end
0
             return @fn_gen
0
           end
0
 
0
           def lastname_generator
0
-            @ln_gen = Proc.new do |def_value, rules|
0
+            @ln_gen = Proc.new do |def_value, rules, index|
0
               Faker::Name.last_name
0
             end
0
             return @ln_gen
0
           end
0
 
0
           def phone_generator
0
-            @phone_gen = Proc.new do |def_value, rules|
0
+            @phone_gen = Proc.new do |def_value, rules, index|
0
               Faker::PhoneNumber.phone_number
0
             end
0
             return @phone_gen
0
           end
0
 
0
           def company_generator
0
-            @company_gen = Proc.new do |def_value, rules|
0
+            @company_gen = Proc.new do |def_value, rules, index|
0
               str = Faker::Company.name
0
 
0
               if rules[:include_bs]
0
@@ -151,7 +151,7 @@ module Mack
0
           end
0
 
0
           def name_generator
0
-            @name_gen = Proc.new do |def_value, rules|
0
+            @name_gen = Proc.new do |def_value, rules, index|
0
               Faker::Name.name
0
             end
0
             return @name_gen
...
1
2
 
 
 
 
 
 
 
 
 
 
 
 
3
4
5
...
9
10
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
13
 
 
14
15
16
 
 
17
18
19
20
 
21
22
23
24
25
 
26
27
28
...
34
35
36
 
 
 
 
37
38
39
40
 
 
 
 
41
42
43
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
21
22
23
24
25
26
27
28
29
30
31
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
...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
0
@@ -1,5 +1,17 @@
0
 module Mack
0
   module Data
0
+    #
0
+    # Add factory capability to a class.
0
+    # 
0
+    # A factory is able to define which field it want to generate content for,
0
+    # define a scope for different situation, and set a custom content generator 
0
+    # for field that doesn't want to use the default content generator.
0
+    #
0
+    # For more information and usage, please read README file
0
+    #
0
+    # author: Darsono Sutedja
0
+    # July 2008
0
+    #
0
     module Factory      
0
       
0
       # make sure the data factory API is available to the class that includes it
0
@@ -9,20 +21,39 @@ module Mack
0
       
0
       module ClassMethods
0
         
0
+        #
0
+        # Run the factory to produce n number of objects.
0
+        #
0
+        # Example:
0
+        # class CarFactory
0
+        #    include Mack::Data::Factory
0
+        #    field :name, "honda" { |def_value, rules, index| "#{def_value} #{['civic', 'accord', 'pilot'].randomize[0]}"}
0
+        # end
0
+        #
0
+        # CarFactory.create(100) #=> will produce 100 cars whose name is "honda xxx" where xxx is a random item from ['civic', 'accord', 'pilot']
0
+        #
0
+        # params:
0
+        # * num - how many objects to produce
0
+        # * scope - run the factory in a named scope
0
+        #
0
         def create(num, scope = :default)
0
           factory_name = self.name.underscore
0
+          
0
+          # retrieve the model name from the factory class. 
0
           model_name = factory_name.gsub('_factory', '')
0
-          #puts "creating #{num} instances of #{model_name.camelcase}"
0
           
0
+          # if user is running custom scope, then merge the fields 
0
+          # defined for that scope with the default one, before we run the factory
0
           scoped_fields = field_manager.scopes[scope]
0
           fields = field_manager.scopes[:default].merge(scoped_fields)
0
           
0
           num.times do |i|
0
+            #puts "Creating #{model_name} ##{i+1}"
0
             obj = model_name.camelcase.constantize.new
0
             
0
             fields.each_pair do |k, v|
0
               field_name = k.to_s
0
-              field_value = v.get_value
0
+              field_value = v.get_value(i)
0
               assert_method(obj, "#{field_name}=", "#{model_name.camelcase} doesn't have #{field_name}= method!") do
0
                 obj.send("#{field_name}=", field_value)
0
               end
0
@@ -34,10 +65,18 @@ module Mack
0
           end
0
         end
0
         
0
+        #
0
+        # Define a field with its default value and rules and an optional content generator
0
+        # for this factory
0
+        #
0
         def field(model_attrib_sym, default_value, options = {}, &block)
0
           field_manager.add(scope, model_attrib_sym, default_value, options, &block)
0
         end
0
         
0
+        # 
0
+        # Define a scope in the factory.
0
+        # Any field defined in a scope will overwrite its cousin in the default scope.
0
+        #
0
         def scope_for(tag)
0
           set_scope(tag)
0
           yield
...
31
32
33
34
 
35
36
37
...
43
44
45
46
47
48
 
 
49
50
51
52
53
54
55
 
56
57
58
...
31
32
33
 
34
35
36
37
...
43
44
45
 
 
 
46
47
48
49
50
51
52
53
 
54
55
56
57
0
@@ -31,7 +31,7 @@ module Mack
0
         self.field_value_producer = Mack::Data::Factory::FieldContentGenerator.send("#{field_rules[:content]}_generator")
0
       end
0
       
0
-      def get_value
0
+      def get_value(index = 0)
0
         # return the field_value immediately if the rule states that it's immutable
0
         return field_value if field_rules[:immutable]
0
         
0
@@ -43,16 +43,15 @@ module Mack
0
           begin
0
             owner_model = owner.to_s.camelcase.constantize
0
             bridge = Mack::Data::Bridge.new
0
-            self.field_value = (bridge.get(owner_model, rand(bridge.count(owner_model)))).send(key)
0
-            return self.field_value
0
-            #self.field_value = owner_model.get(rand(owner_model.count)).send(key)
0
+            value = bridge.get_first(owner_model).send(key)
0
+            return value
0
           rescue Exception
0
             Mack.logger.warn "WARNING: DataFactory: field_value for #{field_name} is not set properly because data relationship defined is not correct"
0
           end
0
         end
0
         
0
         # must generate random string and also respect the rules
0
-        field_value_producer.call(field_value, field_rules)
0
+        field_value_producer.call(field_value, field_rules, index)
0
       end
0
     end
0
   end
...
15
16
17
 
 
 
 
18
19
20
...
15
16
17
18
19
20
21
22
23
24
0
@@ -15,6 +15,10 @@ module Mack
0
         handler(obj).get(obj, *args)
0
       end
0
       
0
+      def get_first(obj, *args)
0
+        handler(obj).get_first(obj, *args)
0
+      end
0
+      
0
       def count(obj, *args)
0
         handler(obj).count(obj, *args)
0
       end
...
5
6
7
8
 
9
10
11
...
20
21
22
 
 
 
 
23
24
25
...
5
6
7
 
8
9
10
11
...
20
21
22
23
24
25
26
27
28
29
0
@@ -5,7 +5,7 @@ module Mack
0
         
0
         def can_handle(obj)
0
           return false if !Object.const_defined?('ActiveRecord')
0
-          return obj.is_a?(::ActiveRecord::Base)
0
+          return obj.ancestors.include?(::ActiveRecord::Base)
0
         end
0
         
0
         def get(obj, *args)
0
@@ -20,6 +20,10 @@ module Mack
0
           obj.save
0
         end
0
         
0
+        def get_first(obj, *args)
0
+          obj.find(:first, *args)
0
+        end
0
+        
0
       end
0
     end
0
   end
...
5
6
7
8
 
9
10
11
...
20
21
22
 
 
 
 
23
24
25
...
5
6
7
 
8
9
10
11
...
20
21
22
23
24
25
26
27
28
29
0
@@ -5,7 +5,7 @@ module Mack
0
         
0
         def can_handle(obj)
0
           return false if !Object.const_defined?('DataMapper')
0
-          return obj.is_a?(::DataMapper::Resource)
0
+          return obj.ancestors.include?(::DataMapper::Resource)
0
         end
0
         
0
         def get(obj, *args)
0
@@ -20,6 +20,10 @@ module Mack
0
           obj.save
0
         end
0
         
0
+        def get_first(obj, *args)
0
+          obj.first(*args)
0
+        end
0
+        
0
       end
0
     end
0
   end
...
19
20
21
 
 
 
 
 
22
23
24
...
19
20
21
22
23
24
25
26
27
28
29
0
@@ -19,6 +19,11 @@ module Mack
0
           Mack.logger.warn "Mack::Data::OrmBridge: You don't have supported orm api handler installed."
0
         end
0
         
0
+        def get_first(obj, *args)
0
+          Mack.logger.warn "Mack::Data::OrmBridge: You don't have supported orm api handler installed."
0
+        end
0
+        
0
+        
0
       end
0
     end
0
   end

Comments