view_mapper 0.3.3 → 0.3.4
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.rdoc +3 -1
- data/VERSION +1 -1
- data/lib/view_mapper.rb +1 -0
- data/lib/view_mapper/belongs_to_parent_models.rb +12 -26
- data/lib/view_mapper/has_many_child_models.rb +9 -9
- data/lib/view_mapper/model_info.rb +56 -18
- data/lib/view_mapper/views/belongs_to/belongs_to_view.rb +14 -0
- data/lib/view_mapper/views/belongs_to_auto_complete/belongs_to_auto_complete_view.rb +9 -2
- data/lib/view_mapper/views/has_many/templates/helper.rb +1 -1
- data/lib/view_mapper/views/has_many/templates/view_child_form.html.erb +1 -1
- data/lib/view_mapper/views/has_many/templates/view_form.html.erb +1 -1
- data/lib/view_mapper/views/has_many_existing/has_many_existing_view.rb +126 -0
- data/lib/view_mapper/views/has_many_existing/templates/model.rb +21 -0
- data/lib/view_mapper/views/has_many_existing/templates/view_child_form.html.erb +16 -0
- data/lib/view_mapper/views/has_many_existing/templates/view_form.html.erb +20 -0
- data/lib/view_mapper/views/has_many_existing/templates/view_show.html.erb +26 -0
- data/test/generators/scaffold_for_view/scaffold_for_view_generator_test.rb +15 -15
- data/test/generators/view_for/view_for_generator_test.rb +18 -18
- data/test/model_info_test.rb +91 -20
- data/test/test_helper.rb +75 -105
- data/test/views/auto_complete/auto_complete_test.rb +104 -102
- data/test/views/auto_complete/expected_templates/edit.html.erb +6 -6
- data/test/views/auto_complete/expected_templates/expected_routes.rb +1 -1
- data/test/views/auto_complete/expected_templates/index.html.erb +10 -10
- data/test/views/auto_complete/expected_templates/new.html.erb +5 -5
- data/test/views/auto_complete/expected_templates/show.html.erb +6 -6
- data/test/views/auto_complete/expected_templates/{testies.html.erb → test_models.html.erb} +1 -1
- data/test/views/auto_complete/expected_templates/test_models_controller.rb +89 -0
- data/test/views/belongs_to/belongs_to_test.rb +238 -202
- data/test/views/belongs_to/expected_templates/_form.html.erb +4 -4
- data/test/views/belongs_to/expected_templates/child_model.rb +10 -0
- data/test/views/belongs_to/expected_templates/create_child_models.rb +18 -0
- data/test/views/belongs_to/expected_templates/edit.html.erb +4 -4
- data/test/views/belongs_to/expected_templates/index.html.erb +11 -11
- data/test/views/belongs_to/expected_templates/new.html.erb +3 -3
- data/test/views/belongs_to/expected_templates/show.html.erb +7 -7
- data/test/views/belongs_to_auto_complete/belongs_to_auto_complete_test.rb +440 -406
- data/test/views/belongs_to_auto_complete/expected_templates/_form.html.erb +4 -4
- data/test/views/belongs_to_auto_complete/expected_templates/child_model.rb +16 -0
- data/test/views/belongs_to_auto_complete/expected_templates/{some_other_models.html.erb → child_models.html.erb} +1 -1
- data/test/views/belongs_to_auto_complete/expected_templates/child_models_controller.rb +89 -0
- data/test/views/belongs_to_auto_complete/expected_templates/create_child_models.rb +18 -0
- data/test/views/belongs_to_auto_complete/expected_templates/edit.html.erb +4 -4
- data/test/views/belongs_to_auto_complete/expected_templates/expected_routes.rb +2 -2
- data/test/views/belongs_to_auto_complete/expected_templates/index.html.erb +11 -11
- data/test/views/belongs_to_auto_complete/expected_templates/new.html.erb +3 -3
- data/test/views/belongs_to_auto_complete/expected_templates/show.html.erb +7 -7
- data/test/views/has_many/expected_templates/_form.html.erb +8 -8
- data/test/views/has_many/expected_templates/{_person.html.erb → _second_child_model.html.erb} +5 -5
- data/test/views/has_many/expected_templates/create_parent_models.rb +16 -0
- data/test/views/has_many/expected_templates/edit.html.erb +4 -4
- data/test/views/has_many/expected_templates/index.html.erb +7 -7
- data/test/views/has_many/expected_templates/new.html.erb +3 -3
- data/test/views/has_many/expected_templates/{parent.rb → parent_model.rb} +5 -5
- data/test/views/has_many/expected_templates/show.html.erb +15 -15
- data/test/views/has_many/has_many_view_test.rb +334 -292
- data/test/views/has_many_existing/expected_templates/_assignment.html.erb +14 -0
- data/test/views/has_many_existing/expected_templates/_form.html.erb +16 -0
- data/test/views/{has_many/expected_templates/create_parents.rb → has_many_existing/expected_templates/create_programmers.rb} +3 -3
- data/test/views/has_many_existing/expected_templates/edit.html.erb +11 -0
- data/test/views/has_many_existing/expected_templates/index.html.erb +20 -0
- data/test/views/has_many_existing/expected_templates/new.html.erb +10 -0
- data/test/views/has_many_existing/expected_templates/programmer.rb +10 -0
- data/test/views/has_many_existing/expected_templates/show.html.erb +20 -0
- data/test/views/has_many_existing/has_many_existing_test.rb +495 -0
- data/test/views/paperclip/expected_templates/{create_testies.rb → create_test_models.rb} +3 -3
- data/test/views/paperclip/expected_templates/edit.html.erb +4 -4
- data/test/views/paperclip/expected_templates/index.html.erb +10 -10
- data/test/views/paperclip/expected_templates/new.html.erb +3 -3
- data/test/views/paperclip/expected_templates/show.html.erb +8 -8
- data/test/views/paperclip/expected_templates/{testy.rb → test_model.rb} +1 -1
- data/test/views/paperclip/paperclip_view_test.rb +254 -226
- data/view_mapper.gemspec +43 -27
- metadata +64 -37
- data/test/views/auto_complete/expected_templates/actual_index +0 -26
- data/test/views/auto_complete/expected_templates/testies_controller.rb +0 -89
- data/test/views/belongs_to/expected_templates/create_some_other_models.rb +0 -18
- data/test/views/belongs_to/expected_templates/some_other_model.rb +0 -10
- data/test/views/belongs_to_auto_complete/expected_templates/create_some_other_models.rb +0 -18
- data/test/views/belongs_to_auto_complete/expected_templates/some_other_model.rb +0 -16
- data/test/views/belongs_to_auto_complete/expected_templates/some_other_models_controller.rb +0 -89
data/README.rdoc
CHANGED
@@ -45,7 +45,9 @@ This is the same as view_for, but will also generate a new model at the same tim
|
|
45
45
|
|
46
46
|
{belongs_to}[http://patshaughnessy.net/2010/1/25/creating-associations-to-existing-data-part-1-belongs_to-scaffolding]: Generates scaffolding that allows you to select an existing, associated model.
|
47
47
|
|
48
|
-
belongs_to_auto_complete: Generates scaffolding that allows you to select an existing, associated model using auto_complete.
|
48
|
+
{belongs_to_auto_complete}[http://patshaughnessy.net/2010/2/13/creating-associations-to-existing-data-part-2-belongs_to-with-auto_complete]: Generates scaffolding that allows you to select an existing, associated model using auto_complete.
|
49
|
+
|
50
|
+
{has_many_existing}[http://patshaughnessy.net/2010/4/4/creating-associations-to-existing-data-part-3-has_many-through-scaffolding]: Generates scaffolding for a complex form to edit two models that have a has_many, :through association with a third model. Use this if you have a many-many relationship with existing data.
|
49
51
|
|
50
52
|
== Examples
|
51
53
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.4
|
data/lib/view_mapper.rb
CHANGED
@@ -9,3 +9,4 @@ require 'view_mapper/views/paperclip/paperclip_view'
|
|
9
9
|
require 'view_mapper/views/has_many/has_many_view'
|
10
10
|
require 'view_mapper/views/belongs_to/belongs_to_view'
|
11
11
|
require 'view_mapper/views/belongs_to_auto_complete/belongs_to_auto_complete_view'
|
12
|
+
require 'view_mapper/views/has_many_existing/has_many_existing_view'
|
@@ -1,20 +1,6 @@
|
|
1
1
|
module ViewMapper
|
2
2
|
module BelongsToParentModels
|
3
3
|
|
4
|
-
def manifest
|
5
|
-
m = super.edit do |action|
|
6
|
-
action unless is_model_dependency_action(action) || !valid
|
7
|
-
end
|
8
|
-
if valid
|
9
|
-
m.template(
|
10
|
-
"view_form.html.erb",
|
11
|
-
File.join('app/views', controller_class_path, controller_file_name, "_form.html.erb")
|
12
|
-
)
|
13
|
-
add_model_actions(m) unless view_only?
|
14
|
-
end
|
15
|
-
m
|
16
|
-
end
|
17
|
-
|
18
4
|
def add_model_actions(m)
|
19
5
|
m.directory(File.join('test/fixtures', class_path))
|
20
6
|
m.template 'model.erb', File.join('app/models', class_path, "#{file_name}.rb")
|
@@ -70,30 +56,30 @@ module ViewMapper
|
|
70
56
|
end
|
71
57
|
return false
|
72
58
|
end
|
73
|
-
parents.reject! { |parent_model| !validate_parent_model(parent_model) }
|
59
|
+
parents.reject! { |parent_model| !validate_parent_model(parent_model, class_name, view_only? ? model : nil) }
|
74
60
|
@parent_models = parents
|
75
61
|
!parents.empty?
|
76
62
|
end
|
77
63
|
|
78
|
-
def validate_parent_model(parent_model)
|
64
|
+
def validate_parent_model(parent_model, child_model_name, child_model, check_setter_method = false)
|
79
65
|
parent_model_name = parent_model.name
|
80
66
|
if !parent_model.valid?
|
81
67
|
logger.error parent_model.error
|
82
68
|
return false
|
83
|
-
elsif
|
84
|
-
logger.warning "Model #{
|
69
|
+
elsif child_model && !child_model.belongs_to?(parent_model_name)
|
70
|
+
logger.warning "Model #{child_model.name} does not belong to model #{parent_model_name}."
|
85
71
|
return false
|
86
|
-
elsif
|
87
|
-
logger.warning "Model #{
|
72
|
+
elsif child_model && !child_model.has_method?(virtual_attribute_for(parent_model))
|
73
|
+
logger.warning "Model #{child_model.name} does not have a method #{virtual_attribute_for(parent_model)}."
|
88
74
|
return false
|
89
|
-
elsif
|
90
|
-
logger.warning "Model #{
|
75
|
+
elsif child_model && check_setter_method && !child_model.has_method?(virtual_attribute_setter_for(parent_model))
|
76
|
+
logger.warning "Model #{child_model.name} does not have a method #{virtual_attribute_setter_for(parent_model)}."
|
91
77
|
return false
|
92
|
-
elsif
|
93
|
-
logger.warning "Model #{
|
78
|
+
elsif child_model && !child_model.has_foreign_key_for?(parent_model_name)
|
79
|
+
logger.warning "Model #{child_model.name} does not contain a foreign key for #{parent_model_name}."
|
94
80
|
return false
|
95
|
-
elsif !parent_model.has_many?(
|
96
|
-
logger.warning "Model #{parent_model_name} does not contain a has_many association for #{
|
81
|
+
elsif !parent_model.has_many?(child_model_name.pluralize)
|
82
|
+
logger.warning "Model #{parent_model_name} does not contain a has_many association for #{child_model_name}."
|
97
83
|
return false
|
98
84
|
elsif !parent_model.has_method?(field_for(parent_model)) && !parent_model.has_column?(field_for(parent_model))
|
99
85
|
logger.warning "Model #{parent_model_name} does not have a #{field_for(parent_model)} attribute."
|
@@ -82,26 +82,26 @@ module ViewMapper
|
|
82
82
|
end
|
83
83
|
return false
|
84
84
|
end
|
85
|
-
cms.reject! { |child_model| !validate_child_model(child_model) }
|
85
|
+
cms.reject! { |child_model| !validate_child_model(child_model, class_name, view_only? ? model : nil) }
|
86
86
|
@child_models = cms
|
87
87
|
!cms.empty?
|
88
88
|
end
|
89
89
|
|
90
|
-
def validate_child_model(child_model)
|
90
|
+
def validate_child_model(child_model, parent_model_name, parent_model)
|
91
91
|
if !child_model.valid?
|
92
92
|
logger.error child_model.error
|
93
93
|
return false
|
94
|
-
elsif
|
95
|
-
logger.warning "Model #{
|
94
|
+
elsif parent_model && !parent_model.accepts_nested_attributes_for?(child_model)
|
95
|
+
logger.warning "Model #{parent_model.name} does not accept nested attributes for model #{child_model.name}."
|
96
96
|
return false
|
97
97
|
else
|
98
|
-
if child_model.has_many?(
|
98
|
+
if child_model.has_many?(parent_model_name.pluralize) || child_model.has_and_belongs_to_many?(parent_model_name.pluralize)
|
99
99
|
true
|
100
|
-
elsif !child_model.belongs_to?(
|
101
|
-
logger.warning "Model #{child_model.name} does not contain a belongs_to association for #{
|
100
|
+
elsif !child_model.belongs_to?(parent_model_name)
|
101
|
+
logger.warning "Model #{child_model.name} does not contain a belongs_to association for #{parent_model_name}."
|
102
102
|
return false
|
103
|
-
elsif !child_model.has_foreign_key_for?(
|
104
|
-
logger.warning "Model #{child_model.name} does not contain a foreign key for #{
|
103
|
+
elsif !child_model.has_foreign_key_for?(parent_model_name)
|
104
|
+
logger.warning "Model #{child_model.name} does not contain a foreign key for #{parent_model_name}."
|
105
105
|
return false
|
106
106
|
end
|
107
107
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module ViewMapper
|
2
2
|
class ModelInfo
|
3
3
|
|
4
|
-
attr_reader
|
5
|
-
|
6
|
-
attr_reader
|
7
|
-
attr_reader
|
4
|
+
attr_reader :model
|
5
|
+
attr_accessor :through_model # has_many :through => XYZ
|
6
|
+
attr_reader :name
|
7
|
+
attr_reader :error
|
8
8
|
|
9
9
|
def initialize(model_name)
|
10
10
|
@model = find_model(model_name)
|
@@ -52,18 +52,47 @@ module ViewMapper
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def child_models
|
55
|
-
model_info_array_for_association(:has_many)
|
55
|
+
@child_models ||= model_info_array_for_association(:has_many)
|
56
56
|
end
|
57
57
|
|
58
58
|
def parent_models
|
59
|
-
model_info_array_for_association(:belongs_to)
|
59
|
+
@parent_models ||= model_info_array_for_association(:belongs_to)
|
60
60
|
end
|
61
61
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
62
|
+
def has_many_through_models
|
63
|
+
@has_many_through_models ||= model_info_array_for_association(:has_many, ActiveRecord::Reflection::ThroughReflection)
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_through_model(source_model_name)
|
67
|
+
reflections_for_association(:has_many, ActiveRecord::Reflection::ThroughReflection).each do |kvpair|
|
68
|
+
reflection_model_name = kvpair[0].to_s.singularize
|
69
|
+
if reflection_model_name == source_model_name.underscore
|
70
|
+
reflection = kvpair[1]
|
71
|
+
return ModelInfo.new(reflection.options[:through].to_s.singularize)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def reflections_for_association(association_type, type)
|
78
|
+
model.reflections.select { |key, value| value.macro == association_type && value.is_a?(type) }
|
79
|
+
end
|
80
|
+
|
81
|
+
def model_info_from_reflection(reflection_model_name, reflection)
|
82
|
+
model_info = ModelInfo.new(reflection_model_name)
|
83
|
+
if reflection.is_a? ActiveRecord::Reflection::ThroughReflection
|
84
|
+
model_info.through_model = ModelInfo.new reflection.options[:through].to_s.singularize
|
85
|
+
end
|
86
|
+
model_info
|
87
|
+
end
|
88
|
+
|
89
|
+
def model_info_array_for_association(association_type, type = ActiveRecord::Reflection::AssociationReflection)
|
90
|
+
reflections_for_association(association_type, type).collect do |kvpair|
|
91
|
+
reflection_model_name = kvpair[0].to_s.singularize
|
92
|
+
reflection = kvpair[1]
|
93
|
+
model_info_from_reflection(reflection_model_name, reflection)
|
94
|
+
end.sort do |a, b|
|
95
|
+
a.name <=> b.name
|
67
96
|
end
|
68
97
|
end
|
69
98
|
|
@@ -77,18 +106,27 @@ module ViewMapper
|
|
77
106
|
end
|
78
107
|
|
79
108
|
def belongs_to?(parent_model_name)
|
80
|
-
|
109
|
+
!association_for(:belongs_to, parent_model_name).nil?
|
81
110
|
end
|
82
111
|
|
83
112
|
def has_many?(child_model_name)
|
84
|
-
|
113
|
+
!association_for(:has_many, child_model_name).nil?
|
85
114
|
end
|
86
115
|
|
87
116
|
def has_and_belongs_to_many?(model_name)
|
88
|
-
|
117
|
+
!association_for(:has_and_belongs_to_many, model_name).nil?
|
118
|
+
end
|
119
|
+
|
120
|
+
def has_many_through?(model_name)
|
121
|
+
reflection = association_for(:has_many, model_name.pluralize)
|
122
|
+
reflection && reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
|
89
123
|
end
|
90
124
|
|
91
125
|
def has_foreign_key_for?(parent_model_name)
|
126
|
+
!foreign_key_for(parent_model_name).nil?
|
127
|
+
end
|
128
|
+
|
129
|
+
def foreign_key_for(parent_model_name)
|
92
130
|
model.columns.detect { |col| is_foreign_key_for?(col, parent_model_name) }
|
93
131
|
end
|
94
132
|
|
@@ -140,10 +178,10 @@ module ViewMapper
|
|
140
178
|
end
|
141
179
|
end
|
142
180
|
|
143
|
-
def
|
144
|
-
|
181
|
+
def association_for(association, model_name)
|
182
|
+
model.reflections.values.detect do |reflection|
|
145
183
|
reflection.name == model_name.underscore.to_sym && reflection.macro == association
|
146
|
-
end
|
184
|
+
end
|
147
185
|
end
|
148
186
|
|
149
187
|
def is_paperclip_column?(col)
|
@@ -161,7 +199,7 @@ module ViewMapper
|
|
161
199
|
def has_column_for_attachment(attachment, paperclip_col)
|
162
200
|
has_column = model.columns.map {|col| col.name}.include?(paperclip_col)
|
163
201
|
if !has_column
|
164
|
-
@error = "Column \'#{paperclip_col}\' does not exist. First run script/generate paperclip #{name.
|
202
|
+
@error = "Column \'#{paperclip_col}\' does not exist. First run script/generate paperclip #{name.underscore} #{attachment}."
|
165
203
|
end
|
166
204
|
has_column
|
167
205
|
end
|
@@ -11,6 +11,20 @@ module ViewMapper
|
|
11
11
|
[ BelongsToView.source_root, File.expand_path(source_root), File.join(self.class.lookup('model').path, 'templates') ]
|
12
12
|
end
|
13
13
|
|
14
|
+
def manifest
|
15
|
+
m = super.edit do |action|
|
16
|
+
action unless is_model_dependency_action(action) || !valid
|
17
|
+
end
|
18
|
+
if valid
|
19
|
+
m.template(
|
20
|
+
"view_form.html.erb",
|
21
|
+
File.join('app/views', controller_class_path, controller_file_name, "_form.html.erb")
|
22
|
+
)
|
23
|
+
add_model_actions(m) unless view_only?
|
24
|
+
end
|
25
|
+
m
|
26
|
+
end
|
27
|
+
|
14
28
|
def validate
|
15
29
|
super
|
16
30
|
@valid &&= validate_parent_models
|
@@ -12,8 +12,15 @@ module ViewMapper
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def manifest
|
15
|
-
m = super
|
15
|
+
m = super.edit do |action|
|
16
|
+
action unless is_model_dependency_action(action) || !valid
|
17
|
+
end
|
16
18
|
if valid
|
19
|
+
m.template(
|
20
|
+
"view_form.html.erb",
|
21
|
+
File.join('app/views', controller_class_path, controller_file_name, "_form.html.erb")
|
22
|
+
)
|
23
|
+
add_model_actions(m) unless view_only?
|
17
24
|
parent_models.reverse.each do |parent_model|
|
18
25
|
m.route :name => 'connect',
|
19
26
|
:path => auto_complete_for_method(parent_model),
|
@@ -34,7 +41,7 @@ module ViewMapper
|
|
34
41
|
@valid &&= validate_parent_models
|
35
42
|
end
|
36
43
|
|
37
|
-
def validate_parent_model(parent_model)
|
44
|
+
def validate_parent_model(parent_model, child_model_name, child_model, check_setter_method = true)
|
38
45
|
valid = super
|
39
46
|
if valid && !parent_model.has_column?(field_for(parent_model))
|
40
47
|
logger.warning "Model #{parent_model.name} does not have a #{field_for(parent_model)} column."
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module <%= controller_class_name %>Helper
|
2
2
|
|
3
3
|
def remove_child_link(name, form_builder)
|
4
|
-
form_builder.hidden_field(:
|
4
|
+
form_builder.hidden_field(:_destroy) + link_to_function(name, "remove_child(this)")
|
5
5
|
end
|
6
6
|
|
7
7
|
def add_child_link(name, child, form_builder)
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module ViewMapper
|
2
|
+
module HasManyExistingView
|
3
|
+
|
4
|
+
include BelongsToParentModels
|
5
|
+
include HasManyChildModels
|
6
|
+
|
7
|
+
def self.source_root
|
8
|
+
File.expand_path(File.dirname(__FILE__) + "/templates")
|
9
|
+
end
|
10
|
+
|
11
|
+
def source_roots_for_view
|
12
|
+
[
|
13
|
+
HasManyExistingView.source_root,
|
14
|
+
HasManyView.source_root,
|
15
|
+
File.expand_path(source_root),
|
16
|
+
File.join(self.class.lookup('model').path, 'templates')
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
def manifest
|
21
|
+
m = super.edit do |action|
|
22
|
+
action unless is_child_model_action?(action)
|
23
|
+
end
|
24
|
+
add_through_models_manifest(m)
|
25
|
+
m
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_through_models_manifest(m)
|
29
|
+
add_child_model_actions(m) if valid && !view_only?
|
30
|
+
add_through_model_forms(m) if valid
|
31
|
+
m
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_through_model_forms(m)
|
35
|
+
m.template(
|
36
|
+
"view_show.html.erb",
|
37
|
+
File.join('app/views', controller_class_path, controller_file_name, "show.html.erb"),
|
38
|
+
{ :assigns => { :has_many_through_models => has_many_through_models } }
|
39
|
+
)
|
40
|
+
m.template(
|
41
|
+
"view_form.html.erb",
|
42
|
+
File.join('app/views', controller_class_path, controller_file_name, "_form.html.erb")
|
43
|
+
)
|
44
|
+
has_many_through_models.each do |hmt_model|
|
45
|
+
m.template(
|
46
|
+
"view_child_form.html.erb",
|
47
|
+
File.join('app/views', controller_class_path, controller_file_name, "_#{hmt_model.through_model.name.underscore}.html.erb"),
|
48
|
+
{ :assigns => { :hmt_model => hmt_model } }
|
49
|
+
|
50
|
+
)
|
51
|
+
end
|
52
|
+
m.file('nested_attributes.js', 'public/javascripts/nested_attributes.js')
|
53
|
+
m
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate
|
57
|
+
super
|
58
|
+
@valid &&= validate_hmt_models
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_many_through_models
|
62
|
+
@hmt_models ||= find_hmt_models
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_hmt_models
|
66
|
+
if view_param
|
67
|
+
view_param.split(',').collect do |param|
|
68
|
+
hmt_model_info_from_param(param)
|
69
|
+
end
|
70
|
+
elsif view_only?
|
71
|
+
model.has_many_through_models
|
72
|
+
else
|
73
|
+
[]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def hmt_model_info_from_param(param)
|
78
|
+
if /(.*)\[(.*)\]/.match(param)
|
79
|
+
hmt_model = ModelInfo.new($1.singularize)
|
80
|
+
select_parent_by hmt_model, $2
|
81
|
+
else
|
82
|
+
hmt_model = ModelInfo.new(param.singularize)
|
83
|
+
end
|
84
|
+
hmt_model
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_hmt_models
|
88
|
+
models = has_many_through_models
|
89
|
+
if models.empty?
|
90
|
+
if view_only?
|
91
|
+
logger.error "No has_many through associations exist in class #{model.name}."
|
92
|
+
else
|
93
|
+
logger.error "No has_many through association specified."
|
94
|
+
end
|
95
|
+
return false
|
96
|
+
end
|
97
|
+
models.reject! { |hmt_model| !validate_hmt_model(hmt_model) }
|
98
|
+
@hmt_models = models
|
99
|
+
!models.empty?
|
100
|
+
end
|
101
|
+
|
102
|
+
def validate_hmt_model(hmt_model)
|
103
|
+
if !hmt_model.valid?
|
104
|
+
logger.error hmt_model.error
|
105
|
+
return false
|
106
|
+
elsif !hmt_model.has_many_through?(class_name)
|
107
|
+
logger.warning "Model #{hmt_model.name} does not contain a has_many through association for #{class_name}."
|
108
|
+
return false
|
109
|
+
end
|
110
|
+
|
111
|
+
hmt_model.through_model = hmt_model.find_through_model(class_name) if hmt_model.through_model.nil?
|
112
|
+
if !hmt_model.through_model.valid?
|
113
|
+
logger.error hmt_model.through_model.error
|
114
|
+
return false
|
115
|
+
elsif !validate_parent_model(hmt_model, hmt_model.through_model.name, hmt_model.through_model)
|
116
|
+
return false
|
117
|
+
elsif !validate_child_model(hmt_model.through_model, class_name, view_only? ? model : nil)
|
118
|
+
return false
|
119
|
+
elsif !validate_child_model(hmt_model.through_model, hmt_model.name, nil)
|
120
|
+
return false
|
121
|
+
end
|
122
|
+
true
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class <%= class_name %> < ActiveRecord::Base
|
2
|
+
<% has_many_through_models.each do |hmt_model| -%>
|
3
|
+
<% attribs = Array.new(hmt_model.through_model.attributes) -%>
|
4
|
+
<% attribs << hmt_model.through_model.foreign_key_for(hmt_model.name) -%>
|
5
|
+
has_many :<%= hmt_model.name.underscore.pluralize %>, :through => :<%= hmt_model.through_model.name.underscore.pluralize %>
|
6
|
+
has_many :<%= hmt_model.through_model.name.underscore.pluralize %>
|
7
|
+
accepts_nested_attributes_for :<%= hmt_model.through_model.name.underscore.pluralize %>,
|
8
|
+
:allow_destroy => true<% if attribs.size > 0 %>,<% end %>
|
9
|
+
<% if attribs.size > 0 -%>
|
10
|
+
<% if attribs.size == 1 -%>
|
11
|
+
:reject_if => proc { |attrs| attrs['<%= attribs[0].name %>'].blank? }
|
12
|
+
<% elsif -%>
|
13
|
+
:reject_if => proc { |attrs|
|
14
|
+
<% attribs.each_with_index do |attr, i| -%>
|
15
|
+
attrs['<%= attr.name %>'].blank?<% unless i == attribs.size-1 %> &&<% end %>
|
16
|
+
<% end -%>
|
17
|
+
}
|
18
|
+
<% end -%>
|
19
|
+
<% end -%>
|
20
|
+
<% end -%>
|
21
|
+
end
|