From 056fdc74d52833ac2755713e990bd9f3f9a8c415 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 16 May 2007 01:24:25 +0000 Subject: Scaffold resource is now scaffold git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6746 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- .../generators/components/scaffold/USAGE | 37 +++++++++ .../scaffold/scaffold_resource_generator.rb | 92 ++++++++++++++++++++++ .../components/scaffold/templates/controller.rb | 85 ++++++++++++++++++++ .../components/scaffold/templates/fixtures.yml | 11 +++ .../scaffold/templates/functional_test.rb | 57 ++++++++++++++ .../components/scaffold/templates/helper.rb | 2 + .../components/scaffold/templates/layout.html.erb | 17 ++++ .../components/scaffold/templates/migration.rb | 13 +++ .../components/scaffold/templates/model.rb | 2 + .../components/scaffold/templates/style.css | 74 +++++++++++++++++ .../components/scaffold/templates/unit_test.rb | 10 +++ .../scaffold/templates/view_edit.html.erb | 19 +++++ .../scaffold/templates/view_index.html.erb | 24 ++++++ .../scaffold/templates/view_new.html.erb | 18 +++++ .../scaffold/templates/view_show.html.erb | 10 +++ 15 files changed, 471 insertions(+) create mode 100644 railties/lib/rails_generator/generators/components/scaffold/USAGE create mode 100644 railties/lib/rails_generator/generators/components/scaffold/scaffold_resource_generator.rb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/fixtures.yml create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/helper.rb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/migration.rb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/model.rb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/style.css create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/unit_test.rb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb create mode 100644 railties/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb (limited to 'railties/lib/rails_generator/generators/components/scaffold') diff --git a/railties/lib/rails_generator/generators/components/scaffold/USAGE b/railties/lib/rails_generator/generators/components/scaffold/USAGE new file mode 100644 index 0000000000..60e13c770f --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/USAGE @@ -0,0 +1,37 @@ +Description: + The scaffold resource generator creates a model, a controller, and a + set of templates that's ready to use as the starting point for your + REST-like, resource-oriented application. This basically means that it + follows a set of conventions to exploit the full set of HTTP verbs + (GET/POST/PUT/DELETE) and is prepared for multi-client access (like one + view for HTML, one for an XML API, one for ATOM, etc). Everything comes + with sample unit and functional tests as well. + + The generator takes the name of the model as its first argument. This + model name is then pluralized to get the controller name. So + "scaffold_resource post" will generate a Post model and a + PostsController and will be intended for URLs like /posts and + /posts/45. + + As additional parameters, the generator will take attribute pairs + described by name and type. These attributes will be used to + prepopulate the migration to create the table for the model and to give + you a set of templates for the view. For example, "scaffold_resource + post title:string created_on:date body:text published:boolean" will + give you a model with those four attributes, forms to create and edit + those models from, and an index that'll list them all. + + You don't have to think up all attributes up front, but it's a good + idea of adding just the baseline of what's needed to start really + working with the resource. + + The generator also adds a declaration to your config/routes.rb file + to hook up the rules that'll point URLs to this new resource. If you + create a resource like "scaffold_resource post", it will add + "map.resources :posts" (notice the plural form) in the routes file, + making your new resource accessible from /posts. + +Examples: + ./script/generate scaffold_resource post # no attributes, view will be anemic + ./script/generate scaffold_resource post title:string created_on:date body:text published:boolean + ./script/generate scaffold_resource purchase order_id:integer created_at:datetime amount:decimal diff --git a/railties/lib/rails_generator/generators/components/scaffold/scaffold_resource_generator.rb b/railties/lib/rails_generator/generators/components/scaffold/scaffold_resource_generator.rb new file mode 100644 index 0000000000..a10f7f12b3 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/scaffold_resource_generator.rb @@ -0,0 +1,92 @@ +class ScaffoldResourceGenerator < Rails::Generator::NamedBase + attr_reader :controller_name, + :controller_class_path, + :controller_file_path, + :controller_class_nesting, + :controller_class_nesting_depth, + :controller_class_name, + :controller_singular_name, + :controller_plural_name + alias_method :controller_file_name, :controller_singular_name + alias_method :controller_table_name, :controller_plural_name + + def initialize(runtime_args, runtime_options = {}) + super + + @controller_name = @name.pluralize + + base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name) + @controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name) + + if @controller_class_nesting.empty? + @controller_class_name = @controller_class_name_without_nesting + else + @controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}" + end + end + + def manifest + record do |m| + # Check for class naming collisions. + m.class_collisions(controller_class_path, "#{controller_class_name}Controller", "#{controller_class_name}Helper") + m.class_collisions(class_path, "#{class_name}") + + # Controller, helper, views, and test directories. + m.directory(File.join('app/models', class_path)) + m.directory(File.join('app/controllers', controller_class_path)) + m.directory(File.join('app/helpers', controller_class_path)) + m.directory(File.join('app/views', controller_class_path, controller_file_name)) + m.directory(File.join('test/functional', controller_class_path)) + m.directory(File.join('test/unit', class_path)) + + for action in scaffold_views + m.template( + "view_#{action}.html.erb", + File.join('app/views', controller_class_path, controller_file_name, "#{action}.html.erb") + ) + end + + # Layout and stylesheet. + m.template('layout.html.erb', File.join('app/views/layouts', controller_class_path, "#{controller_file_name}.html.erb")) + m.template('style.css', 'public/stylesheets/scaffold.css') + + m.template('model.rb', File.join('app/models', class_path, "#{file_name}.rb")) + + m.template( + 'controller.rb', File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb") + ) + + m.template('functional_test.rb', File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb")) + m.template('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb")) + m.template('unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")) + m.template('fixtures.yml', File.join('test/fixtures', "#{table_name}.yml")) + + unless options[:skip_migration] + m.migration_template( + 'migration.rb', 'db/migrate', + :assigns => { + :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}", + :attributes => attributes + }, + :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}" + ) + end + + m.route_resources controller_file_name + end + end + + protected + # Override with your own usage banner. + def banner + "Usage: #{$0} scaffold_resource ModelName [field:type, field:type]" + end + + def scaffold_views + %w[ index show new edit ] + end + + def model_name + class_name.demodulize + end +end diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb new file mode 100644 index 0000000000..f28f364af0 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb @@ -0,0 +1,85 @@ +class <%= controller_class_name %>Controller < ApplicationController + # GET /<%= table_name %> + # GET /<%= table_name %>.xml + def index + @<%= table_name %> = <%= class_name %>.find(:all) + + respond_to do |format| + format.html # index.html.erb + format.xml { render :xml => @<%= table_name %> } + end + end + + # GET /<%= table_name %>/1 + # GET /<%= table_name %>/1.xml + def show + @<%= file_name %> = <%= class_name %>.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.xml { render :xml => @<%= file_name %> } + end + end + + # GET /<%= table_name %>/new + # GET /<%= table_name %>/new.xml + def new + @<%= file_name %> = <%= class_name %>.new + + respond_to do |format| + format.html # new.html.erb + format.xml { render :xml => @<%= file_name %> } + end + end + + # GET /<%= table_name %>/1;edit + def edit + @<%= file_name %> = <%= class_name %>.find(params[:id]) + end + + # POST /<%= table_name %> + # POST /<%= table_name %>.xml + def create + @<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>]) + + respond_to do |format| + if @<%= file_name %>.save + flash[:notice] = '<%= class_name %> was successfully created.' + format.html { redirect_to <%= file_name %>_url(@<%= file_name %>) } + format.xml { render :xml => @<%= file_name %>, :status => :created, :location => <%= file_name %>_url(@<%= file_name %>) } + else + format.html { render :action => "new" } + format.xml { render :xml => @<%= file_name %>.errors } + end + end + end + + # PUT /<%= table_name %>/1 + # PUT /<%= table_name %>/1.xml + def update + @<%= file_name %> = <%= class_name %>.find(params[:id]) + + respond_to do |format| + if @<%= file_name %>.update_attributes(params[:<%= file_name %>]) + flash[:notice] = '<%= class_name %> was successfully updated.' + format.html { redirect_to <%= file_name %>_url(@<%= file_name %>) } + format.xml { head :ok } + else + format.html { render :action => "edit" } + format.xml { render :xml => @<%= file_name %>.errors } + end + end + end + + # DELETE /<%= table_name %>/1 + # DELETE /<%= table_name %>/1.xml + def destroy + @<%= file_name %> = <%= class_name %>.find(params[:id]) + @<%= file_name %>.destroy + + respond_to do |format| + format.html { redirect_to <%= table_name %>_url } + format.xml { head :ok } + end + end +end diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/fixtures.yml b/railties/lib/rails_generator/generators/components/scaffold/templates/fixtures.yml new file mode 100644 index 0000000000..9f5ae29a81 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/fixtures.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html +one: + id: 1 +<% for attribute in attributes -%> + <%= attribute.name %>: <%= attribute.default %> +<% end -%> +two: + id: 2 +<% for attribute in attributes -%> + <%= attribute.name %>: <%= attribute.default %> +<% end -%> \ No newline at end of file diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb new file mode 100644 index 0000000000..0c68fd3122 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb @@ -0,0 +1,57 @@ +require File.dirname(__FILE__) + '<%= '/..' * controller_class_nesting_depth %>/../test_helper' +require '<%= controller_file_path %>_controller' + +# Re-raise errors caught by the controller. +class <%= controller_class_name %>Controller; def rescue_action(e) raise e end; end + +class <%= controller_class_name %>ControllerTest < Test::Unit::TestCase + fixtures :<%= table_name %> + + def setup + @controller = <%= controller_class_name %>Controller.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_should_get_index + get :index + assert_response :success + assert assigns(:<%= table_name %>) + end + + def test_should_get_new + get :new + assert_response :success + end + + def test_should_create_<%= file_name %> + old_count = <%= class_name %>.count + post :create, :<%= file_name %> => { } + assert_equal old_count+1, <%= class_name %>.count + + assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>)) + end + + def test_should_show_<%= file_name %> + get :show, :id => 1 + assert_response :success + end + + def test_should_get_edit + get :edit, :id => 1 + assert_response :success + end + + def test_should_update_<%= file_name %> + put :update, :id => 1, :<%= file_name %> => { } + assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>)) + end + + def test_should_destroy_<%= file_name %> + old_count = <%= class_name %>.count + delete :destroy, :id => 1 + assert_equal old_count-1, <%= class_name %>.count + + assert_redirected_to <%= table_name %>_path + end +end diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/helper.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/helper.rb new file mode 100644 index 0000000000..9bd821b1b2 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/helper.rb @@ -0,0 +1,2 @@ +module <%= controller_class_name %>Helper +end diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb new file mode 100644 index 0000000000..5c1f304232 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb @@ -0,0 +1,17 @@ + + + + + + <%= controller_class_name %>: <%%= controller.action_name %> + <%%= stylesheet_link_tag 'scaffold' %> + + + +

