view_mapper 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/Rakefile
CHANGED
@@ -5,14 +5,16 @@ begin
|
|
5
5
|
require 'jeweler'
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "view_mapper"
|
8
|
-
gem.summary = %Q{
|
9
|
-
gem.description = %Q{
|
8
|
+
gem.summary = %Q{Scaffolding for your models and plugins}
|
9
|
+
gem.description = %Q{View_mapper will generate scaffolding for new or existing models, customized for the plugins you use in your app.}
|
10
10
|
gem.email = "pat@patshaughnessy.net"
|
11
|
-
gem.homepage = "http://
|
11
|
+
gem.homepage = "http://patshaughnessy.net/view_mapper"
|
12
12
|
gem.authors = ["Pat Shaughnessy"]
|
13
13
|
gem.add_development_dependency "thoughtbot-shoulda"
|
14
|
+
gem.add_development_dependency "mocha"
|
14
15
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
16
|
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
16
18
|
rescue LoadError
|
17
19
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
20
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
@@ -7,13 +7,10 @@ class ViewForGenerator < ScaffoldGenerator
|
|
7
7
|
attr_reader :model
|
8
8
|
attr_accessor :valid
|
9
9
|
|
10
|
-
BUILT_IN_COLUMNS = [ 'id', 'created_at', 'updated_at' ]
|
11
|
-
|
12
10
|
def initialize(runtime_args, runtime_options = {})
|
13
11
|
super
|
14
12
|
@source_root = source_root_for_view
|
15
|
-
|
16
|
-
@columns = custom_columns unless model.nil?
|
13
|
+
@model = ModelInfo.new(@name)
|
17
14
|
validate
|
18
15
|
end
|
19
16
|
|
@@ -21,31 +18,6 @@ class ViewForGenerator < ScaffoldGenerator
|
|
21
18
|
self.class.lookup('scaffold').path + "/templates"
|
22
19
|
end
|
23
20
|
|
24
|
-
def find_model(model_name)
|
25
|
-
@model = nil
|
26
|
-
begin
|
27
|
-
@model = Object.const_get model_name.camelize
|
28
|
-
if !model.new.kind_of? ActiveRecord::Base
|
29
|
-
logger.error "Class '#{model_name}' is not an ActiveRecord::Base."
|
30
|
-
@model = nil
|
31
|
-
end
|
32
|
-
rescue NameError
|
33
|
-
logger.error "Class '#{model_name}' does not exist or contains a syntax error and could not be loaded."
|
34
|
-
rescue ActiveRecord::StatementInvalid
|
35
|
-
logger.error "Table for model '#{model_name}' does not exist - run rake db:migrate first."
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def custom_columns
|
40
|
-
@model.columns.reject do |col|
|
41
|
-
built_in_columns.include? col.name
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def built_in_columns
|
46
|
-
BUILT_IN_COLUMNS
|
47
|
-
end
|
48
|
-
|
49
21
|
def record
|
50
22
|
EditableManifest.new(self) { |m| yield m }
|
51
23
|
end
|
@@ -69,17 +41,12 @@ class ViewForGenerator < ScaffoldGenerator
|
|
69
41
|
end
|
70
42
|
|
71
43
|
def attributes
|
72
|
-
@
|
73
|
-
end
|
74
|
-
|
75
|
-
def attributes_from_columns
|
76
|
-
@columns.collect do |col|
|
77
|
-
Rails::Generator::GeneratedAttribute.new col.name, col.type
|
78
|
-
end
|
44
|
+
@attributes ||= model.attributes
|
79
45
|
end
|
80
46
|
|
81
47
|
def validate
|
82
|
-
|
48
|
+
logger.error(model.error) if !model.valid?
|
49
|
+
@valid = model.valid?
|
83
50
|
end
|
84
51
|
|
85
52
|
def banner
|
@@ -0,0 +1,85 @@
|
|
1
|
+
class <%= controller_class_name %>Controller < ApplicationController
|
2
|
+
# GET /<%= table_name %>
|
3
|
+
# GET /<%= table_name %>.xml
|
4
|
+
def index
|
5
|
+
@<%= table_name %> = <%= class_name %>.all
|
6
|
+
|
7
|
+
respond_to do |format|
|
8
|
+
format.html # index.html.erb
|
9
|
+
format.xml { render :xml => @<%= table_name %> }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# GET /<%= table_name %>/1
|
14
|
+
# GET /<%= table_name %>/1.xml
|
15
|
+
def show
|
16
|
+
@<%= file_name %> = <%= class_name %>.find(params[:id])
|
17
|
+
|
18
|
+
respond_to do |format|
|
19
|
+
format.html # show.html.erb
|
20
|
+
format.xml { render :xml => @<%= file_name %> }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# GET /<%= table_name %>/new
|
25
|
+
# GET /<%= table_name %>/new.xml
|
26
|
+
def new
|
27
|
+
@<%= file_name %> = <%= class_name %>.new
|
28
|
+
|
29
|
+
respond_to do |format|
|
30
|
+
format.html # new.html.erb
|
31
|
+
format.xml { render :xml => @<%= file_name %> }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# GET /<%= table_name %>/1/edit
|
36
|
+
def edit
|
37
|
+
@<%= file_name %> = <%= class_name %>.find(params[:id])
|
38
|
+
end
|
39
|
+
|
40
|
+
# POST /<%= table_name %>
|
41
|
+
# POST /<%= table_name %>.xml
|
42
|
+
def create
|
43
|
+
@<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>])
|
44
|
+
|
45
|
+
respond_to do |format|
|
46
|
+
if @<%= file_name %>.save
|
47
|
+
flash[:notice] = '<%= class_name %> was successfully created.'
|
48
|
+
format.html { redirect_to(@<%= file_name %>) }
|
49
|
+
format.xml { render :xml => @<%= file_name %>, :status => :created, :location => @<%= file_name %> }
|
50
|
+
else
|
51
|
+
format.html { render :action => "new" }
|
52
|
+
format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# PUT /<%= table_name %>/1
|
58
|
+
# PUT /<%= table_name %>/1.xml
|
59
|
+
def update
|
60
|
+
@<%= file_name %> = <%= class_name %>.find(params[:id])
|
61
|
+
|
62
|
+
respond_to do |format|
|
63
|
+
if @<%= file_name %>.update_attributes(params[:<%= file_name %>])
|
64
|
+
flash[:notice] = '<%= class_name %> was successfully updated.'
|
65
|
+
format.html { redirect_to(@<%= file_name %>) }
|
66
|
+
format.xml { head :ok }
|
67
|
+
else
|
68
|
+
format.html { render :action => "edit" }
|
69
|
+
format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# DELETE /<%= table_name %>/1
|
75
|
+
# DELETE /<%= table_name %>/1.xml
|
76
|
+
def destroy
|
77
|
+
@<%= file_name %> = <%= class_name %>.find(params[:id])
|
78
|
+
@<%= file_name %>.destroy
|
79
|
+
|
80
|
+
respond_to do |format|
|
81
|
+
format.html { redirect_to(<%= table_name %>_url) }
|
82
|
+
format.xml { head :ok }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
2
|
+
|
3
|
+
<% unless attributes.empty? -%>
|
4
|
+
one:
|
5
|
+
<% for attribute in attributes -%>
|
6
|
+
<%= attribute.name %>: <%= attribute.default %>
|
7
|
+
<% end -%>
|
8
|
+
|
9
|
+
two:
|
10
|
+
<% for attribute in attributes -%>
|
11
|
+
<%= attribute.name %>: <%= attribute.default %>
|
12
|
+
<% end -%>
|
13
|
+
<% else -%>
|
14
|
+
# one:
|
15
|
+
# column: value
|
16
|
+
#
|
17
|
+
# two:
|
18
|
+
# column: value
|
19
|
+
<% end -%>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class <%= controller_class_name %>ControllerTest < ActionController::TestCase
|
4
|
+
test "should get index" do
|
5
|
+
get :index
|
6
|
+
assert_response :success
|
7
|
+
assert_not_nil assigns(:<%= table_name %>)
|
8
|
+
end
|
9
|
+
|
10
|
+
test "should get new" do
|
11
|
+
get :new
|
12
|
+
assert_response :success
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should create <%= file_name %>" do
|
16
|
+
assert_difference('<%= class_name %>.count') do
|
17
|
+
post :create, :<%= file_name %> => { }
|
18
|
+
end
|
19
|
+
|
20
|
+
assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
|
21
|
+
end
|
22
|
+
|
23
|
+
test "should show <%= file_name %>" do
|
24
|
+
get :show, :id => <%= table_name %>(:one).to_param
|
25
|
+
assert_response :success
|
26
|
+
end
|
27
|
+
|
28
|
+
test "should get edit" do
|
29
|
+
get :edit, :id => <%= table_name %>(:one).to_param
|
30
|
+
assert_response :success
|
31
|
+
end
|
32
|
+
|
33
|
+
test "should update <%= file_name %>" do
|
34
|
+
put :update, :id => <%= table_name %>(:one).to_param, :<%= file_name %> => { }
|
35
|
+
assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
|
36
|
+
end
|
37
|
+
|
38
|
+
test "should destroy <%= file_name %>" do
|
39
|
+
assert_difference('<%= class_name %>.count', -1) do
|
40
|
+
delete :destroy, :id => <%= table_name %>(:one).to_param
|
41
|
+
end
|
42
|
+
|
43
|
+
assert_redirected_to <%= table_name %>_path
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module <%= controller_class_name %>Helper
|
2
|
+
|
3
|
+
def remove_child_link(name, form_builder)
|
4
|
+
form_builder.hidden_field(:_delete) + link_to_function(name, "remove_child(this)")
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_child_link(name, child, form_builder)
|
8
|
+
fields = escape_javascript(new_child_fields(child, form_builder))
|
9
|
+
link_to_function(name, h("add_child(this, \"#{child}\", \"#{fields}\")"))
|
10
|
+
end
|
11
|
+
|
12
|
+
def new_child_fields(child, form_builder)
|
13
|
+
form_builder.fields_for(child.pluralize.to_sym, child.camelize.constantize.new, :child_index => 'NEW_RECORD') do |f|
|
14
|
+
render(:partial => child.underscore, :locals => { :f => f })
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
7
|
+
<title><%= controller_class_name %>: <%%= controller.action_name %></title>
|
8
|
+
<%%= stylesheet_link_tag 'scaffold' %>
|
9
|
+
<%%= javascript_include_tag 'prototype.js' %>
|
10
|
+
<%%= javascript_include_tag 'nested_attributes.js' %>
|
11
|
+
</head>
|
12
|
+
<body>
|
13
|
+
|
14
|
+
<p style="color: green"><%%= flash[:notice] %></p>
|
15
|
+
|
16
|
+
<%%= yield %>
|
17
|
+
|
18
|
+
</body>
|
19
|
+
</html>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class <%= migration_name %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
|
+
<% for attribute in attributes -%>
|
5
|
+
t.<%= attribute.type %> :<%= attribute.name %>
|
6
|
+
<% end -%>
|
7
|
+
<% unless options[:skip_timestamps] %>
|
8
|
+
t.timestamps
|
9
|
+
<% end -%>
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :<%= table_name %>
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class <%= class_name %> < ActiveRecord::Base
|
2
|
+
<% attributes.select(&:reference?).each do |attribute| -%>
|
3
|
+
belongs_to :<%= attribute.name %>
|
4
|
+
<% end -%>
|
5
|
+
<% child_models.each do |child_model| -%>
|
6
|
+
has_many :<%= child_model.name.underscore.pluralize %>
|
7
|
+
<% end -%>
|
8
|
+
<% child_models.each do |child_model| -%>
|
9
|
+
accepts_nested_attributes_for :<%= child_model.name.underscore.pluralize %>,
|
10
|
+
:allow_destroy => true<% if child_model.attributes.size > 0 %>,<% end %>
|
11
|
+
<% if child_model.attributes.size > 0 -%>
|
12
|
+
<% if child_model.attributes.size == 1 -%>
|
13
|
+
:reject_if => proc { |attrs| attrs['<%= child_model.attributes[0].name %>'].blank? }
|
14
|
+
<% elsif -%>
|
15
|
+
:reject_if => proc { |attrs|
|
16
|
+
<% child_model.attributes.each_with_index do |attr, i| -%>
|
17
|
+
attrs['<%= attr.name %>'].blank?<% unless i == child_model.attributes.size-1 %> &&<% end %>
|
18
|
+
<% end -%>
|
19
|
+
}
|
20
|
+
<% end -%>
|
21
|
+
<% end -%>
|
22
|
+
<% end -%>
|
23
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
function add_child(element, child_name, new_child) {
|
2
|
+
$(child_name + '_children').insert({
|
3
|
+
bottom: new_child.replace(/NEW_RECORD/g, new Date().getTime())
|
4
|
+
});
|
5
|
+
}
|
6
|
+
|
7
|
+
function remove_child(element) {
|
8
|
+
var hidden_field = $(element).previous("input[type=hidden]");
|
9
|
+
if (hidden_field) {
|
10
|
+
hidden_field.value = '1';
|
11
|
+
}
|
12
|
+
$(element).up(".child").hide();
|
13
|
+
}
|
@@ -0,0 +1,58 @@
|
|
1
|
+
body { background-color: #fff; color: #333; }
|
2
|
+
|
3
|
+
body, p, ol, ul, td {
|
4
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
5
|
+
font-size: 13px;
|
6
|
+
line-height: 18px;
|
7
|
+
}
|
8
|
+
|
9
|
+
pre {
|
10
|
+
background-color: #eee;
|
11
|
+
padding: 10px;
|
12
|
+
font-size: 11px;
|
13
|
+
}
|
14
|
+
|
15
|
+
a { color: #000; }
|
16
|
+
a:visited { color: #666; }
|
17
|
+
a:hover { color: #fff; background-color:#000; }
|
18
|
+
|
19
|
+
.fieldWithErrors {
|
20
|
+
padding: 2px;
|
21
|
+
background-color: red;
|
22
|
+
display: table;
|
23
|
+
}
|
24
|
+
|
25
|
+
#errorExplanation {
|
26
|
+
width: 400px;
|
27
|
+
border: 2px solid red;
|
28
|
+
padding: 7px;
|
29
|
+
padding-bottom: 12px;
|
30
|
+
margin-bottom: 20px;
|
31
|
+
background-color: #f0f0f0;
|
32
|
+
}
|
33
|
+
|
34
|
+
#errorExplanation h2 {
|
35
|
+
text-align: left;
|
36
|
+
font-weight: bold;
|
37
|
+
padding: 5px 5px 5px 15px;
|
38
|
+
font-size: 12px;
|
39
|
+
margin: -7px;
|
40
|
+
background-color: #c00;
|
41
|
+
color: #fff;
|
42
|
+
}
|
43
|
+
|
44
|
+
#errorExplanation p {
|
45
|
+
color: #333;
|
46
|
+
margin-bottom: 0;
|
47
|
+
padding: 5px;
|
48
|
+
}
|
49
|
+
|
50
|
+
#errorExplanation ul li {
|
51
|
+
font-size: 12px;
|
52
|
+
list-style: square;
|
53
|
+
}
|
54
|
+
|
55
|
+
.child {
|
56
|
+
border-left: 10px solid #eee;
|
57
|
+
padding-left:10px;
|
58
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<div class="child">
|
2
|
+
<% for attribute in child_model.attributes -%>
|
3
|
+
<p>
|
4
|
+
<%= child_model.name %> <%%= f.label :<%= attribute.name %> %><br />
|
5
|
+
<%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
|
6
|
+
</p>
|
7
|
+
<% end -%>
|
8
|
+
<p>
|
9
|
+
<%%= f.hidden_field :_delete, :class => 'delete' %>
|
10
|
+
<%%= remove_child_link 'remove', f %>
|
11
|
+
</p>
|
12
|
+
</div>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<h1>Editing <%= singular_name %></h1>
|
2
|
+
|
3
|
+
<%% form_for(@<%= singular_name %>) do |f| %>
|
4
|
+
<%%= render :partial => 'form', :locals => { :f => f } %>
|
5
|
+
<p>
|
6
|
+
<%%= f.submit 'Update' %>
|
7
|
+
</p>
|
8
|
+
<%% end %>
|
9
|
+
|
10
|
+
<%%= link_to 'Show', @<%= singular_name %> %> |
|
11
|
+
<%%= link_to 'Back', <%= plural_name %>_path %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<%%= f.error_messages %>
|
2
|
+
<% for attribute in attributes -%>
|
3
|
+
|
4
|
+
<p>
|
5
|
+
<%%= f.label :<%= attribute.name %> %><br />
|
6
|
+
<%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
|
7
|
+
</p>
|
8
|
+
<% end -%>
|
9
|
+
<% child_models.each do |child_model| -%>
|
10
|
+
|
11
|
+
<div id='<%= child_model.name.underscore %>_children'>
|
12
|
+
<%% f.fields_for :<%= child_model.name.underscore.pluralize %> do |<%= child_model.name.underscore %>_form| %>
|
13
|
+
<%%= render :partial => '<%= child_model.name.underscore %>', :locals => { :f => <%= child_model.name.underscore %>_form } %>
|
14
|
+
<%% end %>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<p>
|
18
|
+
<%%= add_child_link 'Add a <%= child_model.name %>', '<%= child_model.name.underscore %>', f %>
|
19
|
+
</p>
|
20
|
+
<% end -%>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<h1>Listing <%= plural_name %></h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<% for attribute in attributes -%>
|
6
|
+
<th><%= attribute.column.human_name %></th>
|
7
|
+
<% end -%>
|
8
|
+
</tr>
|
9
|
+
|
10
|
+
<%% @<%= plural_name %>.each do |<%= singular_name %>| %>
|
11
|
+
<tr>
|
12
|
+
<% for attribute in attributes -%>
|
13
|
+
<td><%%=h <%= singular_name %>.<%= attribute.name %> %></td>
|
14
|
+
<% end -%>
|
15
|
+
<td><%%= link_to 'Show', <%= singular_name %> %></td>
|
16
|
+
<td><%%= link_to 'Edit', edit_<%= singular_name %>_path(<%= singular_name %>) %></td>
|
17
|
+
<td><%%= link_to 'Destroy', <%= singular_name %>, :confirm => 'Are you sure?', :method => :delete %></td>
|
18
|
+
</tr>
|
19
|
+
<%% end %>
|
20
|
+
</table>
|
21
|
+
|
22
|
+
<br />
|
23
|
+
|
24
|
+
<%%= link_to 'New <%= singular_name %>', new_<%= singular_name %>_path %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<% for attribute in attributes -%>
|
2
|
+
<p>
|
3
|
+
<b><%= attribute.column.human_name %>:</b>
|
4
|
+
<%%=h @<%= singular_name %>.<%= attribute.name %> %>
|
5
|
+
</p>
|
6
|
+
|
7
|
+
<% end -%>
|
8
|
+
<% child_models.each do |child_model| -%>
|
9
|
+
<%% @<%= singular_name %>.<%= child_model.name.underscore.pluralize %>.each do |<%= child_model.name.underscore %>| %>
|
10
|
+
<div class="child">
|
11
|
+
<% for attribute in child_model.attributes -%>
|
12
|
+
<p>
|
13
|
+
<b><%= child_model.name %> <%= attribute.column.human_name %>:</b>
|
14
|
+
<%%=h <%= child_model.name.underscore%>.<%= attribute.name %> %>
|
15
|
+
</p>
|
16
|
+
<% end -%>
|
17
|
+
</div>
|
18
|
+
<%% end %>
|
19
|
+
|
20
|
+
<% end -%>
|
21
|
+
<%%= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>) %> |
|
22
|
+
<%%= link_to 'Back', <%= plural_name %>_path %>
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module ViewMapper
|
2
|
+
module HasManyView
|
3
|
+
|
4
|
+
attr_reader :child_models
|
5
|
+
|
6
|
+
def source_root_for_view
|
7
|
+
File.dirname(__FILE__) + "/has_many_templates"
|
8
|
+
end
|
9
|
+
|
10
|
+
def manifest
|
11
|
+
m = super.edit do |action|
|
12
|
+
action unless is_model_dependency_action(action) || is_view_show(action) || !valid
|
13
|
+
end
|
14
|
+
add_model_actions(m) if valid && !view_only?
|
15
|
+
if valid
|
16
|
+
m.template(
|
17
|
+
"view_show.html.erb",
|
18
|
+
File.join('app/views', controller_class_path, controller_file_name, "show.html.erb"),
|
19
|
+
{ :assigns => { :child_models => child_models } }
|
20
|
+
)
|
21
|
+
m.template(
|
22
|
+
"view_form.html.erb",
|
23
|
+
File.join('app/views', controller_class_path, controller_file_name, "_form.html.erb")
|
24
|
+
)
|
25
|
+
child_models.each do |child_model|
|
26
|
+
m.template(
|
27
|
+
"view_child_form.html.erb",
|
28
|
+
File.join('app/views', controller_class_path, controller_file_name, "_#{child_model.name.underscore}.html.erb"),
|
29
|
+
{ :assigns => { :child_model => child_model } }
|
30
|
+
|
31
|
+
)
|
32
|
+
end
|
33
|
+
m.file('nested_attributes.js', 'public/javascripts/nested_attributes.js')
|
34
|
+
end
|
35
|
+
m
|
36
|
+
end
|
37
|
+
|
38
|
+
def is_model_dependency_action(action)
|
39
|
+
action[0] == :dependency && action[1].include?('model')
|
40
|
+
end
|
41
|
+
|
42
|
+
def is_view_show(action)
|
43
|
+
action[0] == :template && action[1].include?('view_show.html.erb')
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_model_actions(m)
|
47
|
+
m.directory(File.join('test/fixtures', class_path))
|
48
|
+
m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
|
49
|
+
m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
|
50
|
+
unless options[:skip_fixture]
|
51
|
+
m.template 'fixtures.yml', File.join('test/fixtures', "#{table_name}.yml")
|
52
|
+
end
|
53
|
+
unless options[:skip_migration]
|
54
|
+
m.migration_template 'migration.rb',
|
55
|
+
'db/migrate',
|
56
|
+
:assigns => { :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}" },
|
57
|
+
:migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def child_models
|
62
|
+
@child_models ||= find_child_models
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_child_models
|
66
|
+
if view_param
|
67
|
+
view_param.split(',').collect { |param| ModelInfo.new(param.singularize) }
|
68
|
+
elsif view_only?
|
69
|
+
model.child_models
|
70
|
+
else
|
71
|
+
[]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def validate
|
76
|
+
super
|
77
|
+
@valid &&= validate_child_models
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_child_models
|
81
|
+
cms = child_models
|
82
|
+
if cms.empty?
|
83
|
+
if view_only?
|
84
|
+
logger.error "No has_many associations exist in class #{model.name}."
|
85
|
+
else
|
86
|
+
logger.error "No has_many association specified."
|
87
|
+
end
|
88
|
+
return false
|
89
|
+
end
|
90
|
+
cms.reject! { |child_model| !validate_child_model(child_model) }
|
91
|
+
@child_models = cms
|
92
|
+
!cms.empty?
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate_child_model(child_model)
|
96
|
+
if !child_model.valid?
|
97
|
+
logger.error child_model.error
|
98
|
+
return false
|
99
|
+
elsif view_only? && !model.accepts_nested_attributes_for?(child_model)
|
100
|
+
logger.warning "Model #{model.name} does not accept nested attributes for model #{child_model.name}."
|
101
|
+
return false
|
102
|
+
else
|
103
|
+
if child_model.has_many?(class_name.pluralize) || child_model.has_and_belongs_to_many?(class_name.pluralize)
|
104
|
+
true
|
105
|
+
elsif !child_model.belongs_to?(class_name)
|
106
|
+
logger.warning "Model #{child_model.name} does not contain a belongs_to association for #{class_name}."
|
107
|
+
return false
|
108
|
+
elsif !child_model.has_foreign_key_for?(class_name)
|
109
|
+
logger.warning "Model #{child_model.name} does not contain a foreign key for #{class_name}."
|
110
|
+
return false
|
111
|
+
end
|
112
|
+
end
|
113
|
+
true
|
114
|
+
end
|
115
|
+
|
116
|
+
def validate_child_model_associations(child_model)
|
117
|
+
if child_model.belongs_to?(class_name)
|
118
|
+
true
|
119
|
+
else
|
120
|
+
child_model.has_many?(class_name.pluralize) || child_model.has_and_belongs_to_many?(class_name.pluralize)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|