view_mapper 0.2.0 → 0.3.0
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/Rakefile +5 -3
- data/VERSION +1 -1
- data/generators/view_for/view_for_generator.rb +4 -37
- data/lib/view_mapper/has_many_templates/controller.rb +85 -0
- data/lib/view_mapper/has_many_templates/fixtures.yml +19 -0
- data/lib/view_mapper/has_many_templates/functional_test.rb +45 -0
- data/lib/view_mapper/has_many_templates/helper.rb +18 -0
- data/lib/view_mapper/has_many_templates/helper_test.rb +4 -0
- data/lib/view_mapper/has_many_templates/layout.html.erb +19 -0
- data/lib/view_mapper/has_many_templates/migration.rb +16 -0
- data/lib/view_mapper/has_many_templates/model.rb +23 -0
- data/lib/view_mapper/has_many_templates/nested_attributes.js +13 -0
- data/lib/view_mapper/has_many_templates/style.css +58 -0
- data/lib/view_mapper/has_many_templates/unit_test.rb +8 -0
- data/lib/view_mapper/has_many_templates/view_child_form.html.erb +12 -0
- data/lib/view_mapper/has_many_templates/view_edit.html.erb +11 -0
- data/lib/view_mapper/has_many_templates/view_form.html.erb +20 -0
- data/lib/view_mapper/has_many_templates/view_index.html.erb +24 -0
- data/lib/view_mapper/has_many_templates/view_new.html.erb +10 -0
- data/lib/view_mapper/has_many_templates/view_show.html.erb +22 -0
- data/lib/view_mapper/has_many_view.rb +124 -0
- data/lib/view_mapper/model_info.rb +157 -0
- data/lib/view_mapper/paperclip_view.rb +5 -40
- data/lib/view_mapper/view_mapper.rb +2 -2
- data/lib/view_mapper.rb +2 -0
- data/test/expected_templates/has_many/_form.html.erb +26 -0
- data/test/expected_templates/has_many/_person.html.erb +18 -0
- data/test/expected_templates/has_many/create_parents.rb +15 -0
- data/test/expected_templates/has_many/edit.html.erb +11 -0
- data/test/expected_templates/has_many/index.html.erb +20 -0
- data/test/expected_templates/has_many/new.html.erb +10 -0
- data/test/expected_templates/has_many/parent.rb +14 -0
- data/test/expected_templates/has_many/show.html.erb +33 -0
- data/test/has_many_view_test.rb +405 -0
- data/test/model_info_test.rb +81 -0
- data/test/paperclip_view_test.rb +4 -27
- data/test/test_helper.rb +82 -9
- data/test/view_mapper_test.rb +2 -2
- data/view_mapper.gemspec +41 -5
- metadata +48 -5
@@ -0,0 +1,157 @@
|
|
1
|
+
module ViewMapper
|
2
|
+
class ModelInfo
|
3
|
+
|
4
|
+
attr_reader :model
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :attributes
|
7
|
+
attr_reader :error
|
8
|
+
|
9
|
+
def initialize(model_name)
|
10
|
+
@model = find_model(model_name)
|
11
|
+
@name = model.to_s unless model.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
def valid?
|
15
|
+
error.nil?
|
16
|
+
end
|
17
|
+
|
18
|
+
def columns
|
19
|
+
@columns ||= active_record_columns.collect { |col| col.name }
|
20
|
+
end
|
21
|
+
|
22
|
+
def attributes
|
23
|
+
@attributes ||= active_record_columns.collect { |col| Rails::Generator::GeneratedAttribute.new col.name, col.type }
|
24
|
+
end
|
25
|
+
|
26
|
+
def attachments
|
27
|
+
@attachments = find_attachments
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_attachment?(attachment)
|
31
|
+
attachments.include?(attachment)
|
32
|
+
end
|
33
|
+
|
34
|
+
def has_columns_for_attachment?(attachment)
|
35
|
+
!paperclip_columns_for_attachment(attachment).detect { |paperclip_col| !has_column_for_attachment(attachment, paperclip_col) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def child_models
|
39
|
+
model.reflections.select { |key, value| value.macro == :has_many }.collect do |kvpair|
|
40
|
+
kvpair[0].to_s.singularize
|
41
|
+
end.sort.collect do |model_name|
|
42
|
+
ModelInfo.new model_name
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def accepts_nested_attributes_for?(child_model)
|
47
|
+
if !model.new.methods.include? "#{child_model.name.underscore.pluralize}_attributes="
|
48
|
+
@error = "Model #{model} does not accept nested attributes for model #{child_model.name}."
|
49
|
+
false
|
50
|
+
else
|
51
|
+
true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def belongs_to?(parent_model_name)
|
56
|
+
has_association_for? :belongs_to, parent_model_name
|
57
|
+
end
|
58
|
+
|
59
|
+
def has_many?(child_model_name)
|
60
|
+
has_association_for? :has_many, child_model_name
|
61
|
+
end
|
62
|
+
|
63
|
+
def has_and_belongs_to_many?(model_name)
|
64
|
+
has_association_for? :has_and_belongs_to_many, model_name
|
65
|
+
end
|
66
|
+
|
67
|
+
def has_foreign_key_for?(parent_model_name)
|
68
|
+
model.columns.detect { |col| is_foreign_key_for?(col, parent_model_name) }
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def find_model(model_name)
|
74
|
+
model = nil
|
75
|
+
begin
|
76
|
+
model = Object.const_get model_name.camelize
|
77
|
+
if !model.new.kind_of? ActiveRecord::Base
|
78
|
+
@error = "Class '#{model_name}' is not an ActiveRecord::Base."
|
79
|
+
model = nil
|
80
|
+
end
|
81
|
+
rescue NameError
|
82
|
+
@error = "Class '#{model_name}' does not exist or contains a syntax error and could not be loaded."
|
83
|
+
rescue ActiveRecord::StatementInvalid
|
84
|
+
@error = "Table for model '#{model_name}' does not exist - run rake db:migrate first."
|
85
|
+
end
|
86
|
+
model
|
87
|
+
end
|
88
|
+
|
89
|
+
def active_record_columns
|
90
|
+
@active_record_columns ||= inspect_active_record_columns
|
91
|
+
end
|
92
|
+
|
93
|
+
def inspect_active_record_columns
|
94
|
+
model.columns.reject do |col|
|
95
|
+
is_timestamp?(col) || is_primary_key?(col) || is_foreign_key?(col) || is_paperclip_column?(col)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def is_timestamp?(col)
|
100
|
+
%w{ updated_at updated_on created_at created_on }.include? col.name
|
101
|
+
end
|
102
|
+
|
103
|
+
def is_primary_key?(col)
|
104
|
+
col.name == model.primary_key
|
105
|
+
end
|
106
|
+
|
107
|
+
def is_foreign_key?(col)
|
108
|
+
model.reflections.values.detect do |reflection|
|
109
|
+
col.name == reflection.primary_key_name
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def is_foreign_key_for?(col, parent_model_name)
|
114
|
+
model.reflections.values.detect do |reflection|
|
115
|
+
col.name == reflection.primary_key_name && reflection.name == parent_model_name.underscore.to_sym
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def has_association_for?(association, model_name)
|
120
|
+
!model.reflections.values.detect do |reflection|
|
121
|
+
reflection.name == model_name.underscore.to_sym && reflection.macro == association
|
122
|
+
end.nil?
|
123
|
+
end
|
124
|
+
|
125
|
+
def is_paperclip_column?(col)
|
126
|
+
paperclip_columns.include?(col.name)
|
127
|
+
end
|
128
|
+
|
129
|
+
def find_attachments
|
130
|
+
if model.respond_to?('attachment_definitions') && model.attachment_definitions
|
131
|
+
model.attachment_definitions.keys.collect(&:to_s).sort
|
132
|
+
else
|
133
|
+
[]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def has_column_for_attachment(attachment, paperclip_col)
|
138
|
+
has_column = model.columns.map {|col| col.name}.include?(paperclip_col)
|
139
|
+
if !has_column
|
140
|
+
@error = "Column \'#{paperclip_col}\' does not exist. First run script/generate paperclip #{name.downcase} #{attachment}."
|
141
|
+
end
|
142
|
+
has_column
|
143
|
+
end
|
144
|
+
|
145
|
+
def paperclip_columns
|
146
|
+
@paperclip_columns ||= attachments.inject([]) do |result, element|
|
147
|
+
result + paperclip_columns_for_attachment(element)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def paperclip_columns_for_attachment(attachment)
|
152
|
+
%w{ file_name content_type file_size updated_at }.collect do |col|
|
153
|
+
"#{attachment}_#{col}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -38,7 +38,7 @@ module ViewMapper
|
|
38
38
|
if view_param
|
39
39
|
parse_attachments_from_param
|
40
40
|
elsif view_only?
|
41
|
-
|
41
|
+
model.attachments
|
42
42
|
else
|
43
43
|
[]
|
44
44
|
end
|
@@ -48,14 +48,6 @@ module ViewMapper
|
|
48
48
|
view_param.split(',')
|
49
49
|
end
|
50
50
|
|
51
|
-
def inspect_model_for_attachments
|
52
|
-
if model.respond_to?('attachment_definitions') && model.attachment_definitions
|
53
|
-
model.attachment_definitions.keys.collect { |name| name.to_s }.sort
|
54
|
-
else
|
55
|
-
[]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
51
|
def validate
|
60
52
|
@valid = validate_attachments
|
61
53
|
@valid &&= super
|
@@ -65,7 +57,7 @@ module ViewMapper
|
|
65
57
|
if !paperclip_installed
|
66
58
|
logger.error "The Paperclip plugin does not appear to be installed."
|
67
59
|
return false
|
68
|
-
elsif attachments
|
60
|
+
elsif attachments.empty?
|
69
61
|
if view_only?
|
70
62
|
logger.warning "No paperclip attachments exist on the specified class."
|
71
63
|
else
|
@@ -79,44 +71,17 @@ module ViewMapper
|
|
79
71
|
|
80
72
|
def validate_attachment(attachment)
|
81
73
|
if view_only?
|
82
|
-
if !has_attachment(attachment
|
74
|
+
if !model.has_attachment?(attachment)
|
83
75
|
logger.error "Attachment '#{attachment}' does not exist."
|
84
76
|
return false
|
85
|
-
elsif !has_columns_for_attachment(attachment)
|
77
|
+
elsif !model.has_columns_for_attachment?(attachment)
|
78
|
+
logger.error model.error
|
86
79
|
return false
|
87
80
|
end
|
88
81
|
end
|
89
82
|
true
|
90
83
|
end
|
91
84
|
|
92
|
-
def has_attachment(attachment)
|
93
|
-
model.attachment_definitions && model.attachment_definitions.has_key?(attachment)
|
94
|
-
end
|
95
|
-
|
96
|
-
def has_columns_for_attachment(attachment)
|
97
|
-
!paperclip_columns_for_attachment(attachment).detect { |paperclip_col| !has_column_for_attachment(attachment, paperclip_col) }
|
98
|
-
end
|
99
|
-
|
100
|
-
def has_column_for_attachment(attachment, paperclip_col)
|
101
|
-
has_column = model.columns.collect { |col| col.name }.include?(paperclip_col)
|
102
|
-
if !has_column
|
103
|
-
logger.error "Column \'#{paperclip_col}\' does not exist. First run script/generate paperclip #{name} #{attachment}."
|
104
|
-
end
|
105
|
-
has_column
|
106
|
-
end
|
107
|
-
|
108
|
-
def built_in_columns
|
109
|
-
attachments.inject(super) do |result, element|
|
110
|
-
result + paperclip_columns_for_attachment(element)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def paperclip_columns_for_attachment(attachment)
|
115
|
-
%w{ file_name content_type file_size updated_at }.collect do |col|
|
116
|
-
"#{attachment}_#{col}"
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
85
|
def paperclip_installed
|
121
86
|
ActiveRecord::Base.methods.include? 'has_attached_file'
|
122
87
|
end
|
@@ -6,12 +6,12 @@ module ViewMapper
|
|
6
6
|
Rails::Generator::Commands::Destroy.class_eval { include RouteAction::Destroy }
|
7
7
|
super
|
8
8
|
if options[:view]
|
9
|
-
self.extend(
|
9
|
+
self.extend(view_module)
|
10
10
|
@source_root = source_root_for_view
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def view_module
|
15
15
|
"ViewMapper::#{view_name.camelize}View".constantize
|
16
16
|
end
|
17
17
|
|
data/lib/view_mapper.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= f.error_messages %>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
<%= f.label :name %><br />
|
5
|
+
<%= f.text_field :name %>
|
6
|
+
</p>
|
7
|
+
|
8
|
+
<div id='some_other_model_children'>
|
9
|
+
<% f.fields_for :some_other_models do |some_other_model_form| %>
|
10
|
+
<%= render :partial => 'some_other_model', :locals => { :f => some_other_model_form } %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<p>
|
15
|
+
<%= add_child_link 'Add a SomeOtherModel', 'some_other_model', f %>
|
16
|
+
</p>
|
17
|
+
|
18
|
+
<div id='testy_children'>
|
19
|
+
<% f.fields_for :testies do |testy_form| %>
|
20
|
+
<%= render :partial => 'testy', :locals => { :f => testy_form } %>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<p>
|
25
|
+
<%= add_child_link 'Add a Testy', 'testy', f %>
|
26
|
+
</p>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<div class="child">
|
2
|
+
<p>
|
3
|
+
Testy <%= f.label :first_name %><br />
|
4
|
+
<%= f.text_field :first_name %>
|
5
|
+
</p>
|
6
|
+
<p>
|
7
|
+
Testy <%= f.label :last_name %><br />
|
8
|
+
<%= f.text_field :last_name %>
|
9
|
+
</p>
|
10
|
+
<p>
|
11
|
+
Testy <%= f.label :address %><br />
|
12
|
+
<%= f.text_field :address %>
|
13
|
+
</p>
|
14
|
+
<p>
|
15
|
+
<%= f.hidden_field :_delete, :class => 'delete' %>
|
16
|
+
<%= remove_child_link 'remove', f %>
|
17
|
+
</p>
|
18
|
+
</div>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<h1>Listing parents</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>Name</th>
|
6
|
+
</tr>
|
7
|
+
|
8
|
+
<% @parents.each do |parent| %>
|
9
|
+
<tr>
|
10
|
+
<td><%=h parent.name %></td>
|
11
|
+
<td><%= link_to 'Show', parent %></td>
|
12
|
+
<td><%= link_to 'Edit', edit_parent_path(parent) %></td>
|
13
|
+
<td><%= link_to 'Destroy', parent, :confirm => 'Are you sure?', :method => :delete %></td>
|
14
|
+
</tr>
|
15
|
+
<% end %>
|
16
|
+
</table>
|
17
|
+
|
18
|
+
<br />
|
19
|
+
|
20
|
+
<%= link_to 'New parent', new_parent_path %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Parent < ActiveRecord::Base
|
2
|
+
has_many :some_other_models
|
3
|
+
has_many :testies
|
4
|
+
accepts_nested_attributes_for :some_other_models,
|
5
|
+
:allow_destroy => true,
|
6
|
+
:reject_if => proc { |attrs| attrs['name'].blank? }
|
7
|
+
accepts_nested_attributes_for :testies,
|
8
|
+
:allow_destroy => true,
|
9
|
+
:reject_if => proc { |attrs|
|
10
|
+
attrs['first_name'].blank? &&
|
11
|
+
attrs['last_name'].blank? &&
|
12
|
+
attrs['address'].blank?
|
13
|
+
}
|
14
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<p>
|
2
|
+
<b>Name:</b>
|
3
|
+
<%=h @parent.name %>
|
4
|
+
</p>
|
5
|
+
|
6
|
+
<% @parent.some_other_models.each do |some_other_model| %>
|
7
|
+
<div class="child">
|
8
|
+
<p>
|
9
|
+
<b>SomeOtherModel Name:</b>
|
10
|
+
<%=h some_other_model.name %>
|
11
|
+
</p>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% @parent.testies.each do |testy| %>
|
16
|
+
<div class="child">
|
17
|
+
<p>
|
18
|
+
<b>Testy First name:</b>
|
19
|
+
<%=h testy.first_name %>
|
20
|
+
</p>
|
21
|
+
<p>
|
22
|
+
<b>Testy Last name:</b>
|
23
|
+
<%=h testy.last_name %>
|
24
|
+
</p>
|
25
|
+
<p>
|
26
|
+
<b>Testy Address:</b>
|
27
|
+
<%=h testy.address %>
|
28
|
+
</p>
|
29
|
+
</div>
|
30
|
+
<% end %>
|
31
|
+
|
32
|
+
<%= link_to 'Edit', edit_parent_path(@parent) %> |
|
33
|
+
<%= link_to 'Back', parents_path %>
|