sob-shoulda_generator 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/Manifest +32 -0
- data/README.markdown +81 -0
- data/Rakefile +26 -0
- data/TODO +8 -0
- data/VERSION.yml +4 -0
- data/rails_generators/shoulda_model/USAGE +27 -0
- data/rails_generators/shoulda_model/shoulda_model_generator.rb +49 -0
- data/rails_generators/shoulda_model/templates/factory.rb +5 -0
- data/rails_generators/shoulda_model/templates/fixtures.yml +19 -0
- data/rails_generators/shoulda_model/templates/migration.rb +16 -0
- data/rails_generators/shoulda_model/templates/model.rb +2 -0
- data/rails_generators/shoulda_model/templates/unit_test.rb +7 -0
- data/rails_generators/shoulda_scaffold/USAGE +34 -0
- data/rails_generators/shoulda_scaffold/shoulda_scaffold_generator.rb +163 -0
- data/rails_generators/shoulda_scaffold/templates/controller.rb +90 -0
- data/rails_generators/shoulda_scaffold/templates/erb/_form.html.erb +8 -0
- data/rails_generators/shoulda_scaffold/templates/erb/edit.html.erb +12 -0
- data/rails_generators/shoulda_scaffold/templates/erb/index.html.erb +22 -0
- data/rails_generators/shoulda_scaffold/templates/erb/layout.html.erb +22 -0
- data/rails_generators/shoulda_scaffold/templates/erb/new.html.erb +8 -0
- data/rails_generators/shoulda_scaffold/templates/erb/show.html.erb +12 -0
- data/rails_generators/shoulda_scaffold/templates/functional_test/basic.rb +292 -0
- data/rails_generators/shoulda_scaffold/templates/haml/_form.html.haml +11 -0
- data/rails_generators/shoulda_scaffold/templates/haml/edit.html.haml +2 -0
- data/rails_generators/shoulda_scaffold/templates/haml/index.html.haml +20 -0
- data/rails_generators/shoulda_scaffold/templates/haml/layout.html.haml +26 -0
- data/rails_generators/shoulda_scaffold/templates/haml/new.html.haml +2 -0
- data/rails_generators/shoulda_scaffold/templates/haml/show.html.haml +10 -0
- data/rails_generators/shoulda_scaffold/templates/helper.rb +2 -0
- data/rails_generators/shoulda_scaffold/templates/performance_test/browser_test.rb +32 -0
- data/rails_generators/shoulda_scaffold/templates/stylesheets/basic.css +4 -0
- data/rails_generators/shoulda_scaffold/templates/yui/reset-fonts-grids.css +9 -0
- data/test/fixtures/about_yml_plugins/bad_about_yml/about.yml +1 -0
- data/test/fixtures/about_yml_plugins/bad_about_yml/init.rb +1 -0
- data/test/fixtures/about_yml_plugins/plugin_without_about_yml/init.rb +1 -0
- data/test/fixtures/eager/zoo.rb +3 -0
- data/test/fixtures/eager/zoo/reptile_house.rb +2 -0
- data/test/fixtures/environment_with_constant.rb +1 -0
- data/test/fixtures/lib/generators/missing_class/missing_class_generator.rb +0 -0
- data/test/fixtures/lib/generators/working/working_generator.rb +2 -0
- data/test/fixtures/plugins/alternate/a/generators/a_generator/a_generator.rb +4 -0
- data/test/fixtures/plugins/default/gemlike/init.rb +1 -0
- data/test/fixtures/plugins/default/gemlike/lib/gemlike.rb +2 -0
- data/test/fixtures/plugins/default/gemlike/rails/init.rb +7 -0
- data/test/fixtures/plugins/default/plugin_with_no_lib_dir/init.rb +0 -0
- data/test/fixtures/plugins/default/stubby/about.yml +2 -0
- data/test/fixtures/plugins/default/stubby/generators/stubby_generator/stubby_generator.rb +4 -0
- data/test/fixtures/plugins/default/stubby/init.rb +7 -0
- data/test/fixtures/plugins/default/stubby/lib/stubby_mixin.rb +2 -0
- data/test/rails_generators/shoulda_model_generator_test.rb +39 -0
- data/test/shoulda_macros/generator_macros.rb +36 -0
- data/test/stolen_from_railties.rb +288 -0
- data/test/test_helper.rb +41 -0
- metadata +152 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
- form_for(@<%= controller_singular_name %>) do |f|
|
2
|
+
%fieldset
|
3
|
+
%dl
|
4
|
+
%dt= f.label(:id)
|
5
|
+
%dd= f.text_field(:id)
|
6
|
+
<% for attribute in attributes -%>
|
7
|
+
%dt= f.label(:<%= attribute.name %>)
|
8
|
+
%dd= f.<%= attribute.field_type %> :<%= attribute.name %>
|
9
|
+
<% end -%>
|
10
|
+
%p.submitBox== #{link_to('cancel', :back)} or #{f.submit}
|
11
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
%h2 Listing <%= controller_plural_name.humanize %>
|
2
|
+
|
3
|
+
%table
|
4
|
+
%tr
|
5
|
+
<% for attribute in attributes -%>
|
6
|
+
%th <%= attribute.column.human_name %>
|
7
|
+
<% end -%>
|
8
|
+
|
9
|
+
- for <%= controller_singular_name %> in @<%= controller_plural_name %>
|
10
|
+
%tr
|
11
|
+
<% for attribute in attributes -%>
|
12
|
+
%td= h <%= controller_singular_name %>.<%= attribute.name %>
|
13
|
+
<% end -%>
|
14
|
+
%td.tools
|
15
|
+
%ul
|
16
|
+
%li= link_to('show', <%= controller_member_path %>_path(<%= controller_singular_name %>))
|
17
|
+
%li= link_to('edit', edit_<%= controller_member_path %>_path(<%= controller_singular_name %>))
|
18
|
+
%li= link_to('remove', <%= controller_member_path %>_path(<%= controller_singular_name %>), :method => :delete, :confirm => 'Are you sure?')
|
19
|
+
|
20
|
+
%p= link_to 'New <%= controller_singular_name.humanize %>', new_<%= controller_member_path %>_path()
|
@@ -0,0 +1,26 @@
|
|
1
|
+
!!! XML
|
2
|
+
!!! 1.1
|
3
|
+
%html{:xmlns => "http://www.w3.org/1999/xhtml"}
|
4
|
+
%head
|
5
|
+
%meta{"http-equiv" => "Content-type", :content => "text/html; charset=utf-8"}/
|
6
|
+
%title= "#{@page_title}" || "#{controller.controller_name}: #{controller.action_name}"
|
7
|
+
=stylesheet_link_tag 'reset-fonts-grids', 'application', :cache => true, :media => 'screen'
|
8
|
+
%meta{"name" => "copyright", :content => ""}/
|
9
|
+
%meta{"name" => "description", :content => "#{page_description rescue nil}"}/
|
10
|
+
%meta{"name" => "keywords", :content => "#{@page_keywords rescue nil}"}/
|
11
|
+
%link{"rel" => "shortcut icon", :href => "", :type => ""}/
|
12
|
+
%body
|
13
|
+
#hd{:class => "yui-d0"}
|
14
|
+
#hd-content{:class => "yui-d3f"}
|
15
|
+
%h1= link_to(image_tag('', :alt => ''), root_path())
|
16
|
+
%ul{:id => "hd-nav"}
|
17
|
+
#bd{:class => "yui-d0"}
|
18
|
+
#bd-content{:class => "yui-d3f"}
|
19
|
+
%p#flash-notice.flash{:style => "display: none;"}
|
20
|
+
%p#flash-warning.flash{:style => "display: none;"}
|
21
|
+
%p#flash-error.flash{:style => "display: none;"}
|
22
|
+
=yield
|
23
|
+
#ft{:class => "yui-d0"}
|
24
|
+
#ft-content{:class => "yui-d3f"}
|
25
|
+
%p#copyright= "Copyright © 2009 #{link_to('', root_path())}"
|
26
|
+
=javascript_include_tag 'jquery', 'scaffold', 'application', :cache => true
|
@@ -0,0 +1,10 @@
|
|
1
|
+
%dl
|
2
|
+
<% for attribute in attributes -%>
|
3
|
+
%dt <%= attribute.column.human_name %>
|
4
|
+
%dd= h @<%= singular_name %>.<%= attribute.name %>
|
5
|
+
<% end -%>
|
6
|
+
|
7
|
+
%p
|
8
|
+
= link_to 'Edit', edit_<%= controller_member_path %>_path(@<%= controller_singular_name %>)
|
9
|
+
|
|
10
|
+
= link_to 'Back', <%= controller_collection_path %>_path()
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'performance_test_help'
|
3
|
+
|
4
|
+
class <%= controller_class_name %>PerformanceTest < ActionController::PerformanceTest
|
5
|
+
def test_listing_<%= file_name %>
|
6
|
+
get '/<%= controller_collection_path.gsub('_', '/') %>'
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_adding_<%= file_name %>
|
10
|
+
get '/<%= controller_collection_path.gsub('_', '/') %>/new'
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_creating_<%= file_name %>
|
14
|
+
post '/<%= controller_collection_path.gsub('_', '/') %>', :<%= controller_singular_name %> => Factory.attributes_for(:<%= controller_singular_name %>)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_showing_<%= file_name %>
|
18
|
+
get '/<%= controller_collection_path.gsub('_', '/') %>/1'
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_editing_<%= file_name %>
|
22
|
+
get '/<%= controller_collection_path.gsub('_', '/') %>/1/edit'
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_updating_<%= file_name %>
|
26
|
+
put '/<%= controller_collection_path.gsub('_', '/') %>/1'
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_destroying_<%= file_name %>
|
30
|
+
delete '/<%= controller_collection_path.gsub('_', '/') %>/1'
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
.flash { text-align: center; padding: 7px; font-size: 100%; border-width: 1px; border-style: solid; }
|
2
|
+
.flash.notice { background-color: #d7ffd2 !important; border-color: #15b100; color: #0f7d00; }
|
3
|
+
.flash.warning { background-color: #fffad6; border-color: #efcf00; color: #837200; }
|
4
|
+
.flash.error { background-color: #ffebe8; border-color: #dd3c10; color: #aa0000; font-weight: bold; }
|
@@ -0,0 +1,9 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
|
3
|
+
Code licensed under the BSD License:
|
4
|
+
http://developer.yahoo.net/yui/license.txt
|
5
|
+
version: 3.0.0pr2
|
6
|
+
*/
|
7
|
+
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
|
8
|
+
body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
|
9
|
+
body{text-align:center;margin-left:auto;margin-right:auto;}.yui-d0,.yui-d1,.yui-d1f,.yui-d2,.yui-d2f,.yui-d3,.yui-d3f{margin:auto;text-align:left;width:57.69em;*width:56.25em;}.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6{margin:auto;text-align:left;width:100%;}.yui-d0{margin:auto 10px;width:auto;}.yui-d0f{width:100%;}.yui-d2{width:73.076em;*width:71.25em;}.yui-d2f{width:950px;}.yui-d3{width:74.923em;*width:73.05em;}.yui-d3f{width:974px;}.yui-b{position:relative;}.yui-b{_position:static;}.yui-main .yui-b{position:static;}.yui-main{width:100%;}.yui-t1 .yui-main,.yui-t2 .yui-main,.yui-t3 .yui-main{float:right;margin-left:-25em;}.yui-t4 .yui-main,.yui-t5 .yui-main,.yui-t6 .yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 .yui-main .yui-b{margin-left:13.30769em;*margin-left:12.975em;}.yui-t2 .yui-b{float:left;width:13.84615em;*width:13.50em;}.yui-t2 .yui-main .yui-b{margin-left:14.84615em;*margin-left:14.475em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 .yui-main .yui-b{margin-left:24.0769em;*margin-left:23.475em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 .yui-main .yui-b{margin-right:14.8456em;*margin-right:14.475em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 .yui-main .yui-b{margin-right:19.4615em;*margin-right:18.975em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 .yui-main .yui-b{margin-right:24.0769em;*margin-right:23.475em;}.yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:2.0%;}.yui-gb .yui-u{*width:31.8%;*margin-left:1.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;_width:65.7%;}.yui-gd div.first{width:32%;_width:31.5%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;_width:74%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;_width:23.8%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}.yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#bd:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after,.yui-t1:after,.yui-t2:after,.yui-t3:after,.yui-t4:after,.yui-t5:after,.yui-t6:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#bd,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6{zoom:1;}
|
@@ -0,0 +1 @@
|
|
1
|
+
# an empty YAML file - any content in here seems to get parsed as a string
|
@@ -0,0 +1 @@
|
|
1
|
+
# intentionally empty
|
@@ -0,0 +1 @@
|
|
1
|
+
# intentionally empty
|
@@ -0,0 +1 @@
|
|
1
|
+
$initialize_test_set_from_env = 'success'
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
raise 'This init.rb should not be evaluated because rails/init.rb exists'
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# I have access to my directory and the Rails config.
|
2
|
+
raise 'directory expected but undefined in init.rb' unless defined? directory
|
3
|
+
raise 'config expected but undefined in init.rb' unless defined? config
|
4
|
+
|
5
|
+
# My lib/ dir must be in the load path.
|
6
|
+
require 'gemlike'
|
7
|
+
raise 'missing mixin from my lib/ dir' unless defined? Gemlike
|
File without changes
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# I have access to my directory and the Rails config.
|
2
|
+
raise 'directory expected but undefined in init.rb' unless defined? directory
|
3
|
+
raise 'config expected but undefined in init.rb' unless defined? config
|
4
|
+
|
5
|
+
# My lib/ dir must be in the load path.
|
6
|
+
require 'stubby_mixin'
|
7
|
+
raise 'missing mixin from my lib/ dir' unless defined? StubbyMixin
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
|
4
|
+
class ShouldaModelGeneratorTest < GeneratorTestCase
|
5
|
+
context "running the default generator" do
|
6
|
+
setup do
|
7
|
+
run_generator('shoulda_model', %w(Product name:string supplier_id:integer created_at:timestamp))
|
8
|
+
end
|
9
|
+
|
10
|
+
should_generate_model :product
|
11
|
+
should_generate_factory :product
|
12
|
+
should_generate_unit_test :product
|
13
|
+
should_generate_migration :create_products
|
14
|
+
|
15
|
+
should "generate migration" do
|
16
|
+
assert_generated_migration :create_products do |t|
|
17
|
+
assert_generated_column t, :name, :string
|
18
|
+
assert_generated_column t, :supplier_id, :integer
|
19
|
+
assert_generated_column t, :created_at, :timestamp
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "running the generator, when skipping factory and migration" do
|
25
|
+
setup do
|
26
|
+
run_generator('shoulda_model', %w(Product name:string supplier_id:integer created_at:timestamp --skip-factory))
|
27
|
+
end
|
28
|
+
|
29
|
+
should_generate_model :product
|
30
|
+
should_not_generate_factory :product
|
31
|
+
should_generate_unit_test :product
|
32
|
+
should_generate_migration :create_products
|
33
|
+
|
34
|
+
should "not generate migration" do
|
35
|
+
assert_skipped_migration :create_products
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Test::Unit::TestCase
|
2
|
+
class << self
|
3
|
+
def should_generate_model(model)
|
4
|
+
should "generate #{model} model" do
|
5
|
+
assert_generated_model_for(model) do |body|
|
6
|
+
yield body if block_given?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def should_generate_factory(model)
|
12
|
+
should "generate #{model} factory" do
|
13
|
+
assert_generated_factory_for(model)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def should_generate_unit_test(model)
|
18
|
+
should "generate #{model} unit test" do
|
19
|
+
assert_generated_unit_test_for(model)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def should_generate_migration(migration)
|
24
|
+
should "generate a #{migration} migration" do
|
25
|
+
assert_generated_migration migration
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def should_not_generate_factory(model)
|
30
|
+
should "not generate #{model} factory" do
|
31
|
+
deny_generated_factory_for(:product)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,288 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
# Mock out what we need from AR::Base
|
5
|
+
module ActiveRecord
|
6
|
+
class Base
|
7
|
+
class << self
|
8
|
+
attr_accessor :pluralize_table_names, :timestamped_migrations
|
9
|
+
end
|
10
|
+
self.pluralize_table_names = true
|
11
|
+
self.timestamped_migrations = true
|
12
|
+
end
|
13
|
+
|
14
|
+
module ConnectionAdapters
|
15
|
+
class Column
|
16
|
+
attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale
|
17
|
+
|
18
|
+
def initialize(name, default, sql_type = nil)
|
19
|
+
@name = name
|
20
|
+
@default = default
|
21
|
+
@type = @sql_type = sql_type
|
22
|
+
end
|
23
|
+
|
24
|
+
def human_name
|
25
|
+
@name.humanize
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Mock up necessities from ActionView
|
32
|
+
module ActionView
|
33
|
+
module Helpers
|
34
|
+
module ActionRecordHelper; end
|
35
|
+
class InstanceTag; end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Set RAILS_ROOT appropriately fixture generation
|
40
|
+
tmp_dir = "#{File.dirname(__FILE__)}/fixtures/tmp"
|
41
|
+
|
42
|
+
if defined? RAILS_ROOT
|
43
|
+
RAILS_ROOT.replace tmp_dir
|
44
|
+
else
|
45
|
+
RAILS_ROOT = tmp_dir
|
46
|
+
end
|
47
|
+
FileUtils.mkdir_p RAILS_ROOT
|
48
|
+
|
49
|
+
# $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
|
50
|
+
require 'initializer'
|
51
|
+
|
52
|
+
# Mocks out the configuration
|
53
|
+
module Rails
|
54
|
+
def self.configuration
|
55
|
+
Rails::Configuration.new
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
require 'rails_generator'
|
60
|
+
|
61
|
+
class GeneratorTestCase < Test::Unit::TestCase
|
62
|
+
include FileUtils
|
63
|
+
|
64
|
+
def setup
|
65
|
+
ActiveRecord::Base.pluralize_table_names = true
|
66
|
+
|
67
|
+
mkdir_p "#{RAILS_ROOT}/app/views/layouts"
|
68
|
+
mkdir_p "#{RAILS_ROOT}/config"
|
69
|
+
mkdir_p "#{RAILS_ROOT}/db"
|
70
|
+
mkdir_p "#{RAILS_ROOT}/test/fixtures"
|
71
|
+
mkdir_p "#{RAILS_ROOT}/public/stylesheets"
|
72
|
+
|
73
|
+
File.open("#{RAILS_ROOT}/config/routes.rb", 'w') do |f|
|
74
|
+
f << "ActionController::Routing::Routes.draw do |map|\n\nend"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def teardown
|
79
|
+
rm_rf "#{RAILS_ROOT}/app"
|
80
|
+
rm_rf "#{RAILS_ROOT}/test"
|
81
|
+
rm_rf "#{RAILS_ROOT}/config"
|
82
|
+
rm_rf "#{RAILS_ROOT}/db"
|
83
|
+
rm_rf "#{RAILS_ROOT}/public"
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_truth
|
87
|
+
# don't complain, test/unit
|
88
|
+
end
|
89
|
+
|
90
|
+
# Instantiates the Generator.
|
91
|
+
def build_generator(name, params)
|
92
|
+
Rails::Generator::Base.instance(name, params)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Runs the +create+ command (like the command line does).
|
96
|
+
def run_generator(name, params)
|
97
|
+
silence_generator do
|
98
|
+
build_generator(name, params).command(:create).invoke!
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Silences the logger temporarily and returns the output as a String.
|
103
|
+
def silence_generator
|
104
|
+
logger_original = Rails::Generator::Base.logger
|
105
|
+
myout = StringIO.new
|
106
|
+
Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new(myout)
|
107
|
+
yield if block_given?
|
108
|
+
Rails::Generator::Base.logger = logger_original
|
109
|
+
myout.string
|
110
|
+
end
|
111
|
+
|
112
|
+
# Asserts that the given controller was generated.
|
113
|
+
# It takes a name or symbol without the <tt>_controller</tt> part and an optional super class.
|
114
|
+
# The contents of the class source file is passed to a block.
|
115
|
+
def assert_generated_controller_for(name, parent = "ApplicationController")
|
116
|
+
assert_generated_class "app/controllers/#{name.to_s.underscore}_controller", parent do |body|
|
117
|
+
yield body if block_given?
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Asserts that the given model was generated.
|
122
|
+
# It takes a name or symbol and an optional super class.
|
123
|
+
# The contents of the class source file is passed to a block.
|
124
|
+
def assert_generated_model_for(name, parent = "ActiveRecord::Base")
|
125
|
+
assert_generated_class "app/models/#{name.to_s.underscore}", parent do |body|
|
126
|
+
yield body if block_given?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Asserts that the given helper was generated.
|
131
|
+
# It takes a name or symbol without the <tt>_helper</tt> part.
|
132
|
+
# The contents of the module source file is passed to a block.
|
133
|
+
def assert_generated_helper_for(name)
|
134
|
+
assert_generated_module "app/helpers/#{name.to_s.underscore}_helper" do |body|
|
135
|
+
yield body if block_given?
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Asserts that the given functional test was generated.
|
140
|
+
# It takes a name or symbol without the <tt>_controller_test</tt> part and an optional super class.
|
141
|
+
# The contents of the class source file is passed to a block.
|
142
|
+
def assert_generated_functional_test_for(name, parent = "ActionController::TestCase")
|
143
|
+
assert_generated_class "test/functional/#{name.to_s.underscore}_controller_test",parent do |body|
|
144
|
+
yield body if block_given?
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Asserts that the given unit test was generated.
|
149
|
+
# It takes a name or symbol without the <tt>_test</tt> part and an optional super class.
|
150
|
+
# The contents of the class source file is passed to a block.
|
151
|
+
def assert_generated_unit_test_for(name, parent = "ActiveSupport::TestCase")
|
152
|
+
assert_generated_class "test/unit/#{name.to_s.underscore}_test", parent do |body|
|
153
|
+
yield body if block_given?
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Asserts that the given file was generated.
|
158
|
+
# The contents of the file is passed to a block.
|
159
|
+
def assert_generated_file(path)
|
160
|
+
assert_file_exists(path)
|
161
|
+
File.open("#{RAILS_ROOT}/#{path}") do |f|
|
162
|
+
yield f.read if block_given?
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# asserts that the given file exists
|
167
|
+
def assert_file_exists(path)
|
168
|
+
assert File.exist?("#{RAILS_ROOT}/#{path}"),
|
169
|
+
"The file '#{RAILS_ROOT}/#{path}' should exist"
|
170
|
+
end
|
171
|
+
|
172
|
+
# Asserts that the given class source file was generated.
|
173
|
+
# It takes a path without the <tt>.rb</tt> part and an optional super class.
|
174
|
+
# The contents of the class source file is passed to a block.
|
175
|
+
def assert_generated_class(path, parent = nil)
|
176
|
+
# FIXME: Sucky way to detect namespaced classes
|
177
|
+
if path.split('/').size > 3
|
178
|
+
path =~ /\/?(\d+_)?(\w+)\/(\w+)$/
|
179
|
+
class_name = "#{$2.camelize}::#{$3.camelize}"
|
180
|
+
else
|
181
|
+
path =~ /\/?(\d+_)?(\w+)$/
|
182
|
+
class_name = $2.camelize
|
183
|
+
end
|
184
|
+
|
185
|
+
assert_generated_file("#{path}.rb") do |body|
|
186
|
+
assert_match /class #{class_name}#{parent.nil? ? '':" < #{parent}"}/, body, "the file '#{path}.rb' should be a class"
|
187
|
+
yield body if block_given?
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Asserts that the given module source file was generated.
|
192
|
+
# It takes a path without the <tt>.rb</tt> part.
|
193
|
+
# The contents of the class source file is passed to a block.
|
194
|
+
def assert_generated_module(path)
|
195
|
+
# FIXME: Sucky way to detect namespaced modules
|
196
|
+
if path.split('/').size > 3
|
197
|
+
path =~ /\/?(\w+)\/(\w+)$/
|
198
|
+
module_name = "#{$1.camelize}::#{$2.camelize}"
|
199
|
+
else
|
200
|
+
path =~ /\/?(\w+)$/
|
201
|
+
module_name = $1.camelize
|
202
|
+
end
|
203
|
+
|
204
|
+
assert_generated_file("#{path}.rb") do |body|
|
205
|
+
assert_match /module #{module_name}/, body, "the file '#{path}.rb' should be a module"
|
206
|
+
yield body if block_given?
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# Asserts that the given CSS stylesheet file was generated.
|
211
|
+
# It takes a path without the <tt>.css</tt> part.
|
212
|
+
# The contents of the stylesheet source file is passed to a block.
|
213
|
+
def assert_generated_stylesheet(path)
|
214
|
+
assert_generated_file("public/stylesheets/#{path}.css") do |body|
|
215
|
+
yield body if block_given?
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Asserts that the given YAML file was generated.
|
220
|
+
# It takes a path without the <tt>.yml</tt> part.
|
221
|
+
# The parsed YAML tree is passed to a block.
|
222
|
+
def assert_generated_yaml(path)
|
223
|
+
assert_generated_file("#{path}.yml") do |body|
|
224
|
+
yaml = YAML.load(body)
|
225
|
+
assert yaml, 'YAML data missing'
|
226
|
+
yield yaml if block_given?
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# Asserts that the given fixtures YAML file was generated.
|
231
|
+
# It takes a fixture name without the <tt>.yml</tt> part.
|
232
|
+
# The parsed YAML tree is passed to a block.
|
233
|
+
def assert_generated_fixtures_for(name)
|
234
|
+
assert_generated_yaml "test/fixtures/#{name.to_s.underscore}" do |yaml|
|
235
|
+
yield yaml if block_given?
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Asserts that the given views were generated.
|
240
|
+
# It takes a controller name and a list of views (including extensions).
|
241
|
+
# The body of each view is passed to a block.
|
242
|
+
def assert_generated_views_for(name, *actions)
|
243
|
+
actions.each do |action|
|
244
|
+
assert_generated_file("app/views/#{name.to_s.underscore}/#{action}") do |body|
|
245
|
+
yield body if block_given?
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def assert_generated_migration(name, parent = "ActiveRecord::Migration")
|
251
|
+
file = Dir.glob("#{RAILS_ROOT}/db/migrate/*_#{name.to_s.underscore}.rb").first
|
252
|
+
file = file.match(/db\/migrate\/[0-9]+_\w+/).to_s
|
253
|
+
assert_generated_class file, parent do |body|
|
254
|
+
assert_match /timestamps/, body, "should have timestamps defined"
|
255
|
+
yield body if block_given?
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# Asserts that the given migration file was not generated.
|
260
|
+
# It takes the name of the migration as a parameter.
|
261
|
+
def assert_skipped_migration(name)
|
262
|
+
migration_file = "#{RAILS_ROOT}/db/migrate/001_#{name.to_s.underscore}.rb"
|
263
|
+
assert !File.exist?(migration_file), "should not create migration #{migration_file}"
|
264
|
+
end
|
265
|
+
|
266
|
+
# Asserts that the given resource was added to the routes.
|
267
|
+
def assert_added_route_for(name)
|
268
|
+
assert_generated_file("config/routes.rb") do |body|
|
269
|
+
assert_match /map.resources :#{name.to_s.underscore}/, body,
|
270
|
+
"should add route for :#{name.to_s.underscore}"
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# Asserts that the given methods are defined in the body.
|
275
|
+
# This does assume standard rails code conventions with regards to the source code.
|
276
|
+
# The body of each individual method is passed to a block.
|
277
|
+
def assert_has_method(body, *methods)
|
278
|
+
methods.each do |name|
|
279
|
+
assert body =~ /^ def #{name}(\(.+\))?\n((\n| .*\n)*) end/, "should have method #{name}"
|
280
|
+
yield(name, $2) if block_given?
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# Asserts that the given column is defined in the migration.
|
285
|
+
def assert_generated_column(body, name, type)
|
286
|
+
assert_match /t\.#{type.to_s} :#{name.to_s}/, body, "should have column #{name.to_s} defined"
|
287
|
+
end
|
288
|
+
end
|