object_daddy 0.4.1 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|