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.
Files changed (40) hide show
  1. data/Rakefile +5 -3
  2. data/VERSION +1 -1
  3. data/generators/view_for/view_for_generator.rb +4 -37
  4. data/lib/view_mapper/has_many_templates/controller.rb +85 -0
  5. data/lib/view_mapper/has_many_templates/fixtures.yml +19 -0
  6. data/lib/view_mapper/has_many_templates/functional_test.rb +45 -0
  7. data/lib/view_mapper/has_many_templates/helper.rb +18 -0
  8. data/lib/view_mapper/has_many_templates/helper_test.rb +4 -0
  9. data/lib/view_mapper/has_many_templates/layout.html.erb +19 -0
  10. data/lib/view_mapper/has_many_templates/migration.rb +16 -0
  11. data/lib/view_mapper/has_many_templates/model.rb +23 -0
  12. data/lib/view_mapper/has_many_templates/nested_attributes.js +13 -0
  13. data/lib/view_mapper/has_many_templates/style.css +58 -0
  14. data/lib/view_mapper/has_many_templates/unit_test.rb +8 -0
  15. data/lib/view_mapper/has_many_templates/view_child_form.html.erb +12 -0
  16. data/lib/view_mapper/has_many_templates/view_edit.html.erb +11 -0
  17. data/lib/view_mapper/has_many_templates/view_form.html.erb +20 -0
  18. data/lib/view_mapper/has_many_templates/view_index.html.erb +24 -0
  19. data/lib/view_mapper/has_many_templates/view_new.html.erb +10 -0
  20. data/lib/view_mapper/has_many_templates/view_show.html.erb +22 -0
  21. data/lib/view_mapper/has_many_view.rb +124 -0
  22. data/lib/view_mapper/model_info.rb +157 -0
  23. data/lib/view_mapper/paperclip_view.rb +5 -40
  24. data/lib/view_mapper/view_mapper.rb +2 -2
  25. data/lib/view_mapper.rb +2 -0
  26. data/test/expected_templates/has_many/_form.html.erb +26 -0
  27. data/test/expected_templates/has_many/_person.html.erb +18 -0
  28. data/test/expected_templates/has_many/create_parents.rb +15 -0
  29. data/test/expected_templates/has_many/edit.html.erb +11 -0
  30. data/test/expected_templates/has_many/index.html.erb +20 -0
  31. data/test/expected_templates/has_many/new.html.erb +10 -0
  32. data/test/expected_templates/has_many/parent.rb +14 -0
  33. data/test/expected_templates/has_many/show.html.erb +33 -0
  34. data/test/has_many_view_test.rb +405 -0
  35. data/test/model_info_test.rb +81 -0
  36. data/test/paperclip_view_test.rb +4 -27
  37. data/test/test_helper.rb +82 -9
  38. data/test/view_mapper_test.rb +2 -2
  39. data/view_mapper.gemspec +41 -5
  40. 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{Generate complex view code for your models}
9
- gem.description = %Q{Generate complex view code for your models}
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://github.com/patshaughnessy/view_mapper"
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.2.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
- find_model @name
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
- @attributes_from_columns ||= attributes_from_columns
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
- @valid = !model.nil?
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,4 @@
1
+ require 'test_helper'
2
+
3
+ class <%= controller_class_name %>HelperTest < ActionView::TestCase
4
+ 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,8 @@
1
+ require 'test_helper'
2
+
3
+ class <%= class_name %>Test < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -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,10 @@
1
+ <h1>New <%= singular_name %></h1>
2
+
3
+ <%% form_for(@<%= singular_name %>) do |f| %>
4
+ <%%= render :partial => 'form', :locals => { :f => f } %>
5
+ <p>
6
+ <%%= f.submit 'Create' %>
7
+ </p>
8
+ <%% end %>
9
+
10
+ <%%= link_to 'Back', <%= plural_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