object_daddy 0.4.1 → 0.4.3
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.
- data/README.markdown +1 -1
- data/VERSION.yml +1 -1
- data/lib/object_daddy.rb +45 -30
- data/spec/object_daddy_spec.rb +74 -28
- data/spec/resources/schema +5 -0
- metadata +2 -3
- data/lib/object_daddy_flymake.rb +0 -239
data/README.markdown
CHANGED
data/VERSION.yml
CHANGED
data/lib/object_daddy.rb
CHANGED
@@ -3,20 +3,20 @@ module ObjectDaddy
|
|
3
3
|
def self.included(klass)
|
4
4
|
klass.extend ClassMethods
|
5
5
|
if defined? ActiveRecord and klass < ActiveRecord::Base
|
6
|
-
klass.extend RailsClassMethods
|
7
|
-
|
6
|
+
klass.extend RailsClassMethods
|
7
|
+
|
8
8
|
class << klass
|
9
9
|
alias_method :validates_presence_of_without_object_daddy, :validates_presence_of
|
10
10
|
alias_method :validates_presence_of, :validates_presence_of_with_object_daddy
|
11
|
-
end
|
11
|
+
end
|
12
12
|
end
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
module ClassMethods
|
16
16
|
attr_accessor :exemplars_generated, :exemplar_path, :generators
|
17
17
|
attr_reader :presence_validated_attributes
|
18
18
|
protected :exemplars_generated=
|
19
|
-
|
19
|
+
|
20
20
|
# :call-seq:
|
21
21
|
# spawn()
|
22
22
|
# spawn() do |obj| ... end
|
@@ -33,7 +33,10 @@ module ObjectDaddy
|
|
33
33
|
: const_get(@concrete_subclass_name).spawn(args)
|
34
34
|
end
|
35
35
|
generate_values(args)
|
36
|
-
instance = new
|
36
|
+
instance = new
|
37
|
+
args.each_pair do |attribute, value|
|
38
|
+
instance.send("#{attribute}=", value) # support setting of mass-assignment protected attributes
|
39
|
+
end
|
37
40
|
yield instance if block_given?
|
38
41
|
instance
|
39
42
|
end
|
@@ -52,9 +55,9 @@ module ObjectDaddy
|
|
52
55
|
handle = gen_data.keys.first
|
53
56
|
args = gen_data[handle]
|
54
57
|
end
|
55
|
-
|
58
|
+
|
56
59
|
raise ArgumentError, "an attribute name must be specified" unless handle = handle.to_sym
|
57
|
-
|
60
|
+
|
58
61
|
unless args.is_a?(Hash)
|
59
62
|
unless block
|
60
63
|
retval = args
|
@@ -62,11 +65,11 @@ module ObjectDaddy
|
|
62
65
|
end
|
63
66
|
args = {} # args is assumed to be a hash for the rest of the method
|
64
67
|
end
|
65
|
-
|
68
|
+
|
66
69
|
if args[:start]
|
67
70
|
block ||= lambda { |prev| prev.succ }
|
68
71
|
end
|
69
|
-
|
72
|
+
|
70
73
|
if args[:method]
|
71
74
|
h = { :method => args[:method].to_sym }
|
72
75
|
h[:start] = args[:start] if args[:start]
|
@@ -87,21 +90,24 @@ module ObjectDaddy
|
|
87
90
|
def generates_subclass(subclass_name)
|
88
91
|
@concrete_subclass_name = subclass_name.to_s
|
89
92
|
end
|
90
|
-
|
93
|
+
|
91
94
|
def gather_exemplars
|
92
95
|
return if exemplars_generated
|
96
|
+
|
97
|
+
self.generators ||= {}
|
93
98
|
if superclass.respond_to?(:gather_exemplars)
|
94
99
|
superclass.gather_exemplars
|
95
|
-
self.generators = (superclass.generators
|
100
|
+
self.generators = (superclass.generators).merge(generators).dup
|
96
101
|
end
|
97
102
|
|
98
|
-
|
103
|
+
exemplar_path.each do |raw_path|
|
99
104
|
path = File.join(raw_path, "#{underscore(name)}_exemplar.rb")
|
100
105
|
load(path) if File.exists?(path)
|
101
106
|
end
|
107
|
+
|
102
108
|
self.exemplars_generated = true
|
103
109
|
end
|
104
|
-
|
110
|
+
|
105
111
|
def presence_validated_attributes
|
106
112
|
@presence_validated_attributes ||= {}
|
107
113
|
attrs = @presence_validated_attributes
|
@@ -110,25 +116,26 @@ module ObjectDaddy
|
|
110
116
|
end
|
111
117
|
attrs
|
112
118
|
end
|
113
|
-
|
119
|
+
|
114
120
|
protected
|
115
|
-
|
121
|
+
|
116
122
|
# we define an underscore helper ourselves since the ActiveSupport isn't available if we're not using Rails
|
117
123
|
def underscore(string)
|
118
124
|
string.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
119
125
|
end
|
120
|
-
|
126
|
+
|
121
127
|
def record_generator_for(handle, generator)
|
122
128
|
self.generators ||= {}
|
123
129
|
raise ArgumentError, "a generator for attribute [:#{handle}] has already been specified" if (generators[handle] || {})[:source] == self
|
124
130
|
generators[handle] = { :generator => generator, :source => self }
|
125
131
|
end
|
126
|
-
|
132
|
+
|
127
133
|
private
|
128
|
-
|
134
|
+
|
129
135
|
def generate_values(args)
|
130
136
|
(generators || {}).each_pair do |handle, gen_data|
|
131
137
|
next if args.include?(handle) or args.include?(handle.to_s)
|
138
|
+
|
132
139
|
generator = gen_data[:generator]
|
133
140
|
if generator[:block]
|
134
141
|
process_generated_value(args, handle, generator, generator[:block])
|
@@ -143,25 +150,29 @@ module ObjectDaddy
|
|
143
150
|
args[handle] = generator[:class].next
|
144
151
|
end
|
145
152
|
end
|
146
|
-
|
153
|
+
|
147
154
|
generate_missing(args)
|
148
155
|
end
|
149
|
-
|
156
|
+
|
150
157
|
def process_generated_value(args, handle, generator, block)
|
151
158
|
if generator[:start]
|
152
159
|
value = generator[:start]
|
153
160
|
generator.delete(:start)
|
154
161
|
else
|
155
|
-
|
162
|
+
if block.arity == 0
|
163
|
+
value = block.call
|
164
|
+
else
|
165
|
+
value = block.call(generator[:prev])
|
166
|
+
end
|
156
167
|
end
|
157
168
|
generator[:prev] = args[handle] = value
|
158
169
|
end
|
159
|
-
|
170
|
+
|
160
171
|
def generate_missing(args)
|
161
172
|
if presence_validated_attributes and !presence_validated_attributes.empty?
|
162
173
|
req = {}
|
163
174
|
(presence_validated_attributes.keys - args.keys).each {|a| req[a.to_s] = true } # find attributes required by validates_presence_of not already set
|
164
|
-
|
175
|
+
|
165
176
|
belongs_to_associations = reflect_on_all_associations(:belongs_to).to_a
|
166
177
|
missing = belongs_to_associations.select { |a| req[a.name.to_s] or req[a.primary_key_name.to_s] }
|
167
178
|
if create_scope = scope(:create)
|
@@ -172,13 +183,17 @@ module ObjectDaddy
|
|
172
183
|
end
|
173
184
|
end
|
174
185
|
end
|
175
|
-
|
186
|
+
|
176
187
|
module RailsClassMethods
|
177
188
|
def exemplar_path
|
178
|
-
|
179
|
-
|
189
|
+
paths = ['spec', 'test'].inject([]) do |array, dir|
|
190
|
+
if File.directory?(File.join(RAILS_ROOT, dir))
|
191
|
+
array << File.join(RAILS_ROOT, dir, 'exemplars')
|
192
|
+
end
|
193
|
+
array
|
194
|
+
end
|
180
195
|
end
|
181
|
-
|
196
|
+
|
182
197
|
def validates_presence_of_with_object_daddy(*attr_names)
|
183
198
|
@presence_validated_attributes ||= {}
|
184
199
|
new_attr = attr_names.dup
|
@@ -186,7 +201,7 @@ module ObjectDaddy
|
|
186
201
|
new_attr.each {|a| @presence_validated_attributes[a] = true }
|
187
202
|
validates_presence_of_without_object_daddy(*attr_names)
|
188
203
|
end
|
189
|
-
|
204
|
+
|
190
205
|
# :call-seq:
|
191
206
|
# generate()
|
192
207
|
# generate() do |obj| ... end
|
@@ -204,7 +219,7 @@ module ObjectDaddy
|
|
204
219
|
yield instance if block_given?
|
205
220
|
end
|
206
221
|
end
|
207
|
-
|
222
|
+
|
208
223
|
# :call-seq:
|
209
224
|
# generate()
|
210
225
|
# generate() do |obj| ... end
|
data/spec/object_daddy_spec.rb
CHANGED
@@ -157,7 +157,7 @@ describe ObjectDaddy, 'when registering exemplars' do
|
|
157
157
|
before :each do
|
158
158
|
@class = Class.new(OpenStruct)
|
159
159
|
@class.send(:include, ObjectDaddy)
|
160
|
-
@file_path = File.join(File.dirname(__FILE__), 'tmp')
|
160
|
+
@file_path = [File.join(File.dirname(__FILE__), 'tmp')]
|
161
161
|
@file_name = File.join(@file_path, 'widget_exemplar.rb')
|
162
162
|
@class.stubs(:exemplar_path).returns(@file_path)
|
163
163
|
@class.stubs(:name).returns('Widget')
|
@@ -506,7 +506,7 @@ describe ObjectDaddy, "when spawning a class instance" do
|
|
506
506
|
SubWidget.stubs(:exemplar_path).returns(@subfile_path)
|
507
507
|
|
508
508
|
File.open(@file_name, 'w') do |f|
|
509
|
-
f.puts "class Widget\ngenerator_for :blah do |prev| 'blah'; end\nend\n"
|
509
|
+
f.puts "class Widget\ngenerator_for :blah do |prev| 'blah'; end\ngenerator_for :other do |prev| 'bang'; end\nend\n"
|
510
510
|
end
|
511
511
|
end
|
512
512
|
|
@@ -516,35 +516,48 @@ describe ObjectDaddy, "when spawning a class instance" do
|
|
516
516
|
end
|
517
517
|
|
518
518
|
it 'should use generators from the parent class' do
|
519
|
-
SubWidget.spawn.
|
519
|
+
SubWidget.spawn.other.should == 'bang'
|
520
|
+
SubWidget.spawn.blah.should == 'blah'
|
520
521
|
end
|
521
522
|
|
522
|
-
|
523
|
-
|
524
|
-
|
523
|
+
describe 'with subclass generators' do
|
524
|
+
before :each do
|
525
|
+
File.open(@subfile_name, 'w') do |f|
|
526
|
+
f.puts "class SubWidget\ngenerator_for :blah do |prev| 'blip'; end\nend\n"
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
it 'should still use generators from the parent class' do
|
531
|
+
SubWidget.spawn.other.should == 'bang'
|
532
|
+
end
|
533
|
+
|
534
|
+
it 'should allow overriding parent generators' do
|
535
|
+
SubWidget.spawn.blah.should == 'blip'
|
525
536
|
end
|
526
|
-
SubWidget.spawn.blah.should == 'blip'
|
527
537
|
end
|
528
538
|
end
|
529
|
-
|
539
|
+
|
530
540
|
describe 'using generators called directly' do
|
541
|
+
before :each do
|
542
|
+
@class.generator_for :other do |prev| 'bang'; end
|
543
|
+
@class.generator_for :blah do |prev| 'blah'; end
|
544
|
+
end
|
545
|
+
|
531
546
|
it 'should use generators from the parent class' do
|
532
|
-
@
|
533
|
-
@subclass.spawn.blah.should
|
547
|
+
@subclass.spawn.other.should == 'bang'
|
548
|
+
@subclass.spawn.blah.should == 'blah'
|
534
549
|
end
|
535
550
|
|
536
|
-
|
537
|
-
|
538
|
-
@class.generator_for :blah do |prev| 'blah'; end
|
539
|
-
# p @class
|
540
|
-
# p @subclass
|
541
|
-
# @subclass.send(:gather_exemplars)
|
542
|
-
# p @subclass.generators
|
551
|
+
describe 'with subclass generators' do
|
552
|
+
before :each do
|
543
553
|
@subclass.generator_for :blah do |prev| 'blip'; end
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
554
|
+
end
|
555
|
+
|
556
|
+
it 'should still use generators from the parent class' do
|
557
|
+
@subclass.spawn.other.should == 'bang'
|
558
|
+
end
|
559
|
+
|
560
|
+
it 'should allow overriding parent generators' do
|
548
561
|
@subclass.spawn.blah.should == 'blip'
|
549
562
|
end
|
550
563
|
end
|
@@ -593,6 +606,10 @@ if File.exists?("#{File.dirname(__FILE__)}/../../../../config/environment.rb")
|
|
593
606
|
class YaModel < ActiveRecord::Base
|
594
607
|
end
|
595
608
|
|
609
|
+
class ProtectedAttribute < ActiveRecord::Base
|
610
|
+
attr_accessible :public_name
|
611
|
+
end
|
612
|
+
|
596
613
|
describe ObjectDaddy, "when integrated with Rails" do
|
597
614
|
it "should provide a means of generating and saving a class instance" do
|
598
615
|
Frobnitz.should respond_to(:generate)
|
@@ -639,28 +656,43 @@ if File.exists?("#{File.dirname(__FILE__)}/../../../../config/environment.rb")
|
|
639
656
|
describe 'giving an exemplar path for an ActiveRecord model' do
|
640
657
|
it 'should check if a spec directory exists' do
|
641
658
|
File.expects(:directory?).with(File.join(RAILS_ROOT, 'spec'))
|
642
|
-
|
659
|
+
File.expects(:directory?).with(File.join(RAILS_ROOT, 'test'))
|
660
|
+
Frobnitz.exemplar_path.should == []
|
643
661
|
end
|
644
662
|
|
645
663
|
describe 'if a spec directory exists' do
|
646
664
|
before :each do
|
647
|
-
File.
|
665
|
+
File.expects(:directory?).with(File.join(RAILS_ROOT, 'spec')).returns(true)
|
666
|
+
File.expects(:directory?).with(File.join(RAILS_ROOT, 'test')).returns(false)
|
648
667
|
end
|
649
668
|
|
650
|
-
it 'should
|
651
|
-
Frobnitz.exemplar_path.should == File.join(RAILS_ROOT, 'spec', 'exemplars')
|
669
|
+
it 'should return the spec directory string in an array' do
|
670
|
+
Frobnitz.exemplar_path.should == [File.join(RAILS_ROOT, 'spec', 'exemplars')]
|
652
671
|
end
|
653
672
|
end
|
654
673
|
|
655
674
|
describe 'if a spec directory does not exist' do
|
656
675
|
before :each do
|
657
|
-
File.
|
676
|
+
File.expects(:directory?).with(File.join(RAILS_ROOT, 'spec')).returns(false)
|
677
|
+
File.expects(:directory?).with(File.join(RAILS_ROOT, 'test')).returns(true)
|
678
|
+
end
|
679
|
+
|
680
|
+
it 'should return the test directory string in an array' do
|
681
|
+
Frobnitz.exemplar_path.should == [File.join(RAILS_ROOT, 'test', 'exemplars')]
|
682
|
+
end
|
683
|
+
end
|
684
|
+
|
685
|
+
describe 'if both directories exist' do
|
686
|
+
before :each do
|
687
|
+
File.expects(:directory?).with(File.join(RAILS_ROOT, 'spec')).returns(true)
|
688
|
+
File.expects(:directory?).with(File.join(RAILS_ROOT, 'test')).returns(true)
|
658
689
|
end
|
659
690
|
|
660
|
-
it 'should
|
661
|
-
Frobnitz.exemplar_path.should == File.join(RAILS_ROOT, 'test', 'exemplars')
|
691
|
+
it 'should return both directory strings in an array' do
|
692
|
+
Frobnitz.exemplar_path.should == [ File.join(RAILS_ROOT, 'spec', 'exemplars'), File.join(RAILS_ROOT, 'test', 'exemplars')]
|
662
693
|
end
|
663
694
|
end
|
695
|
+
|
664
696
|
end
|
665
697
|
|
666
698
|
describe 'when an association is required by name' do
|
@@ -844,5 +876,19 @@ if File.exists?("#{File.dirname(__FILE__)}/../../../../config/environment.rb")
|
|
844
876
|
Frobnitz.generator_for :name => 'thing'
|
845
877
|
Frobnitz.generate('name' => 'boo').name.should == 'boo'
|
846
878
|
end
|
879
|
+
|
880
|
+
describe "supporting mass-assignment protected attributes" do
|
881
|
+
it "should allow setting a value for a non-protected attribute" do
|
882
|
+
ProtectedAttribute.generate!(:public_name => 'no_worries').public_name.should == 'no_worries'
|
883
|
+
end
|
884
|
+
|
885
|
+
it "should have a protected attribute, which is not set when using regular create!" do
|
886
|
+
ProtectedAttribute.create!(:private_name => 'protected name').private_name.should == nil
|
887
|
+
end
|
888
|
+
|
889
|
+
it "should allow setting a value for a protected attribute" do
|
890
|
+
ProtectedAttribute.generate!(:private_name => 'protected name').private_name.should == 'protected name'
|
891
|
+
end
|
892
|
+
end
|
847
893
|
end
|
848
894
|
end
|
data/spec/resources/schema
CHANGED
@@ -27,4 +27,9 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
27
27
|
create_table :ya_models, :force => true do |t|
|
28
28
|
t.column :name, :string
|
29
29
|
end
|
30
|
+
|
31
|
+
create_table :protected_attributes, :force => true do |t|
|
32
|
+
t.column :public_name, :string
|
33
|
+
t.column :private_name, :string
|
34
|
+
end
|
30
35
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: object_daddy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rick Bradley
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2010-
|
13
|
+
date: 2010-02-28 00:00:00 -03:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -30,7 +30,6 @@ files:
|
|
30
30
|
- init.rb
|
31
31
|
- install.rb
|
32
32
|
- lib/object_daddy.rb
|
33
|
-
- lib/object_daddy_flymake.rb
|
34
33
|
- rails/init.rb
|
35
34
|
- spec/install_spec.rb
|
36
35
|
- spec/object_daddy_spec.rb
|
data/lib/object_daddy_flymake.rb
DELETED
@@ -1,239 +0,0 @@
|
|
1
|
-
module ObjectDaddy
|
2
|
-
|
3
|
-
def self.included(klass)
|
4
|
-
klass.extend ClassMethods
|
5
|
-
if defined? ActiveRecord and klass < ActiveRecord::Base
|
6
|
-
klass.extend RailsClassMethods
|
7
|
-
|
8
|
-
class << klass
|
9
|
-
alias_method :validates_presence_of_without_object_daddy, :validates_presence_of
|
10
|
-
alias_method :validates_presence_of, :validates_presence_of_with_object_daddy
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
module ClassMethods
|
16
|
-
attr_accessor :exemplars_generated, :exemplar_path, :generators
|
17
|
-
attr_reader :presence_validated_attributes
|
18
|
-
protected :exemplars_generated=
|
19
|
-
|
20
|
-
# :call-seq:
|
21
|
-
# spawn()
|
22
|
-
# spawn() do |obj| ... end
|
23
|
-
# spawn(args)
|
24
|
-
# spawn(args) do |obj| ... end
|
25
|
-
#
|
26
|
-
# Creates a valid instance of this class, using any known generators. The
|
27
|
-
# generated instance is yielded to a block if provided.
|
28
|
-
def spawn(args = {})
|
29
|
-
gather_exemplars
|
30
|
-
if @concrete_subclass_name
|
31
|
-
return block_given? \
|
32
|
-
? const_get(@concrete_subclass_name).spawn(args) {|instance| yield instance} \
|
33
|
-
: const_get(@concrete_subclass_name).spawn(args)
|
34
|
-
end
|
35
|
-
generate_values(args)
|
36
|
-
instance = new(args)
|
37
|
-
yield instance if block_given?
|
38
|
-
instance
|
39
|
-
end
|
40
|
-
|
41
|
-
# register a generator for an attribute of this class
|
42
|
-
# generator_for :foo do |prev| ... end
|
43
|
-
# generator_for :foo do ... end
|
44
|
-
# generator_for :foo, value
|
45
|
-
# generator_for :foo => value
|
46
|
-
# generator_for :foo, :class => GeneratorClass
|
47
|
-
# generator_for :foo, :method => :method_name
|
48
|
-
def generator_for(handle, args = {}, &block)
|
49
|
-
if handle.is_a?(Hash)
|
50
|
-
raise ArgumentError, "only specify one attr => value pair at a time" unless handle.keys.length == 1
|
51
|
-
gen_data = handle
|
52
|
-
handle = gen_data.keys.first
|
53
|
-
args = gen_data[handle]
|
54
|
-
end
|
55
|
-
|
56
|
-
raise ArgumentError, "an attribute name must be specified" unless handle = handle.to_sym
|
57
|
-
|
58
|
-
unless args.is_a?(Hash)
|
59
|
-
unless block
|
60
|
-
retval = args
|
61
|
-
block = lambda { retval } # lambda { args } results in returning the empty hash that args gets changed to
|
62
|
-
end
|
63
|
-
args = {} # args is assumed to be a hash for the rest of the method
|
64
|
-
end
|
65
|
-
|
66
|
-
if args[:start]
|
67
|
-
block ||= lambda { |prev| prev.succ }
|
68
|
-
end
|
69
|
-
|
70
|
-
if args[:method]
|
71
|
-
h = { :method => args[:method].to_sym }
|
72
|
-
h[:start] = args[:start] if args[:start]
|
73
|
-
record_generator_for(handle, h)
|
74
|
-
elsif args[:class]
|
75
|
-
raise ArgumentError, "generator class [#{args[:class].name}] does not have a :next method" unless args[:class].respond_to?(:next)
|
76
|
-
record_generator_for(handle, :class => args[:class])
|
77
|
-
elsif block
|
78
|
-
raise ArgumentError, "generator block must take an optional single argument" unless (-1..1).include?(block.arity) # NOTE: lambda {} has an arity of -1, while lambda {||} has an arity of 0
|
79
|
-
h = { :block => block }
|
80
|
-
h[:start] = args[:start] if args[:start]
|
81
|
-
record_generator_for(handle, h)
|
82
|
-
else
|
83
|
-
raise ArgumentError, "a block, :class generator, :method generator, or value must be specified to generator_for"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def generates_subclass(subclass_name)
|
88
|
-
@concrete_subclass_name = subclass_name.to_s
|
89
|
-
end
|
90
|
-
|
91
|
-
def gather_exemplars
|
92
|
-
return if exemplars_generated
|
93
|
-
if superclass.respond_to?(:gather_exemplars)
|
94
|
-
superclass.gather_exemplars
|
95
|
-
self.generators = (superclass.generators || {}).dup
|
96
|
-
end
|
97
|
-
|
98
|
-
[*exemplar_path].each do |raw_path|
|
99
|
-
path = File.join(raw_path, "#{underscore(name)}_exemplar.rb")
|
100
|
-
load(path) if File.exists?(path)
|
101
|
-
end
|
102
|
-
self.exemplars_generated = true
|
103
|
-
end
|
104
|
-
|
105
|
-
def presence_validated_attributes
|
106
|
-
@presence_validated_attributes ||= {}
|
107
|
-
attrs = @presence_validated_attributes
|
108
|
-
if superclass.respond_to?(:presence_validated_attributes)
|
109
|
-
attrs = superclass.presence_validated_attributes.merge(attrs)
|
110
|
-
end
|
111
|
-
attrs
|
112
|
-
end
|
113
|
-
|
114
|
-
protected
|
115
|
-
|
116
|
-
# we define an underscore helper ourselves since the ActiveSupport isn't available if we're not using Rails
|
117
|
-
def underscore(string)
|
118
|
-
string.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
119
|
-
end
|
120
|
-
|
121
|
-
def record_generator_for(handle, generator)
|
122
|
-
self.generators ||= {}
|
123
|
-
raise ArgumentError, "a generator for attribute [:#{handle}] has already been specified" if (generators[handle] || {})[:source] == self
|
124
|
-
generators[handle] = { :generator => generator, :source => self }
|
125
|
-
end
|
126
|
-
|
127
|
-
private
|
128
|
-
|
129
|
-
def generate_values(args)
|
130
|
-
(generators || {}).each_pair do |handle, gen_data|
|
131
|
-
next if args.include?(handle) or args.include?(handle.to_s)
|
132
|
-
generator = gen_data[:generator]
|
133
|
-
if generator[:block]
|
134
|
-
process_generated_value(args, handle, generator, generator[:block])
|
135
|
-
elsif generator[:method]
|
136
|
-
method = method(generator[:method])
|
137
|
-
if method.arity == 1
|
138
|
-
process_generated_value(args, handle, generator, method)
|
139
|
-
else
|
140
|
-
args[handle] = method.call
|
141
|
-
end
|
142
|
-
elsif generator[:class]
|
143
|
-
args[handle] = generator[:class].next
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
generate_missing(args)
|
148
|
-
end
|
149
|
-
|
150
|
-
def process_generated_value(args, handle, generator, block)
|
151
|
-
if generator[:start]
|
152
|
-
value = generator[:start]
|
153
|
-
generator.delete(:start)
|
154
|
-
else
|
155
|
-
value = block.call(generator[:prev])
|
156
|
-
end
|
157
|
-
generator[:prev] = args[handle] = value
|
158
|
-
end
|
159
|
-
|
160
|
-
def generate_missing(args)
|
161
|
-
if presence_validated_attributes and !presence_validated_attributes.empty?
|
162
|
-
req = {}
|
163
|
-
(presence_validated_attributes.keys - args.keys).each {|a| req[a.to_s] = true } # find attributes required by validates_presence_of not already set
|
164
|
-
|
165
|
-
belongs_to_associations = reflect_on_all_associations(:belongs_to).to_a
|
166
|
-
missing = belongs_to_associations.select { |a| req[a.name.to_s] or req[a.primary_key_name.to_s] }
|
167
|
-
if create_scope = scope(:create)
|
168
|
-
missing.reject! { |a| create_scope.include?(a.primary_key_name) }
|
169
|
-
end
|
170
|
-
missing.reject! { |a| [a.name, a.primary_key_name].any? { |n| args.stringify_keys.include?(n.to_s) } }
|
171
|
-
missing.each {|a| args[a.name] = a.class_name.constantize.generate }
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
module RailsClassMethods
|
177
|
-
def exemplar_path
|
178
|
-
dir = File.directory?(File.join(RAILS_ROOT, 'spec')) ? 'spec' : 'test'
|
179
|
-
File.join(RAILS_ROOT, dir, 'exemplars')
|
180
|
-
end
|
181
|
-
|
182
|
-
def validates_presence_of_with_object_daddy(*attr_names)
|
183
|
-
@presence_validated_attributes ||= {}
|
184
|
-
new_attr = attr_names.dup
|
185
|
-
new_attr.pop if new_attr.last.is_a?(Hash)
|
186
|
-
new_attr.each {|a| @presence_validated_attributes[a] = true }
|
187
|
-
validates_presence_of_without_object_daddy(*attr_names)
|
188
|
-
end
|
189
|
-
|
190
|
-
# :call-seq:
|
191
|
-
# generate()
|
192
|
-
# generate() do |obj| ... end
|
193
|
-
# generate(args)
|
194
|
-
# generate(args) do |obj| ... end
|
195
|
-
#
|
196
|
-
# Creates and tries to save an instance of this class, using any known
|
197
|
-
# generators. The generated instance is yielded to a block if provided.
|
198
|
-
#
|
199
|
-
# This will not raise errors on a failed save. Use generate! if you
|
200
|
-
# want errors raised.
|
201
|
-
def generate(args = {})
|
202
|
-
spawn(args) do |instance|
|
203
|
-
instance.save
|
204
|
-
yield instance if block_given?
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
# :call-seq:
|
209
|
-
# generate()
|
210
|
-
# generate() do |obj| ... end
|
211
|
-
# generate(args)
|
212
|
-
# generate(args) do |obj| ... end
|
213
|
-
#
|
214
|
-
# Creates and tries to save! an instance of this class, using any known
|
215
|
-
# generators. The generated instance is yielded to a block if provided.
|
216
|
-
#
|
217
|
-
# This will raise errors on a failed save. Use generate if you do not want
|
218
|
-
# errors raised.
|
219
|
-
def generate!(args = {})
|
220
|
-
spawn(args) do |instance|
|
221
|
-
instance.save!
|
222
|
-
yield instance if block_given?
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
unless ActiveRecord::Base.respond_to? :inherited_with_object_daddy
|
229
|
-
class ActiveRecord::Base
|
230
|
-
def self.inherited_with_object_daddy(subclass)
|
231
|
-
self.inherited_without_object_daddy(subclass)
|
232
|
-
subclass.send(:include, ObjectDaddy) unless subclass < ObjectDaddy
|
233
|
-
end
|
234
|
-
|
235
|
-
class << self
|
236
|
-
alias_method_chain :inherited, :object_daddy
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|