Permalink
Browse files

Initial commit.

  • Loading branch information...
0 parents commit 4c8cf9636a6d6bdfdf20b1d28fd33a8b0107e749 Norman Clarke committed Nov 7, 2008
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008 [name of plugin creator]
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
92 README.textile
@@ -0,0 +1,92 @@
+h1. Haml Scaffold
+
+A collection of hacks to the Rails scaffold generator, to make it output
+templates using HAML rather than ERB. You may like some of it, and may hate
+other parts. You're free to use it under the terms of the MIT license if the
+parts you like outweigh the parts you hate.
+
+This scaffold generator does the same thing as the default Rails scaffold
+generator, with a few differences.
+
+h2. Differences from Rails Scaffolding:
+
+* HAML not ERB.
+
+h3. Controller
+
+* Loads object with a before_filter to be DRYer.
+* Adds placeholder permission checking before_filters on all actions.
+* "Destroy" method handles error conditions.
+* Actions are alphabetized for more obvious consistency.
+
+h3. Controller Test
+
+* Tests error conditions, not just the "happy-path."
+* Has 100% code coverage with RCov.
+* Simplifies test method names and alphabetizes them for more obvious consistency.
+* Uses some very simple mocking with mocha to limit calls to the DB.
+
+h3. Views
+
+* Have cleaner, more semantic XHTML.
+* Are broken up into a couple of partials to be DRYer.
+* Use will_paginate.
+
+h3. Misc
+
+* Doesn't generate a layout or CSS file.
+
+h2. Samples
+
+"View them here.":http://github.com/norman/haml-scaffold/tree/master/samples
+
+h2. Installation
+
+There are three ways you can install this generator:
+
+h3. Gem
+
+@sudo gem install norman-haml_scaffold@
+
+- or -
+
+<code>
+<pre>
+git clone git://github.com/norman/haml-scaffold.git
+cd haml-scaffold
+gem build haml_scaffold.gemspec
+sudo gem install haml_scaffold-*.gem
+</pre>
+</code>
+
+h3. Manual
+
+Download the tarball from the Github repository and unarchive it in ~/.rails/generators.
+
+h3. Plugin
+
+@./script/plugin install git://github.com/norman/haml-scaffold.git@
+
+
+
+h2. Dependencies
+
+The generated code will depend on:
+
+* "will_paginate":http://github.com/mislav/will_paginate/
+* "mocha":http://mocha.rubyforge.org/
+
+You'll need to add the gems and or requires to your config/environment.rb
+manually.
+
+h2. Other stuff you might be interested in:
+
+* "RSpec HAML scaffold generator":http://github.com/dfischer/rspec-haml-scaffold-generator
+* "Randomba scaffold":https://github.com/norman/randomba-scaffold/tree (like this one, but ERB)
+
+h2. Author
+
+"Norman Clarke":mailto:norman@randomba.org
+
+This work is derived from code in "Ruby on Rails":http://rubyonrails.org/ and
+is released under its same license, the MIT License.
98 generators/haml_scaffold/haml_scaffold_generator.rb
@@ -0,0 +1,98 @@
+class HamlScaffoldGenerator < Rails::Generator::NamedBase
+ default_options :skip_timestamps => false, :skip_migration => false
+
+ attr_reader :controller_name,
+ :controller_class_path,
+ :controller_file_path,
+ :controller_class_nesting,
+ :controller_class_nesting_depth,
+ :controller_class_name,
+ :controller_underscore_name,
+ :controller_singular_name,
+ :controller_plural_name
+ alias_method :controller_file_name, :controller_underscore_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_underscore_name, @controller_plural_name = inflect_names(base_name)
+ @controller_singular_name=base_name.singularize
+ 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, test and stylesheets 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.haml")
+ )
+ end
+
+ m.template(
+ "_form.html.erb",
+ File.join('app/views', controller_class_path, controller_file_name, "_form.html.haml")
+ )
+
+ m.template(
+ "_object.html.erb",
+ File.join('app/views', controller_class_path, controller_file_name, "_#{name}.html.haml")
+ )
+
+ 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.route_resources controller_file_name
+
+ m.dependency 'model', [name] + @args, :collision => :skip
+ end
+ end
+
+ protected
+ # Override with your own usage banner.
+ def banner
+ "Usage: #{$0} scaffold ModelName [field:type, field:type]"
+ end
+
+ def add_options!(opt)
+ opt.separator ''
+ opt.separator 'Options:'
+ opt.on("--skip-timestamps",
+ "Don't add timestamps to the migration file for this model") { |v| options[:skip_timestamps] = v }
+ opt.on("--skip-migration",
+ "Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
+ end
+
+ def scaffold_views
+ %w[ index show new edit ]
+ end
+
+ def model_name
+ class_name.demodulize
+ end
+end
10 generators/haml_scaffold/templates/_form.html.erb
@@ -0,0 +1,10 @@
+- form_for(<%= singular_name %>) do |f|
+ = f.error_messages
+<% for attribute in attributes -%>
+ %p
+ = f.label :<%= attribute.name %>
+ %br
+ = f.<%= attribute.field_type %> :<%= attribute.name %>
+<% end -%>
+ %p
+ = f.submit "Submit"
10 generators/haml_scaffold/templates/_object.html.erb
@@ -0,0 +1,10 @@
+= content_tag_for :div, <%= singular_name %> do
+ %ul
+<% for attribute in attributes -%>
+ %li
+ %strong <%= attribute.column.human_name %>:
+ =h <%= singular_name %>.<%= attribute.name %>
+<% end -%>
+ = 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
80 generators/haml_scaffold/templates/controller.rb
@@ -0,0 +1,80 @@
+class <%= controller_class_name %>Controller < ApplicationController
+
+ before_filter :find_<%= file_name %>
+
+ <%= file_name.pluralize.upcase %>_PER_PAGE = 20
+
+ 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 %> }
+ format.xml { render :xml => @<%= file_name %>, :status => :created, :location => @<%= file_name %> }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ def destroy
+ respond_to do |format|
+ if @<%= file_name %>.destroy
+ flash[:notice] = '<%= class_name %> was successfully destroyed.'
+ format.html { redirect_to <%= file_name.pluralize %>_path }
+ format.xml { head :ok }
+ else
+ flash[:error] = '<%= class_name %> could not be destroyed.'
+ format.html { redirect_to @<%= file_name %> }
+ format.xml { head :unprocessable_entity }
+ end
+ end
+ end
+
+ def index
+ @<%= table_name %> = <%= class_name %>.paginate(:page => params[:page], :per_page => <%= file_name.pluralize.upcase %>_PER_PAGE)
+ respond_to do |format|
+ format.html
+ format.xml { render :xml => @<%= table_name %> }
+ end
+ end
+
+ def edit
+ end
+
+ def new
+ @<%= file_name %> = <%= class_name %>.new
+ respond_to do |format|
+ format.html
+ format.xml { render :xml => @<%= file_name %> }
+ end
+ end
+
+ def show
+ respond_to do |format|
+ format.html
+ format.xml { render :xml => @<%= file_name %> }
+ end
+ end
+
+ def update
+ 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 %> }
+ format.xml { head :ok }
+ else
+ format.html { render :action => "edit" }
+ format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ private
+
+ def find_<%= file_name %>
+ @<%= file_name %> = <%= class_name %>.find(params[:id]) if params[:id]
+ end
+
+end
64 generators/haml_scaffold/templates/functional_test.rb
@@ -0,0 +1,64 @@
+require 'test_helper'
+
+class <%= controller_class_name %>ControllerTest < ActionController::TestCase
+
+ def test_create
+ <%= class_name %>.any_instance.expects(:save).returns(true)
+ post :create, :<%= file_name %> => { }
+ assert_response :redirect
+ end
+
+ def test_create_with_failure
+ <%= class_name %>.any_instance.expects(:save).returns(false)
+ post :create, :<%= file_name %> => { }
+ assert_template "new"
+ end
+
+ def test_destroy
+ <%= class_name %>.any_instance.expects(:destroy).returns(true)
+ delete :destroy, :id => <%= table_name %>(:one).to_param
+ assert_not_nil flash[:notice]
+ assert_response :redirect
+ end
+
+ def test_destroy_with_failure
+ <%= class_name %>.any_instance.expects(:destroy).returns(false)
+ delete :destroy, :id => <%= table_name %>(:one).to_param
+ assert_not_nil flash[:error]
+ assert_response :redirect
+ end
+
+ def test_edit
+ get :edit, :id => <%= table_name %>(:one).to_param
+ assert_response :success
+ end
+
+ def test_index
+ get :index
+ assert_response :success
+ assert_not_nil assigns(:<%= table_name %>)
+ end
+
+ def test_new
+ get :new
+ assert_response :success
+ end
+
+ def test_show
+ get :show, :id => <%= table_name %>(:one).to_param
+ assert_response :success
+ end
+
+ def test_update
+ <%= class_name %>.any_instance.expects(:save).returns(true)
+ put :update, :id => <%= table_name %>(:one).to_param, :<%= file_name %> => { }
+ assert_response :redirect
+ end
+
+ def test_update_with_failure
+ <%= class_name %>.any_instance.expects(:save).returns(false)
+ put :update, :id => <%= table_name %>(:one).to_param, :<%= file_name %> => { }
+ assert_template "edit"
+ end
+
+end
2 generators/haml_scaffold/templates/helper.rb
@@ -0,0 +1,2 @@
+module <%= controller_class_name %>Helper
+end
5 generators/haml_scaffold/templates/view_edit.html.erb
@@ -0,0 +1,5 @@
+%h2 Editing <%= singular_name %>
+= render :partial => "form", :locals => {:<%= singular_name %> => @<%= singular_name %>}
+%ul
+ %li= link_to 'Show', @<%= singular_name %>
+ %li= link_to 'Back', <%= plural_name %>_path
8 generators/haml_scaffold/templates/view_index.html.erb
@@ -0,0 +1,8 @@
+%h2 Listing <%= plural_name %>
+- if !@<%= plural_name %>.empty?
+ .<%= plural_name %>
+ = render :partial => "<%= singular_name %>", :collection => @<%= plural_name %>
+ = will_paginate(@<%= plural_name %>)
+- else
+ %p There are no <%= plural_name %> to show yet.
+= link_to 'New <%= singular_name %>', new_<%= singular_name %>_path
4 generators/haml_scaffold/templates/view_new.html.erb
@@ -0,0 +1,4 @@
+%h2 New <%= singular_name %>
+= render :partial => "form", :locals => {:<%= singular_name %> => @<%= singular_name %>}
+%ul
+ %li= link_to 'Back', <%= plural_name %>_path
11 generators/haml_scaffold/templates/view_show.html.erb
@@ -0,0 +1,11 @@
+%h2= "<%= class_name %> \"#{@<%= singular_name %>.to_param}\""
+= content_tag_for :div, @<%= singular_name %> do
+ %ul
+<% for attribute in attributes -%>
+ %li
+ %strong <%= attribute.column.human_name %>:
+ =h @<%= singular_name %>.<%= attribute.name %>
+<% end -%>
+%ul
+ %li= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>)
+ %li= link_to 'Back', <%= plural_name %>_path
BIN haml_scaffold-0.1.0.gem
Binary file not shown.
36 haml_scaffold.gemspec
@@ -0,0 +1,36 @@
+Gem::Specification.new do |s|
+ s.name = "haml_scaffold"
+ s.version = "0.1.0"
+ s.date = "2008-09-02"
+ s.add_dependency('will_paginate', '>= 2.2.2')
+ s.add_dependency('mocha', '>= 0.9.0')
+ s.summary = "An improved Rails scaffold that uses HAML."
+ s.email = 'norman@randomba.org'
+ s.homepage = 'http://randomba.org'
+ s.description = "An improved Rails scaffold that uses HAML."
+ s.has_rdoc = false
+ s.authors = ['Norman Clarke']
+ s.files = [
+ "MIT-LICENSE",
+ "README.textile",
+ "init.rb",
+ "generators/haml_scaffold/haml_scaffold_generator.rb",
+ "generators/haml_scaffold/templates/_form.html.erb",
+ "generators/haml_scaffold/templates/_object.html.erb",
+ "generators/haml_scaffold/templates/controller.rb",
+ "generators/haml_scaffold/templates/functional_test.rb",
+ "generators/haml_scaffold/templates/helper.rb",
+ "generators/haml_scaffold/templates/view_edit.html.erb",
+ "generators/haml_scaffold/templates/view_index.html.erb",
+ "generators/haml_scaffold/templates/view_new.html.erb",
+ "generators/haml_scaffold/templates/view_show.html.erb",
+ "samples/posts_controller.rb",
+ "samples/posts_controller_test.rb",
+ "samples/views/_form.html.haml",
+ "samples/views/_post.html.haml",
+ "samples/views/edit.html.haml",
+ "samples/views/index.html.haml",
+ "samples/views/new.html.haml",
+ "samples/views/show.html.haml"
+ ]
+end
0 init.rb
No changes.
80 samples/posts_controller.rb
@@ -0,0 +1,80 @@
+class PostsController < ApplicationController
+
+ before_filter :find_post
+
+ POSTS_PER_PAGE = 20
+
+ def create
+ @post = Post.new(params[:post])
+ respond_to do |format|
+ if @post.save
+ flash[:notice] = 'Post was successfully created.'
+ format.html { redirect_to @post }
+ format.xml { render :xml => @post, :status => :created, :location => @post }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ def destroy
+ respond_to do |format|
+ if @post.destroy
+ flash[:notice] = 'Post was successfully destroyed.'
+ format.html { redirect_to posts_path }
+ format.xml { head :ok }
+ else
+ flash[:error] = 'Post could not be destroyed.'
+ format.html { redirect_to @post }
+ format.xml { head :unprocessable_entity }
+ end
+ end
+ end
+
+ def index
+ @posts = Post.paginate(:page => params[:page], :per_page => POSTS_PER_PAGE)
+ respond_to do |format|
+ format.html
+ format.xml { render :xml => @posts }
+ end
+ end
+
+ def edit
+ end
+
+ def new
+ @post = Post.new
+ respond_to do |format|
+ format.html
+ format.xml { render :xml => @post }
+ end
+ end
+
+ def show
+ respond_to do |format|
+ format.html
+ format.xml { render :xml => @post }
+ end
+ end
+
+ def update
+ respond_to do |format|
+ if @post.update_attributes(params[:post])
+ flash[:notice] = 'Post was successfully updated.'
+ format.html { redirect_to @post }
+ format.xml { head :ok }
+ else
+ format.html { render :action => "edit" }
+ format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ private
+
+ def find_post
+ @post = Post.find(params[:id]) if params[:id]
+ end
+
+end
64 samples/posts_controller_test.rb
@@ -0,0 +1,64 @@
+require 'test_helper'
+
+class PostsControllerTest < ActionController::TestCase
+
+ def test_create
+ Post.any_instance.expects(:save).returns(true)
+ post :create, :post => { }
+ assert_response :redirect
+ end
+
+ def test_create_with_failure
+ Post.any_instance.expects(:save).returns(false)
+ post :create, :post => { }
+ assert_template "new"
+ end
+
+ def test_destroy
+ Post.any_instance.expects(:destroy).returns(true)
+ delete :destroy, :id => posts(:one).to_param
+ assert_not_nil flash[:notice]
+ assert_response :redirect
+ end
+
+ def test_destroy_with_failure
+ Post.any_instance.expects(:destroy).returns(false)
+ delete :destroy, :id => posts(:one).to_param
+ assert_not_nil flash[:error]
+ assert_response :redirect
+ end
+
+ def test_edit
+ get :edit, :id => posts(:one).to_param
+ assert_response :success
+ end
+
+ def test_index
+ get :index
+ assert_response :success
+ assert_not_nil assigns(:posts)
+ end
+
+ def test_new
+ get :new
+ assert_response :success
+ end
+
+ def test_show
+ get :show, :id => posts(:one).to_param
+ assert_response :success
+ end
+
+ def test_update
+ Post.any_instance.expects(:save).returns(true)
+ put :update, :id => posts(:one).to_param, :post => { }
+ assert_response :redirect
+ end
+
+ def test_update_with_failure
+ Post.any_instance.expects(:save).returns(false)
+ put :update, :id => posts(:one).to_param, :post => { }
+ assert_template "edit"
+ end
+
+end
16 samples/views/_form.html.haml
@@ -0,0 +1,16 @@
+- form_for(post) do |f|
+ = f.error_messages
+ %p
+ = f.label :title
+ %br
+ = f.text_field :title
+ %p
+ = f.label :author
+ %br
+ = f.text_field :author
+ %p
+ = f.label :content
+ %br
+ = f.text_area :content
+ %p
+ = f.submit "Submit"
14 samples/views/_post.html.haml
@@ -0,0 +1,14 @@
+= content_tag_for :div, post do
+ %ul
+ %li
+ %strong Title:
+ =h post.title
+ %li
+ %strong Author:
+ =h post.author
+ %li
+ %strong Content:
+ =h post.content
+ = link_to 'Show', post
+ = link_to 'Edit', edit_post_path(post)
+ = link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete
5 samples/views/edit.html.haml
@@ -0,0 +1,5 @@
+%h2 Editing post
+= render :partial => "form", :locals => {:post => @post}
+%ul
+ %li= link_to 'Show', @post
+ %li= link_to 'Back', posts_path
8 samples/views/index.html.haml
@@ -0,0 +1,8 @@
+%h2 Listing posts
+- if !@posts.empty?
+ .posts
+ = render :partial => "post", :collection => @posts
+ = will_paginate(@posts)
+- else
+ %p There are no posts to show yet.
+= link_to 'New post', new_post_path
4 samples/views/new.html.haml
@@ -0,0 +1,4 @@
+%h2 New post
+= render :partial => "form", :locals => {:post => @post}
+%ul
+ %li= link_to 'Back', posts_path
15 samples/views/show.html.haml
@@ -0,0 +1,15 @@
+%h2= "Post \"#{@post.to_param}\""
+= content_tag_for :div, @post do
+ %ul
+ %li
+ %strong Title:
+ =h @post.title
+ %li
+ %strong Author:
+ =h @post.author
+ %li
+ %strong Content:
+ =h @post.content
+%ul
+ %li= link_to 'Edit', edit_post_path(@post)
+ %li= link_to 'Back', posts_path

0 comments on commit 4c8cf96

Please sign in to comment.