<%%= flash[:notice] %>

+ +<%%= yield %> + + + diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/migration.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/migration.rb new file mode 100644 index 0000000000..cb1ddd399e --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/migration.rb @@ -0,0 +1,13 @@ +class <%= migration_name %> < ActiveRecord::Migration + def self.up + create_table :<%= table_name %> do |t| +<% for attribute in attributes -%> + t.<%= attribute.type %> :<%= attribute.name %> +<% end -%> + end + end + + def self.down + drop_table :<%= table_name %> + end +end diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/model.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/model.rb new file mode 100644 index 0000000000..8d4c89e912 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/model.rb @@ -0,0 +1,2 @@ +class <%= class_name %> < ActiveRecord::Base +end diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/style.css b/railties/lib/rails_generator/generators/components/scaffold/templates/style.css new file mode 100644 index 0000000000..8f239a3597 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/style.css @@ -0,0 +1,74 @@ +body { background-color: #fff; color: #333; } + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { color: #000; } +a:visited { color: #666; } +a:hover { color: #fff; background-color:#000; } + +.fieldWithErrors { + padding: 2px; + background-color: red; + display: table; +} + +#errorExplanation { + width: 400px; + border: 2px solid red; + padding: 7px; + padding-bottom: 12px; + margin-bottom: 20px; + background-color: #f0f0f0; +} + +#errorExplanation h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + background-color: #c00; + color: #fff; +} + +#errorExplanation p { + color: #333; + margin-bottom: 0; + padding: 5px; +} + +#errorExplanation ul li { + font-size: 12px; + list-style: square; +} + +div.uploadStatus { + margin: 5px; +} + +div.progressBar { + margin: 5px; +} + +div.progressBar div.border { + background-color: #fff; + border: 1px solid grey; + width: 100%; +} + +div.progressBar div.background { + background-color: #333; + height: 18px; + width: 0%; +} + diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/unit_test.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/unit_test.rb new file mode 100644 index 0000000000..b464de47a2 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/unit_test.rb @@ -0,0 +1,10 @@ +require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper' + +class <%= class_name %>Test < Test::Unit::TestCase + fixtures :<%= table_name %> + + # Replace this with your real tests. + def test_truth + assert true + end +end diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb new file mode 100644 index 0000000000..a39916db96 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb @@ -0,0 +1,19 @@ +

Editing <%= singular_name %>

+ +<%%= error_messages_for :<%= singular_name %> %> + +<%% form_for(@<%= singular_name %>) do |f| %> +<% for attribute in attributes -%> +

+ <%= attribute.column.human_name %>
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %> +

+ +<% end -%> +

+ <%%= f.submit "Update" %> +

+<%% end %> + +<%%= link_to 'Show', @<%= singular_name %> %> | +<%%= link_to 'Back', <%= plural_name %>_path %> \ No newline at end of file diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb new file mode 100644 index 0000000000..88a4c9bf77 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb @@ -0,0 +1,24 @@ +

Listing <%= plural_name %>

+ + + +<% for attribute in attributes -%> + +<% end -%> + + +<%% for <%= singular_name %> in @<%= plural_name %> %> + +<% for attribute in attributes -%> + +<% end -%> + + + + +<%% end %> +
<%= attribute.column.human_name %>
<%%=h <%= singular_name %>.<%= attribute.name %> %><%%= link_to 'Show', <%= singular_name %> %><%%= link_to 'Edit', edit_<%= singular_name %>_path(<%= singular_name %>) %><%%= link_to 'Destroy', <%= singular_name %>), :confirm => 'Are you sure?', :method => :delete %>
+ +
+ +<%%= link_to 'New <%= singular_name %>', new_<%= singular_name %>_path %> \ No newline at end of file diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb new file mode 100644 index 0000000000..3d92e1f516 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb @@ -0,0 +1,18 @@ +

New <%= singular_name %>

+ +<%%= error_messages_for :<%= singular_name %> %> + +<%% form_for(@<%= singular_name %>) do |f| %> +<% for attribute in attributes -%> +

+ <%= attribute.column.human_name %>
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %> +

+ +<% end -%> +

+ <%%= f.submit "Create" %> +

+<%% end %> + +<%%= link_to 'Back', <%= plural_name %>_path %> \ No newline at end of file diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb new file mode 100644 index 0000000000..adecaf70c6 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb @@ -0,0 +1,10 @@ +<% for attribute in attributes -%> +

+ <%= attribute.column.human_name %>: + <%%=h @<%= singular_name %>.<%= attribute.name %> %> +

+ +<% end -%> + +<%%= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>) %> | +<%%= link_to 'Back', <%= plural_name %>_path %> \ No newline at end of file -- cgit v1.2.3