summaryrefslogtreecommitdiff
path: root/lib/generators
diff options
context:
space:
mode:
authorStefan Wintermeyer <stefan.wintermeyer@amooma.de>2012-12-17 12:05:14 +0100
committerStefan Wintermeyer <stefan.wintermeyer@amooma.de>2012-12-17 12:05:14 +0100
commiteaad37485fe59d0306c37cc038dda6d210052910 (patch)
tree072c4b0e33d442528555b82c415f5e7a1712b2b0 /lib/generators
parent3e706c2025ecc5523e81ad649639ef2ff75e7bac (diff)
parentb80bd744ad873f6fc43018bc4bfb90677de167bd (diff)
Merge branch 'develop'
Diffstat (limited to 'lib/generators')
-rw-r--r--lib/generators/nifty.rb28
-rw-r--r--lib/generators/nifty/authentication/USAGE50
-rw-r--r--lib/generators/nifty/authentication/authentication_generator.rb154
-rw-r--r--lib/generators/nifty/authentication/templates/authlogic_session.rb2
-rw-r--r--lib/generators/nifty/authentication/templates/controller_authentication.rb60
-rw-r--r--lib/generators/nifty/authentication/templates/fixtures.yml24
-rw-r--r--lib/generators/nifty/authentication/templates/migration.rb20
-rw-r--r--lib/generators/nifty/authentication/templates/sessions_controller.rb41
-rw-r--r--lib/generators/nifty/authentication/templates/sessions_helper.rb2
-rw-r--r--lib/generators/nifty/authentication/templates/tests/rspec/sessions_controller.rb39
-rw-r--r--lib/generators/nifty/authentication/templates/tests/rspec/user.rb83
-rw-r--r--lib/generators/nifty/authentication/templates/tests/rspec/users_controller.rb56
-rw-r--r--lib/generators/nifty/authentication/templates/tests/shoulda/sessions_controller.rb40
-rw-r--r--lib/generators/nifty/authentication/templates/tests/shoulda/user.rb85
-rw-r--r--lib/generators/nifty/authentication/templates/tests/shoulda/users_controller.rb61
-rw-r--r--lib/generators/nifty/authentication/templates/tests/testunit/sessions_controller.rb36
-rw-r--r--lib/generators/nifty/authentication/templates/tests/testunit/user.rb88
-rw-r--r--lib/generators/nifty/authentication/templates/tests/testunit/users_controller.rb53
-rw-r--r--lib/generators/nifty/authentication/templates/user.rb38
-rw-r--r--lib/generators/nifty/authentication/templates/users_controller.rb32
-rw-r--r--lib/generators/nifty/authentication/templates/users_helper.rb2
-rw-r--r--lib/generators/nifty/authentication/templates/views/erb/_form.html.erb20
-rw-r--r--lib/generators/nifty/authentication/templates/views/erb/edit.html.erb3
-rw-r--r--lib/generators/nifty/authentication/templates/views/erb/login.html.erb30
-rw-r--r--lib/generators/nifty/authentication/templates/views/erb/signup.html.erb5
-rw-r--r--lib/generators/nifty/authentication/templates/views/haml/_form.html.haml16
-rw-r--r--lib/generators/nifty/authentication/templates/views/haml/edit.html.haml3
-rw-r--r--lib/generators/nifty/authentication/templates/views/haml/login.html.haml26
-rw-r--r--lib/generators/nifty/authentication/templates/views/haml/signup.html.haml5
-rw-r--r--lib/generators/nifty/config/USAGE23
-rw-r--r--lib/generators/nifty/config/config_generator.rb24
-rw-r--r--lib/generators/nifty/config/templates/config.yml8
-rw-r--r--lib/generators/nifty/config/templates/load_config.rb2
-rw-r--r--lib/generators/nifty/layout/USAGE25
-rw-r--r--lib/generators/nifty/layout/layout_generator.rb29
-rw-r--r--lib/generators/nifty/layout/templates/error_messages_helper.rb23
-rw-r--r--lib/generators/nifty/layout/templates/layout.html.haml21
-rw-r--r--lib/generators/nifty/layout/templates/layout_helper.rb38
-rw-r--r--lib/generators/nifty/layout/templates/stylesheet.css83
-rw-r--r--lib/generators/nifty/layout/templates/stylesheet.sass73
-rw-r--r--lib/generators/nifty/scaffold/USAGE51
-rw-r--r--lib/generators/nifty/scaffold/scaffold_generator.rb344
-rw-r--r--lib/generators/nifty/scaffold/templates/actions/create.rb8
-rw-r--r--lib/generators/nifty/scaffold/templates/actions/destroy.rb5
-rw-r--r--lib/generators/nifty/scaffold/templates/actions/edit.rb3
-rw-r--r--lib/generators/nifty/scaffold/templates/actions/index.rb3
-rw-r--r--lib/generators/nifty/scaffold/templates/actions/new.rb3
-rw-r--r--lib/generators/nifty/scaffold/templates/actions/show.rb3
-rw-r--r--lib/generators/nifty/scaffold/templates/actions/update.rb8
-rw-r--r--lib/generators/nifty/scaffold/templates/controller.rb3
-rw-r--r--lib/generators/nifty/scaffold/templates/fixtures.yml9
-rw-r--r--lib/generators/nifty/scaffold/templates/helper.rb2
-rw-r--r--lib/generators/nifty/scaffold/templates/locale.yml46
-rw-r--r--lib/generators/nifty/scaffold/templates/locale_de.yml46
-rw-r--r--lib/generators/nifty/scaffold/templates/migration.rb16
-rw-r--r--lib/generators/nifty/scaffold/templates/model.rb4
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/rspec/actions/create.rb11
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/rspec/actions/destroy.rb6
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/rspec/actions/edit.rb4
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/rspec/actions/index.rb4
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/rspec/actions/new.rb4
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/rspec/actions/show.rb4
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/rspec/actions/update.rb11
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/rspec/controller.rb8
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/rspec/model.rb7
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/shoulda/actions/create.rb13
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/shoulda/actions/destroy.rb8
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/shoulda/actions/edit.rb6
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/shoulda/actions/index.rb6
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/shoulda/actions/new.rb6
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/shoulda/actions/show.rb6
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/shoulda/actions/update.rb13
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/shoulda/controller.rb5
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/shoulda/model.rb7
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/testunit/actions/create.rb11
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/testunit/actions/destroy.rb6
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/testunit/actions/edit.rb4
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/testunit/actions/index.rb4
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/testunit/actions/new.rb4
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/testunit/actions/show.rb4
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/testunit/actions/update.rb11
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/testunit/controller.rb49
-rw-r--r--lib/generators/nifty/scaffold/templates/tests/testunit/model.rb7
-rw-r--r--lib/generators/nifty/scaffold/templates/views/haml/_form.html.haml7
-rw-r--r--lib/generators/nifty/scaffold/templates/views/haml/_form_core.html.haml4
-rw-r--r--lib/generators/nifty/scaffold/templates/views/haml/_index_core.html.haml13
-rw-r--r--lib/generators/nifty/scaffold/templates/views/haml/edit.html.haml3
-rw-r--r--lib/generators/nifty/scaffold/templates/views/haml/index.html.haml6
-rw-r--r--lib/generators/nifty/scaffold/templates/views/haml/new.html.haml3
-rw-r--r--lib/generators/nifty/scaffold/templates/views/haml/show.html.haml9
90 files changed, 2279 insertions, 0 deletions
diff --git a/lib/generators/nifty.rb b/lib/generators/nifty.rb
new file mode 100644
index 0000000..1c3d6d7
--- /dev/null
+++ b/lib/generators/nifty.rb
@@ -0,0 +1,28 @@
+require 'rails/generators/base'
+
+module Nifty
+ module Generators
+ class Base < Rails::Generators::Base #:nodoc:
+ def self.source_root
+ @_nifty_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'nifty', generator_name, 'templates'))
+ end
+
+ def self.banner
+ "rails generate nifty:#{generator_name} #{self.arguments.map{ |a| a.usage }.join(' ')} [options]"
+ end
+
+ private
+
+ def add_gem(name, options = {})
+ gemfile_content = File.read(destination_path("Gemfile"))
+ File.open(destination_path("Gemfile"), 'a') { |f| f.write("\n") } unless gemfile_content =~ /\n\Z/
+ gem name, options unless gemfile_content.include? name
+ end
+
+ def print_usage
+ self.class.help(Thor::Base.shell.new)
+ exit
+ end
+ end
+ end
+end
diff --git a/lib/generators/nifty/authentication/USAGE b/lib/generators/nifty/authentication/USAGE
new file mode 100644
index 0000000..89f0a64
--- /dev/null
+++ b/lib/generators/nifty/authentication/USAGE
@@ -0,0 +1,50 @@
+Description:
+ Generates a user model, users controller, and sessions controller. The
+ users controller handles the registration and the sessions controller
+ handles authentication. This is similar to restful_authentication, but
+ simpler.
+
+ IMPORTANT: This generator uses the "title" helper method which is generated
+ by the nifty_layout generator. You may want to run that generator first.
+
+Usage:
+ If you do not pass any arguments, the model name will default to "user", and
+ the authentication controller will default to "session". You can override
+ each of these respectively by passing one or two arguments. Either name can
+ be CamelCased or under_scored.
+
+ Make sure to setup the authlogic gem if you are using that option.
+
+ gem "authlogic" # in Gemfile
+
+Examples:
+ rails generate nifty:authentication
+
+ Creates user model, users_controller, and sessions_controller.
+
+ rails generate nifty:authentication account
+
+ Creates account model, accounts_controller, and sessions_controller.
+
+ rails generate nifty:authentication Account UserSession
+
+ Creates account model, accounts_controller, and user_sessions_controller.
+
+Methods:
+ There are several methods generated which you can use in your application.
+ Here's a common example of what you might add to your layout.
+
+ <% if logged_in? %>
+ Welcome <%= current_user.username %>! Not you?
+ <%= link_to "Log out", logout_path %>
+ <% else %>
+ <%= link_to "Sign up", signup_path %> or
+ <%= link_to "log in", login_path %>.
+ <% end %>
+
+ You can also restrict unregistered users from accessing a controller using
+ a before filter. For example.
+
+ before_filter :login_required, :except => [:index, :show]
+
+ See the generated file lib/authentication.rb for details. \ No newline at end of file
diff --git a/lib/generators/nifty/authentication/authentication_generator.rb b/lib/generators/nifty/authentication/authentication_generator.rb
new file mode 100644
index 0000000..d4dcbde
--- /dev/null
+++ b/lib/generators/nifty/authentication/authentication_generator.rb
@@ -0,0 +1,154 @@
+require 'generators/nifty'
+require 'rails/generators/migration'
+
+module Nifty
+ module Generators
+ class AuthenticationGenerator < Base
+ include Rails::Generators::Migration
+
+ argument :user_name, :type => :string, :default => 'user', :banner => 'user_name'
+ argument :session_name, :type => :string, :default => '[[DEFAULT]]', :banner => 'sessions_controller_name'
+
+ class_option :testunit, :desc => 'Use test/unit for test files.', :group => 'Test framework', :type => :boolean
+ class_option :rspec, :desc => 'Use RSpec for test files.', :group => 'Test framework', :type => :boolean
+ class_option :shoulda, :desc => 'Use shoulda for test files.', :group => 'Test framework', :type => :boolean
+
+ class_option :haml, :desc => 'Generate HAML views instead of ERB.', :type => :boolean
+ class_option :authlogic, :desc => 'Use Authlogic for authentication.', :type => :boolean
+
+ def add_gems
+ add_gem "bcrypt-ruby", :require => "bcrypt"
+ add_gem "mocha", :group => :test
+ end
+
+ def create_model_files
+ template 'user.rb', "app/models/#{user_singular_name}.rb"
+ template 'authlogic_session.rb', "app/models/#{user_singular_name}_session.rb" if options.authlogic?
+ end
+
+ def create_controller_files
+ template 'users_controller.rb', "app/controllers/#{user_plural_name}_controller.rb"
+ template 'sessions_controller.rb', "app/controllers/#{session_plural_name}_controller.rb"
+ end
+
+ def create_helper_files
+ template 'users_helper.rb', "app/helpers/#{user_plural_name}_helper.rb"
+ template 'sessions_helper.rb', "app/helpers/#{session_plural_name}_helper.rb"
+ end
+
+ def create_view_files
+ template "views/#{view_language}/signup.html.#{view_language}", "app/views/#{user_plural_name}/new.html.#{view_language}"
+ template "views/#{view_language}/edit.html.#{view_language}", "app/views/#{user_plural_name}/edit.html.#{view_language}"
+ template "views/#{view_language}/_form.html.#{view_language}", "app/views/#{user_plural_name}/_form.html.#{view_language}"
+ template "views/#{view_language}/login.html.#{view_language}", "app/views/#{session_plural_name}/new.html.#{view_language}"
+ end
+
+ def create_lib_files
+ template 'controller_authentication.rb', 'lib/controller_authentication.rb'
+ end
+
+ def create_routes
+ route "resources #{user_plural_name.to_sym.inspect}"
+ route "resources #{session_plural_name.to_sym.inspect}"
+ route "match 'login' => '#{session_plural_name}#new', :as => :login"
+ route "match 'logout' => '#{session_plural_name}#destroy', :as => :logout"
+ route "match 'signup' => '#{user_plural_name}#new', :as => :signup"
+ route "match '#{user_singular_name}/edit' => '#{user_plural_name}#edit', :as => :edit_current_#{user_singular_name}"
+ end
+
+ def create_migration
+ migration_template 'migration.rb', "db/migrate/create_#{user_plural_name}.rb"
+ end
+
+ def load_and_include_authentication
+ inject_into_class "config/application.rb", "Application", " config.autoload_paths << \"\#{config.root}/lib\""
+ inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " include ControllerAuthentication\n"
+ end
+
+ def create_test_files
+ if test_framework == :rspec
+ template 'fixtures.yml', "spec/fixtures/#{user_plural_name}.yml"
+ template 'tests/rspec/user.rb', "spec/models/#{user_singular_name}_spec.rb"
+ template 'tests/rspec/users_controller.rb', "spec/controllers/#{user_plural_name}_controller_spec.rb"
+ template 'tests/rspec/sessions_controller.rb', "spec/controllers/#{session_plural_name}_controller_spec.rb"
+ else
+ template 'fixtures.yml', "test/fixtures/#{user_plural_name}.yml"
+ template "tests/#{test_framework}/user.rb", "test/unit/#{user_singular_name}_test.rb"
+ template "tests/#{test_framework}/users_controller.rb", "test/functional/#{user_plural_name}_controller_test.rb"
+ template "tests/#{test_framework}/sessions_controller.rb", "test/functional/#{session_plural_name}_controller_test.rb"
+ end
+ end
+
+ private
+
+ def session_name
+ @_session_name ||= @session_name == '[[DEFAULT]]' ?
+ (options.authlogic? ? user_name + '_session' : 'session') :
+ @session_name
+ end
+
+ def user_singular_name
+ user_name.underscore
+ end
+
+ def user_plural_name
+ user_singular_name.pluralize
+ end
+
+ def user_class_name
+ user_name.camelize
+ end
+
+ def user_plural_class_name
+ user_plural_name.camelize
+ end
+
+ def session_singular_name
+ session_name.underscore
+ end
+
+ def session_plural_name
+ session_singular_name.pluralize
+ end
+
+ def session_class_name
+ session_name.camelize
+ end
+
+ def session_plural_class_name
+ session_plural_name.camelize
+ end
+
+ def view_language
+ options.haml? ? 'haml' : 'erb'
+ end
+
+ def test_framework
+ return @test_framework if defined?(@test_framework)
+ if options.testunit?
+ return @test_framework = :testunit
+ elsif options.rspec?
+ return @test_framework = :rspec
+ elsif options.shoulda?
+ return @test_framework = :shoulda
+ else
+ return @test_framework = File.exist?(destination_path('spec')) ? :rspec : :testunit
+ end
+ end
+
+ def destination_path(path)
+ File.join(destination_root, path)
+ end
+
+ # FIXME: Should be proxied to ActiveRecord::Generators::Base
+ # Implement the required interface for Rails::Generators::Migration.
+ def self.next_migration_number(dirname) #:nodoc:
+ if ActiveRecord::Base.timestamped_migrations
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
+ else
+ "%.3d" % (current_migration_number(dirname) + 1)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/authlogic_session.rb b/lib/generators/nifty/authentication/templates/authlogic_session.rb
new file mode 100644
index 0000000..676cfd0
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/authlogic_session.rb
@@ -0,0 +1,2 @@
+class <%= session_class_name %> < Authlogic::Session::Base
+end
diff --git a/lib/generators/nifty/authentication/templates/controller_authentication.rb b/lib/generators/nifty/authentication/templates/controller_authentication.rb
new file mode 100644
index 0000000..6d34ab0
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/controller_authentication.rb
@@ -0,0 +1,60 @@
+# This module is included in your application controller which makes
+# several methods available to all controllers and views. Here's a
+# common example you might add to your application layout file.
+#
+# <%% if logged_in? %>
+# Welcome <%%= current_<%= user_singular_name %>.username %>.
+# <%%= link_to "Edit profile", edit_current_<%= user_singular_name %>_path %> or
+# <%%= link_to "Log out", logout_path %>
+# <%% else %>
+# <%%= link_to "Sign up", signup_path %> or
+# <%%= link_to "log in", login_path %>.
+# <%% end %>
+#
+# You can also restrict unregistered users from accessing a controller using
+# a before filter. For example.
+#
+# before_filter :login_required, :except => [:index, :show]
+module ControllerAuthentication
+ def self.included(controller)
+ controller.send :helper_method, :current_<%= user_singular_name %>, :logged_in?, :redirect_to_target_or_default
+ end
+
+<%- if options[:authlogic] -%>
+ def current_<%= session_singular_name %>
+ return @current_<%= session_singular_name %> if defined?(@current_<%= session_singular_name %>)
+ @current_<%= session_singular_name %> = <%= session_class_name %>.find
+ end
+
+ def current_<%= user_singular_name %>
+ return @current_<%= user_singular_name %> if defined?(@current_<%= user_singular_name %>)
+ @current_<%= user_singular_name %> = current_<%= session_singular_name %> && current_<%= session_singular_name %>.record
+ end
+<%- else -%>
+ def current_<%= user_singular_name %>
+ @current_<%= user_singular_name %> ||= <%= user_class_name %>.find(session[:<%= user_singular_name %>_id]) if session[:<%= user_singular_name %>_id]
+ end
+<%- end -%>
+
+ def logged_in?
+ current_<%= user_singular_name %>
+ end
+
+ def login_required
+ unless logged_in?
+ store_target_location
+ redirect_to login_url, :alert => "You must first log in or sign up before accessing this page."
+ end
+ end
+
+ def redirect_to_target_or_default(default, *args)
+ redirect_to(session[:return_to] || default, *args)
+ session[:return_to] = nil
+ end
+
+ private
+
+ def store_target_location
+ session[:return_to] = request.url
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/fixtures.yml b/lib/generators/nifty/authentication/templates/fixtures.yml
new file mode 100644
index 0000000..c52532b
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/fixtures.yml
@@ -0,0 +1,24 @@
+# password: "secret"
+foo:
+ username: foo
+ email: foo@example.com
+<%- if options[:authlogic] -%>
+ persistence_token: d5ddba13ed4408ea2b0a12ab18ed2d2eda086279736bdc121ca726a11f1e4b99217d9c534c2cc4ebb22729349c8c5fdbe1529e1f2c3c5859c62ef4dd9feea25c
+ crypted_password: 3d16c326648cccafe3d4b4cb024475c381dda92f430dfedf6f933e1f61203bacb6bae2437849bdb43b06be335e23790e4aa03902b3c28c3bbbbe27d501e521f3
+ password_salt: n6z_wtpWoIsHgQb5IcFd
+<%- else -%>
+ password_hash: 3488f5f7efecab14b91eb96169e5e1ee518a569f
+ password_salt: bef65e058905c379436d80d1a32e7374b139e7b0
+<%- end -%>
+
+bar:
+ username: bar
+ email: bar@example.com
+<%- if options[:authlogic] -%>
+ persistence_token: 19e074bd7cb506ab3e7e53e41f24f0ab3221c8cb68111f4c1aa43965114ad734233979a50a9463537487cdca18c279ac91c4bc83693d589625d446493322394c
+ crypted_password: 3bc9f4113ca645a186765df3d31a9352d0067bf2304ba0cdd6b08a7f3d58c6668ab1762fa3e76aef466ea2ff188399d8e6c40244fa59312bb4112292dac9f7f0
+ password_salt: UiAh9ejabnKRxqsiK0xO
+<%- else -%>
+ password_hash: 3488f5f7efecab14b91eb96169e5e1ee518a569f
+ password_salt: bef65e058905c379436d80d1a32e7374b139e7b0
+<%- end -%>
diff --git a/lib/generators/nifty/authentication/templates/migration.rb b/lib/generators/nifty/authentication/templates/migration.rb
new file mode 100644
index 0000000..c945df3
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/migration.rb
@@ -0,0 +1,20 @@
+class Create<%= user_plural_class_name %> < ActiveRecord::Migration
+ def self.up
+ create_table :<%= user_plural_name %> do |t|
+ t.string :username
+ t.string :email
+ <%- if options[:authlogic] -%>
+ t.string :persistence_token
+ t.string :crypted_password
+ <%- else -%>
+ t.string :password_hash
+ <%- end -%>
+ t.string :password_salt
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :<%= user_plural_name %>
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/sessions_controller.rb b/lib/generators/nifty/authentication/templates/sessions_controller.rb
new file mode 100644
index 0000000..65e77c1
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/sessions_controller.rb
@@ -0,0 +1,41 @@
+class <%= session_plural_class_name %>Controller < ApplicationController
+<%- if options[:authlogic] -%>
+ def new
+ @<%= session_singular_name %> = <%= session_class_name %>.new
+ end
+
+ def create
+ @<%= session_singular_name %> = <%= session_class_name %>.new(params[:<%= session_singular_name %>])
+ if @<%= session_singular_name %>.save
+ redirect_to_target_or_default root_url, :notice => "Logged in successfully."
+ else
+ render :new
+ end
+ end
+
+ def destroy
+ @<%= session_singular_name %> = <%= session_class_name %>.find
+ @<%= session_singular_name %>.destroy
+ redirect_to root_url, :notice => "You have been logged out."
+ end
+<%- else -%>
+ def new
+ end
+
+ def create
+ <%= user_singular_name %> = <%= user_class_name %>.authenticate(params[:login], params[:password])
+ if <%= user_singular_name %>
+ session[:<%= user_singular_name %>_id] = <%= user_singular_name %>.id
+ redirect_to_target_or_default root_url, :notice => "Logged in successfully."
+ else
+ flash.now[:alert] = "Invalid login or password."
+ render :new
+ end
+ end
+
+ def destroy
+ session[:<%= user_singular_name %>_id] = nil
+ redirect_to root_url, :notice => "You have been logged out."
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/sessions_helper.rb b/lib/generators/nifty/authentication/templates/sessions_helper.rb
new file mode 100644
index 0000000..0958537
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/sessions_helper.rb
@@ -0,0 +1,2 @@
+module <%= session_plural_class_name %>Helper
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/rspec/sessions_controller.rb b/lib/generators/nifty/authentication/templates/tests/rspec/sessions_controller.rb
new file mode 100644
index 0000000..e0953cc
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/rspec/sessions_controller.rb
@@ -0,0 +1,39 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe <%= session_plural_class_name %>Controller do
+ fixtures :all
+ render_views
+
+ it "new action should render new template" do
+ get :new
+ response.should render_template(:new)
+ end
+
+<%- if options[:authlogic] -%>
+ it "create action should render new template when authentication is invalid" do
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "badpassword" }
+ response.should render_template(:new)
+ <%= session_class_name %>.find.should be_nil
+ end
+
+ it "create action should redirect when authentication is valid" do
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "secret" }
+ response.should redirect_to(root_url)
+ <%= session_class_name %>.find.<%= user_singular_name %>.should == <%= user_plural_name %>(:foo)
+ end
+<%- else -%>
+ it "create action should render new template when authentication is invalid" do
+ <%= user_class_name %>.stubs(:authenticate).returns(nil)
+ post :create
+ response.should render_template(:new)
+ session['<%= user_singular_name %>_id'].should be_nil
+ end
+
+ it "create action should redirect when authentication is valid" do
+ <%= user_class_name %>.stubs(:authenticate).returns(<%= user_class_name %>.first)
+ post :create
+ response.should redirect_to(root_url)
+ session['<%= user_singular_name %>_id'].should == <%= user_class_name %>.first.id
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/rspec/user.rb b/lib/generators/nifty/authentication/templates/tests/rspec/user.rb
new file mode 100644
index 0000000..a3f7e92
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/rspec/user.rb
@@ -0,0 +1,83 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe <%= user_class_name %> do
+<%- unless options[:authlogic] -%>
+ def new_<%= user_singular_name %>(attributes = {})
+ attributes[:username] ||= 'foo'
+ attributes[:email] ||= 'foo@example.com'
+ attributes[:password] ||= 'abc123'
+ attributes[:password_confirmation] ||= attributes[:password]
+ <%= user_class_name %>.new(attributes)
+ end
+
+ before(:each) do
+ <%= user_class_name %>.delete_all
+ end
+
+ it "should be valid" do
+ new_<%= user_singular_name %>.should be_valid
+ end
+
+ it "should require username" do
+ new_<%= user_singular_name %>(:username => '').should have(1).error_on(:username)
+ end
+
+ it "should require password" do
+ new_<%= user_singular_name %>(:password => '').should have(1).error_on(:password)
+ end
+
+ it "should require well formed email" do
+ new_<%= user_singular_name %>(:email => 'foo@bar@example.com').should have(1).error_on(:email)
+ end
+
+ it "should validate uniqueness of email" do
+ new_<%= user_singular_name %>(:email => 'bar@example.com').save!
+ new_<%= user_singular_name %>(:email => 'bar@example.com').should have(1).error_on(:email)
+ end
+
+ it "should validate uniqueness of username" do
+ new_<%= user_singular_name %>(:username => 'uniquename').save!
+ new_<%= user_singular_name %>(:username => 'uniquename').should have(1).error_on(:username)
+ end
+
+ it "should not allow odd characters in username" do
+ new_<%= user_singular_name %>(:username => 'odd ^&(@)').should have(1).error_on(:username)
+ end
+
+ it "should validate password is longer than 3 characters" do
+ new_<%= user_singular_name %>(:password => 'bad').should have(1).error_on(:password)
+ end
+
+ it "should require matching password confirmation" do
+ new_<%= user_singular_name %>(:password_confirmation => 'nonmatching').should have(1).error_on(:password)
+ end
+
+ it "should generate password hash and salt on create" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>
+ <%= user_singular_name %>.save!
+ <%= user_singular_name %>.password_hash.should_not be_nil
+ <%= user_singular_name %>.password_salt.should_not be_nil
+ end
+
+ it "should authenticate by username" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret')
+ <%= user_singular_name %>.save!
+ <%= user_class_name %>.authenticate('foobar', 'secret').should == <%= user_singular_name %>
+ end
+
+ it "should authenticate by email" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:email => 'foo@bar.com', :password => 'secret')
+ <%= user_singular_name %>.save!
+ <%= user_class_name %>.authenticate('foo@bar.com', 'secret').should == <%= user_singular_name %>
+ end
+
+ it "should not authenticate bad username" do
+ <%= user_class_name %>.authenticate('nonexisting', 'secret').should be_nil
+ end
+
+ it "should not authenticate bad password" do
+ new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret').save!
+ <%= user_class_name %>.authenticate('foobar', 'badpassword').should be_nil
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/rspec/users_controller.rb b/lib/generators/nifty/authentication/templates/tests/rspec/users_controller.rb
new file mode 100644
index 0000000..60bcff9
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/rspec/users_controller.rb
@@ -0,0 +1,56 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe <%= user_plural_class_name %>Controller do
+ fixtures :all
+ render_views
+
+ it "new action should render new template" do
+ get :new
+ response.should render_template(:new)
+ end
+
+ it "create action should render new template when model is invalid" do
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ post :create
+ response.should render_template(:new)
+ end
+
+ it "create action should redirect when model is valid" do
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ post :create
+ response.should redirect_to(root_url)
+ <%- unless options[:authlogic] -%>
+ session['<%= user_singular_name %>_id'].should == assigns['<%= user_singular_name %>'].id
+ <%- end -%>
+ end
+
+ it "edit action should redirect when not logged in" do
+ get :edit, :id => "ignored"
+ response.should redirect_to(login_url)
+ end
+
+ it "edit action should render edit template" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ get :edit, :id => "ignored"
+ response.should render_template(:edit)
+ end
+
+ it "update action should redirect when not logged in" do
+ put :update, :id => "ignored"
+ response.should redirect_to(login_url)
+ end
+
+ it "update action should render edit template when <%= user_singular_name %> is invalid" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ put :update, :id => "ignored"
+ response.should render_template(:edit)
+ end
+
+ it "update action should redirect when <%= user_singular_name %> is valid" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ put :update, :id => "ignored"
+ response.should redirect_to(root_url)
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/shoulda/sessions_controller.rb b/lib/generators/nifty/authentication/templates/tests/shoulda/sessions_controller.rb
new file mode 100644
index 0000000..e2f9005
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/shoulda/sessions_controller.rb
@@ -0,0 +1,40 @@
+require 'test_helper'
+
+class <%= session_plural_class_name %>ControllerTest < ActionController::TestCase
+ context "new action" do
+ should "render new template" do
+ get :new
+ assert_template 'new'
+ end
+ end
+
+ context "create action" do
+ <%- if options[:authlogic] -%>
+ should "render new template when authentication is invalid" do
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "badpassword" }
+ assert_template 'new'
+ assert_nil <%= session_class_name %>.find
+ end
+
+ should "redirect when authentication is valid" do
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "secret" }
+ assert_redirected_to root_url
+ assert_equal <%= user_plural_name %>(:foo), <%= session_class_name %>.find.<%= user_singular_name %>
+ end
+ <%- else -%>
+ should "render new template when authentication is invalid" do
+ <%= user_class_name %>.stubs(:authenticate).returns(nil)
+ post :create
+ assert_template 'new'
+ assert_nil session['<%= user_singular_name %>_id']
+ end
+
+ should "redirect when authentication is valid" do
+ <%= user_class_name %>.stubs(:authenticate).returns(<%= user_class_name %>.first)
+ post :create
+ assert_redirected_to root_url
+ assert_equal <%= user_class_name %>.first.id, session['<%= user_singular_name %>_id']
+ end
+ <%- end -%>
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/shoulda/user.rb b/lib/generators/nifty/authentication/templates/tests/shoulda/user.rb
new file mode 100644
index 0000000..beb8bf4
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/shoulda/user.rb
@@ -0,0 +1,85 @@
+require 'test_helper'
+
+class <%= user_class_name %>Test < ActiveSupport::TestCase
+<%- unless options[:authlogic] -%>
+ def new_<%= user_singular_name %>(attributes = {})
+ attributes[:username] ||= 'foo'
+ attributes[:email] ||= 'foo@example.com'
+ attributes[:password] ||= 'abc123'
+ attributes[:password_confirmation] ||= attributes[:password]
+ <%= user_singular_name %> = <%= user_class_name %>.new(attributes)
+ <%= user_singular_name %>.valid? # run validations
+ <%= user_singular_name %>
+ end
+
+ def setup
+ <%= user_class_name %>.delete_all
+ end
+
+ should "be valid" do
+ assert new_<%= user_singular_name %>.valid?
+ end
+
+ should "require username" do
+ assert_equal ["can't be blank"], new_<%= user_singular_name %>(:username => '').errors[:username]
+ end
+
+ should "require password" do
+ assert_equal ["can't be blank"], new_<%= user_singular_name %>(:password => '').errors[:password]
+ end
+
+ should "require well formed email" do
+ assert_equal ["is invalid"], new_<%= user_singular_name %>(:email => 'foo@bar@example.com').errors[:email]
+ end
+
+ should "validate uniqueness of email" do
+ new_<%= user_singular_name %>(:email => 'bar@example.com').save!
+ assert_equal ["has already been taken"], new_<%= user_singular_name %>(:email => 'bar@example.com').errors[:email]
+ end
+
+ should "validate uniqueness of username" do
+ new_<%= user_singular_name %>(:username => 'uniquename').save!
+ assert_equal ["has already been taken"], new_<%= user_singular_name %>(:username => 'uniquename').errors[:username]
+ end
+
+ should "not allow odd characters in username" do
+ assert_equal ["should only contain letters, numbers, or .-_@"], new_<%= user_singular_name %>(:username => 'odd ^&(@)').errors[:username]
+ end
+
+ should "validate password is longer than 3 characters" do
+ assert_equal ["is too short (minimum is 4 characters)"], new_<%= user_singular_name %>(:password => 'bad').errors[:password]
+ end
+
+ should "require matching password confirmation" do
+ assert_equal ["doesn't match confirmation"], new_<%= user_singular_name %>(:password_confirmation => 'nonmatching').errors[:password]
+ end
+
+ should "generate password hash and salt on create" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>
+ <%= user_singular_name %>.save!
+ assert <%= user_singular_name %>.password_hash
+ assert <%= user_singular_name %>.password_salt
+ end
+
+ should "authenticate by username" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret')
+ <%= user_singular_name %>.save!
+ assert_equal <%= user_singular_name %>, <%= user_class_name %>.authenticate('foobar', 'secret')
+ end
+
+ should "authenticate by email" do
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:email => 'foo@bar.com', :password => 'secret')
+ <%= user_singular_name %>.save!
+ assert_equal <%= user_singular_name %>, <%= user_class_name %>.authenticate('foo@bar.com', 'secret')
+ end
+
+ should "not authenticate bad username" do
+ assert_nil <%= user_class_name %>.authenticate('nonexisting', 'secret')
+ end
+
+ should "not authenticate bad password" do
+ new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret').save!
+ assert_nil <%= user_class_name %>.authenticate('foobar', 'badpassword')
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/shoulda/users_controller.rb b/lib/generators/nifty/authentication/templates/tests/shoulda/users_controller.rb
new file mode 100644
index 0000000..1728329
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/shoulda/users_controller.rb
@@ -0,0 +1,61 @@
+require 'test_helper'
+
+class <%= user_plural_class_name %>ControllerTest < ActionController::TestCase
+ context "new action" do
+ should "render new template" do
+ get :new
+ assert_template 'new'
+ end
+ end
+
+ context "create action" do
+ should "render new template when <%= user_singular_name %> is invalid" do
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ post :create
+ assert_template 'new'
+ end
+
+ should "redirect when <%= user_singular_name %> is valid" do
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ post :create
+ assert_redirected_to root_url
+ <%- unless options[:authlogic] -%>
+ assert_equal assigns['<%= user_singular_name %>'].id, session['<%= user_singular_name %>_id']
+ <%- end -%>
+ end
+ end
+
+ context "edit action" do
+ should "redirect when not logged in" do
+ get :edit, :id => "ignored"
+ assert_redirected_to login_url
+ end
+
+ should "render edit template" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ get :edit, :id => "ignored"
+ assert_template 'edit'
+ end
+ end
+
+ context "update action" do
+ should "redirect when not logged in" do
+ put :update, :id => "ignored"
+ assert_redirected_to login_url
+ end
+
+ should "render edit template when <%= user_singular_name %> is invalid" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ put :update, :id => "ignored"
+ assert_template 'edit'
+ end
+
+ should "redirect when <%= user_singular_name %> is valid" do
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ put :update, :id => "ignored"
+ assert_redirected_to root_url
+ end
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/testunit/sessions_controller.rb b/lib/generators/nifty/authentication/templates/tests/testunit/sessions_controller.rb
new file mode 100644
index 0000000..fe2a65b
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/testunit/sessions_controller.rb
@@ -0,0 +1,36 @@
+require 'test_helper'
+
+class <%= session_plural_class_name %>ControllerTest < ActionController::TestCase
+ def test_new
+ get :new
+ assert_template 'new'
+ end
+
+<%- if options[:authlogic] -%>
+ def test_create_invalid
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "badpassword" }
+ assert_template 'new'
+ assert_nil <%= session_class_name %>.find
+ end
+
+ def test_create_valid
+ post :create, :<%= session_singular_name %> => { :username => "foo", :password => "secret" }
+ assert_redirected_to root_url
+ assert_equal <%= user_plural_name %>(:foo), <%= session_class_name %>.find.<%= user_singular_name %>
+ end
+<%- else -%>
+ def test_create_invalid
+ <%= user_class_name %>.stubs(:authenticate).returns(nil)
+ post :create
+ assert_template 'new'
+ assert_nil session['<%= user_singular_name %>_id']
+ end
+
+ def test_create_valid
+ <%= user_class_name %>.stubs(:authenticate).returns(<%= user_class_name %>.first)
+ post :create
+ assert_redirected_to root_url
+ assert_equal <%= user_class_name %>.first.id, session['<%= user_singular_name %>_id']
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/testunit/user.rb b/lib/generators/nifty/authentication/templates/tests/testunit/user.rb
new file mode 100644
index 0000000..c036cf1
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/testunit/user.rb
@@ -0,0 +1,88 @@
+require 'test_helper'
+
+class <%= user_class_name %>Test < ActiveSupport::TestCase
+<%- unless options[:authlogic] -%>
+ def new_<%= user_singular_name %>(attributes = {})
+ attributes[:username] ||= 'foo'
+ attributes[:email] ||= 'foo@example.com'
+ attributes[:password] ||= 'abc123'
+ attributes[:password_confirmation] ||= attributes[:password]
+ <%= user_singular_name %> = <%= user_class_name %>.new(attributes)
+ <%= user_singular_name %>.valid? # run validations
+ <%= user_singular_name %>
+ end
+
+ def setup
+ <%= user_class_name %>.delete_all
+ end
+
+ def test_valid
+ assert new_<%= user_singular_name %>.valid?
+ end
+
+ def test_require_username
+ assert_equal ["can't be blank"], new_<%= user_singular_name %>(:username => '').errors[:username]
+ end
+
+ def test_require_password
+ assert_equal ["can't be blank"], new_<%= user_singular_name %>(:password => '').errors[:password]
+ end
+
+ def test_require_well_formed_email
+ assert_equal ["is invalid"], new_<%= user_singular_name %>(:email => 'foo@bar@example.com').errors[:email]
+ end
+
+ def test_validate_uniqueness_of_email
+ new_<%= user_singular_name %>(:email => 'bar@example.com').save!
+ assert_equal ["has already been taken"], new_<%= user_singular_name %>(:email => 'bar@example.com').errors[:email]
+ end
+
+ def test_validate_uniqueness_of_username
+ new_<%= user_singular_name %>(:username => 'uniquename').save!
+ assert_equal ["has already been taken"], new_<%= user_singular_name %>(:username => 'uniquename').errors[:username]
+ end
+
+ def test_validate_odd_characters_in_username
+ assert_equal ["should only contain letters, numbers, or .-_@"], new_<%= user_singular_name %>(:username => 'odd ^&(@)').errors[:username]
+ end
+
+ def test_validate_password_length
+ assert_equal ["is too short (minimum is 4 characters)"], new_<%= user_singular_name %>(:password => 'bad').errors[:password]
+ end
+
+ def test_require_matching_password_confirmation
+ assert_equal ["doesn't match confirmation"], new_<%= user_singular_name %>(:password_confirmation => 'nonmatching').errors[:password]
+ end
+
+ def test_generate_password_hash_and_salt_on_create
+ <%= user_singular_name %> = new_<%= user_singular_name %>
+ <%= user_singular_name %>.save!
+ assert <%= user_singular_name %>.password_hash
+ assert <%= user_singular_name %>.password_salt
+ end
+
+ def test_authenticate_by_username
+ <%= user_class_name %>.delete_all
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret')
+ <%= user_singular_name %>.save!
+ assert_equal <%= user_singular_name %>, <%= user_class_name %>.authenticate('foobar', 'secret')
+ end
+
+ def test_authenticate_by_email
+ <%= user_class_name %>.delete_all
+ <%= user_singular_name %> = new_<%= user_singular_name %>(:email => 'foo@bar.com', :password => 'secret')
+ <%= user_singular_name %>.save!
+ assert_equal <%= user_singular_name %>, <%= user_class_name %>.authenticate('foo@bar.com', 'secret')
+ end
+
+ def test_authenticate_bad_username
+ assert_nil <%= user_class_name %>.authenticate('nonexisting', 'secret')
+ end
+
+ def test_authenticate_bad_password
+ <%= user_class_name %>.delete_all
+ new_<%= user_singular_name %>(:username => 'foobar', :password => 'secret').save!
+ assert_nil <%= user_class_name %>.authenticate('foobar', 'badpassword')
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/tests/testunit/users_controller.rb b/lib/generators/nifty/authentication/templates/tests/testunit/users_controller.rb
new file mode 100644
index 0000000..ef8a3f7
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/tests/testunit/users_controller.rb
@@ -0,0 +1,53 @@
+require 'test_helper'
+
+class <%= user_plural_class_name %>ControllerTest < ActionController::TestCase
+ def test_new
+ get :new
+ assert_template 'new'
+ end
+
+ def test_create_invalid
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ post :create
+ assert_template 'new'
+ end
+
+ def test_create_valid
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ post :create
+ assert_redirected_to root_url
+ <%- unless options[:authlogic] -%>
+ assert_equal assigns['<%= user_singular_name %>'].id, session['<%= user_singular_name %>_id']
+ <%- end -%>
+ end
+
+ def test_edit_without_user
+ get :edit, :id => "ignored"
+ assert_redirected_to login_url
+ end
+
+ def test_edit
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ get :edit, :id => "ignored"
+ assert_template 'edit'
+ end
+
+ def test_update_without_user
+ put :update, :id => "ignored"
+ assert_redirected_to login_url
+ end
+
+ def test_update_invalid
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(false)
+ put :update, :id => "ignored"
+ assert_template 'edit'
+ end
+
+ def test_update_valid
+ @controller.stubs(:current_<%= user_singular_name %>).returns(<%= user_class_name %>.first)
+ <%= user_class_name %>.any_instance.stubs(:valid?).returns(true)
+ put :update, :id => "ignored"
+ assert_redirected_to root_url
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/user.rb b/lib/generators/nifty/authentication/templates/user.rb
new file mode 100644
index 0000000..ec18524
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/user.rb
@@ -0,0 +1,38 @@
+class <%= user_class_name %> < ActiveRecord::Base
+<%- if options[:authlogic] -%>
+ acts_as_authentic
+<%- else -%>
+ # new columns need to be added here to be writable through mass assignment
+ attr_accessible :username, :email, :password, :password_confirmation
+
+ attr_accessor :password
+ before_save :prepare_password
+
+ validates_presence_of :username
+ validates_uniqueness_of :username, :email, :allow_blank => true
+ validates_format_of :username, :with => /^[-\w\._@]+$/i, :allow_blank => true, :message => "should only contain letters, numbers, or .-_@"
+ validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
+ validates_presence_of :password, :on => :create
+ validates_confirmation_of :password
+ validates_length_of :password, :minimum => 4, :allow_blank => true
+
+ # login can be either username or email address
+ def self.authenticate(login, pass)
+ <%= user_singular_name %> = find_by_username(login) || find_by_email(login)
+ return <%= user_singular_name %> if <%= user_singular_name %> && <%= user_singular_name %>.password_hash == <%= user_singular_name %>.encrypt_password(pass)
+ end
+
+ def encrypt_password(pass)
+ BCrypt::Engine.hash_secret(pass, password_salt)
+ end
+
+ private
+
+ def prepare_password
+ unless password.blank?
+ self.password_salt = BCrypt::Engine.generate_salt
+ self.password_hash = encrypt_password(password)
+ end
+ end
+<%- end -%>
+end
diff --git a/lib/generators/nifty/authentication/templates/users_controller.rb b/lib/generators/nifty/authentication/templates/users_controller.rb
new file mode 100644
index 0000000..2faed00
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/users_controller.rb
@@ -0,0 +1,32 @@
+class <%= user_plural_class_name %>Controller < ApplicationController
+ before_filter :login_required, :except => [:new, :create]
+
+ def new
+ @<%= user_singular_name %> = <%= user_class_name %>.new
+ end
+
+ def create
+ @<%= user_singular_name %> = <%= user_class_name %>.new(params[:<%= user_singular_name %>])
+ if @<%= user_singular_name %>.save
+ <%- unless options[:authlogic] -%>
+ session[:<%= user_singular_name %>_id] = @<%= user_singular_name %>.id
+ <%- end -%>
+ redirect_to root_url, :notice => "Thank you for signing up! You are now logged in."
+ else
+ render :new
+ end
+ end
+
+ def edit
+ @<%= user_singular_name %> = current_<%= user_singular_name %>
+ end
+
+ def update
+ @<%= user_singular_name %> = current_<%= user_singular_name %>
+ if @<%= user_singular_name %>.update_attributes(params[:<%= user_singular_name %>])
+ redirect_to root_url, :notice => "Your profile has been updated."
+ else
+ render :edit
+ end
+ end
+end
diff --git a/lib/generators/nifty/authentication/templates/users_helper.rb b/lib/generators/nifty/authentication/templates/users_helper.rb
new file mode 100644
index 0000000..7eb9040
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/users_helper.rb
@@ -0,0 +1,2 @@
+module <%= user_plural_class_name %>Helper
+end
diff --git a/lib/generators/nifty/authentication/templates/views/erb/_form.html.erb b/lib/generators/nifty/authentication/templates/views/erb/_form.html.erb
new file mode 100644
index 0000000..4e1c47d
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/erb/_form.html.erb
@@ -0,0 +1,20 @@
+<%%= form_for @<%= user_singular_name %> do |f| %>
+ <%%= f.error_messages %>
+ <div class="field">
+ <%%= f.label :username %>
+ <%%= f.text_field :username %>
+ </div>
+ <div class="field">
+ <%%= f.label :email, "Email Address" %>
+ <%%= f.text_field :email %>
+ </div>
+ <div class="field">
+ <%%= f.label :password %>
+ <%%= f.password_field :password %>
+ </div>
+ <div class="field">
+ <%%= f.label :password_confirmation, "Confirm Password" %>
+ <%%= f.password_field :password_confirmation %>
+ </div>
+ <div class="actions"><%%= f.submit (@<%= user_singular_name %>.new_record? ? "Sign up" : "Update") %></div>
+<%% end %>
diff --git a/lib/generators/nifty/authentication/templates/views/erb/edit.html.erb b/lib/generators/nifty/authentication/templates/views/erb/edit.html.erb
new file mode 100644
index 0000000..75de67e
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/erb/edit.html.erb
@@ -0,0 +1,3 @@
+<%% title "Update Profile" %>
+
+<%%= render "form" %>
diff --git a/lib/generators/nifty/authentication/templates/views/erb/login.html.erb b/lib/generators/nifty/authentication/templates/views/erb/login.html.erb
new file mode 100644
index 0000000..1cbc428
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/erb/login.html.erb
@@ -0,0 +1,30 @@
+<%% title "Log in" %>
+
+<p>Don't have an account? <%%= link_to "Sign up!", signup_path %></p>
+
+<%- if options[:authlogic] -%>
+<%%= form_for @<%= session_singular_name %> do |f| %>
+ <%%= f.error_messages %>
+ <div class="field">
+ <%%= f.label :username %>
+ <%%= f.text_field :username %>
+ </div>
+ <div class="field">
+ <%%= f.label :password %>
+ <%%= f.password_field :password %>
+ </div>
+ <div class="actions"><%%= f.submit "Log in" %></div>
+<%% end %>
+<%- else -%>
+<%%= form_tag <%= session_plural_name %>_path do %>
+ <div class="field">
+ <%%= label_tag :login, "Username or Email Address" %>
+ <%%= text_field_tag :login, params[:login] %>
+ </div>
+ <div class="field">
+ <%%= label_tag :password %>
+ <%%= password_field_tag :password %>
+ </div>
+ <div class="actions"><%%= submit_tag "Log in" %></div>
+<%% end %>
+<%- end -%>
diff --git a/lib/generators/nifty/authentication/templates/views/erb/signup.html.erb b/lib/generators/nifty/authentication/templates/views/erb/signup.html.erb
new file mode 100644
index 0000000..6f282b5
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/erb/signup.html.erb
@@ -0,0 +1,5 @@
+<%% title "Sign up" %>
+
+<p>Already have an account? <%%= link_to "Log in", login_path %>.</p>
+
+<%%= render "form" %>
diff --git a/lib/generators/nifty/authentication/templates/views/haml/_form.html.haml b/lib/generators/nifty/authentication/templates/views/haml/_form.html.haml
new file mode 100644
index 0000000..992ee9c
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/haml/_form.html.haml
@@ -0,0 +1,16 @@
+= form_for @<%= user_singular_name %> do |f|
+ = f.error_messages
+ .field
+ = f.label :username
+ = f.text_field :username
+ .field
+ = f.label :email, "Email Address"
+ = f.text_field :email
+ .field
+ = f.label :password
+ = f.password_field :password
+ .field
+ = f.label :password_confirmation, "Confirm Password"
+ = f.password_field :password_confirmation
+ .actions
+ = f.submit (@<%= user_singular_name %>.new_record? ? "Sign up" : "Update")
diff --git a/lib/generators/nifty/authentication/templates/views/haml/edit.html.haml b/lib/generators/nifty/authentication/templates/views/haml/edit.html.haml
new file mode 100644
index 0000000..4b43a3b
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/haml/edit.html.haml
@@ -0,0 +1,3 @@
+- title "Sign up"
+
+= render "form"
diff --git a/lib/generators/nifty/authentication/templates/views/haml/login.html.haml b/lib/generators/nifty/authentication/templates/views/haml/login.html.haml
new file mode 100644
index 0000000..22fc95b
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/haml/login.html.haml
@@ -0,0 +1,26 @@
+- title "Log in"
+
+%p== Don't have an account? #{link_to "Sign up!", signup_path}
+
+<%- if options[:authlogic] -%>
+= form_for @<%= session_singular_name %> do |f|
+ = f.error_messages
+ .field
+ = f.label :username
+ = f.text_field :username
+ .field
+ = f.label :password
+ = f.password_field :password
+ .actions
+ = f.submit "Log in"
+<%- else -%>
+- form_tag <%= session_plural_name %>_path do
+ .field
+ = label_tag :login, "Username or Email Address"
+ = text_field_tag :login, params[:login]
+ .field
+ = label_tag :password
+ = password_field_tag :password
+ .actions
+ = submit_tag "Log in"
+<%- end -%>
diff --git a/lib/generators/nifty/authentication/templates/views/haml/signup.html.haml b/lib/generators/nifty/authentication/templates/views/haml/signup.html.haml
new file mode 100644
index 0000000..dc75c13
--- /dev/null
+++ b/lib/generators/nifty/authentication/templates/views/haml/signup.html.haml
@@ -0,0 +1,5 @@
+- title "Sign up"
+
+%p== Already have an account? #{link_to "Log in", login_path}.
+
+= render "form"
diff --git a/lib/generators/nifty/config/USAGE b/lib/generators/nifty/config/USAGE
new file mode 100644
index 0000000..f98972c
--- /dev/null
+++ b/lib/generators/nifty/config/USAGE
@@ -0,0 +1,23 @@
+Description:
+ The nifty_config generator creates YAML file in your config
+ directory and an initializer to load this config. The config has a
+ separate section for each environment. This is a great place to put
+ any config settings you don't want in your app.
+
+ The config is loaded into a constant called APP_CONFIG by default,
+ this changes depending on the name you choose to pass the generator.
+ Use this constant to access the config settings like this.
+
+ APP_CONFIG[:some_setting]
+
+
+Examples:
+ rails generate nifty:config
+
+ Config: config/app_config.yml
+ Initializer: config/initializers/load_app_config.rb
+
+ rails generate nifty:config passwords
+
+ Config: config/passwords_config.yml
+ Initializer: config/initializers/load_passwords_config.rb
diff --git a/lib/generators/nifty/config/config_generator.rb b/lib/generators/nifty/config/config_generator.rb
new file mode 100644
index 0000000..811c80e
--- /dev/null
+++ b/lib/generators/nifty/config/config_generator.rb
@@ -0,0 +1,24 @@
+require 'generators/nifty'
+
+module Nifty
+ module Generators
+ class ConfigGenerator < Base
+ argument :config_name, :type => :string, :default => 'app', :banner => 'config_name'
+
+ def create_config
+ template "load_config.rb", "config/initializers/load_#{file_name}_config.rb"
+ copy_file "config.yml", "config/#{file_name}_config.yml"
+ end
+
+ private
+
+ def file_name
+ config_name.underscore
+ end
+
+ def constant_name
+ config_name.underscore.upcase
+ end
+ end
+ end
+end
diff --git a/lib/generators/nifty/config/templates/config.yml b/lib/generators/nifty/config/templates/config.yml
new file mode 100644
index 0000000..3a26ebc
--- /dev/null
+++ b/lib/generators/nifty/config/templates/config.yml
@@ -0,0 +1,8 @@
+development:
+ domain: localhost:3000
+
+test:
+ domain: test.host
+
+production:
+ domain: example.com
diff --git a/lib/generators/nifty/config/templates/load_config.rb b/lib/generators/nifty/config/templates/load_config.rb
new file mode 100644
index 0000000..06e6a52
--- /dev/null
+++ b/lib/generators/nifty/config/templates/load_config.rb
@@ -0,0 +1,2 @@
+raw_config = File.read("#{Rails.root}/config/<%= file_name %>_config.yml")
+<%= constant_name %>_CONFIG = YAML.load(raw_config)[Rails.env].symbolize_keys
diff --git a/lib/generators/nifty/layout/USAGE b/lib/generators/nifty/layout/USAGE
new file mode 100644
index 0000000..f94af0d
--- /dev/null
+++ b/lib/generators/nifty/layout/USAGE
@@ -0,0 +1,25 @@
+Description:
+ The nifty_layout generator creates a basic layout, stylesheet and
+ helper which will give some structure to a starting Rails app.
+
+ The generator takes one argument which will be the name of the
+ layout and stylesheet files. If no argument is passed then it defaults
+ to "application".
+
+ The helper module includes some methods which can be called in any
+ template or partial to set variables to be used in the layout, such as
+ page title and javascript/stylesheet includes.
+
+Examples:
+ rails generate nifty:layout
+
+ Layout: app/views/layouts/application.html.erb
+ Stylesheet: public/stylesheets/application.css
+ Helper: app/helpers/layout_helper.rb
+
+
+ rails generate nifty:layout admin
+
+ Layout: app/views/layouts/admin.html.erb
+ Stylesheet: public/stylesheets/admin.css
+ Helper: app/helpers/layout_helper.rb
diff --git a/lib/generators/nifty/layout/layout_generator.rb b/lib/generators/nifty/layout/layout_generator.rb
new file mode 100644
index 0000000..fb7f9f4
--- /dev/null
+++ b/lib/generators/nifty/layout/layout_generator.rb
@@ -0,0 +1,29 @@
+require 'generators/nifty'
+
+module Nifty
+ module Generators
+ class LayoutGenerator < Base
+ argument :layout_name, :type => :string, :default => 'application', :banner => 'layout_name'
+
+ class_option :haml, :desc => 'Generate HAML for view, and SASS for stylesheet.', :type => :boolean, :default => true
+
+ def create_layout
+ if options.haml?
+ template 'layout.html.haml', "app/views/layouts/#{file_name}.html.haml"
+ copy_file 'stylesheet.sass', "public/stylesheets/sass/#{file_name}.sass"
+ else
+ template 'layout.html.erb', "app/views/layouts/#{file_name}.html.erb"
+ copy_file 'stylesheet.css', "public/stylesheets/#{file_name}.css"
+ end
+ copy_file 'layout_helper.rb', 'app/helpers/layout_helper.rb'
+ copy_file 'error_messages_helper.rb', 'app/helpers/error_messages_helper.rb'
+ end
+
+ private
+
+ def file_name
+ layout_name.underscore
+ end
+ end
+ end
+end
diff --git a/lib/generators/nifty/layout/templates/error_messages_helper.rb b/lib/generators/nifty/layout/templates/error_messages_helper.rb
new file mode 100644
index 0000000..8e9c4d3
--- /dev/null
+++ b/lib/generators/nifty/layout/templates/error_messages_helper.rb
@@ -0,0 +1,23 @@
+module ErrorMessagesHelper
+ # Render error messages for the given objects. The :message and :header_message options are allowed.
+ def error_messages_for(*objects)
+ options = objects.extract_options!
+ options[:header_message] ||= I18n.t(:"activerecord.errors.header", :default => "Invalid Fields")
+ options[:message] ||= I18n.t(:"activerecord.errors.message", :default => "Correct the following errors and try again.")
+ messages = objects.compact.map { |o| o.errors.full_messages }.flatten
+ unless messages.empty?
+ content_tag(:div, :class => "error_messages") do
+ list_items = messages.map { |msg| content_tag(:li, msg.html_safe) }
+ content_tag(:h2, options[:header_message].html_safe) + content_tag(:p, options[:message].html_safe) + content_tag(:ul, list_items.join.html_safe)
+ end
+ end
+ end
+
+ module FormBuilderAdditions
+ def error_messages(options = {})
+ @template.error_messages_for(@object, options)
+ end
+ end
+end
+
+ActionView::Helpers::FormBuilder.send(:include, ErrorMessagesHelper::FormBuilderAdditions)
diff --git a/lib/generators/nifty/layout/templates/layout.html.haml b/lib/generators/nifty/layout/templates/layout.html.haml
new file mode 100644
index 0000000..24ec1d6
--- /dev/null
+++ b/lib/generators/nifty/layout/templates/layout.html.haml
@@ -0,0 +1,21 @@
+!!!
+%html
+
+ %head
+ %title
+ = content_for?(:title) ? yield(:title) : "Untitled"
+ %meta{"http-equiv"=>"Content-Type", :content=>"text/html; charset=utf-8"}/
+ = stylesheet_link_tag "application"
+ = javascript_include_tag "application"
+ = csrf_meta_tag
+ = yield(:head)
+
+ %body
+ #container
+ - flash.each do |name, msg|
+ = content_tag :div, msg, :id => "flash_#{name}"
+
+ - if show_title?
+ %h1= yield(:title)
+
+ = yield
diff --git a/lib/generators/nifty/layout/templates/layout_helper.rb b/lib/generators/nifty/layout/templates/layout_helper.rb
new file mode 100644
index 0000000..93011d6
--- /dev/null
+++ b/lib/generators/nifty/layout/templates/layout_helper.rb
@@ -0,0 +1,38 @@
+# These helper methods can be called in your template to set variables to be used in the layout
+# This module should be included in all views globally,
+# to do so you may need to add this line to your ApplicationController
+# helper :layout
+module LayoutHelper
+
+ def title(page_title, show_title = true)
+ content_for(:title) { strip_tags(page_title.to_s) }
+ @show_title = show_title
+ end
+
+ def show_title?
+ @show_title
+ end
+
+ def stylesheet(*args)
+ content_for(:head) { stylesheet_link_tag(*args) }
+ end
+
+ def javascript(*args)
+ content_for(:head) { javascript_include_tag(*args) }
+ end
+
+ def translation_missing?(output)
+ (output =~ /span/ or output.empty?)
+ end
+
+ def conditional_hint(translation_key)
+ output = t(translation_key)
+ return output unless translation_missing?(output)
+ false
+ end
+
+ def conditional_t(translation_key)
+ output = t(translation_key)
+ strip_tags(output)
+ end
+end \ No newline at end of file
diff --git a/lib/generators/nifty/layout/templates/stylesheet.css b/lib/generators/nifty/layout/templates/stylesheet.css
new file mode 100644
index 0000000..448a53f
--- /dev/null
+++ b/lib/generators/nifty/layout/templates/stylesheet.css
@@ -0,0 +1,83 @@
+html, body {
+ background-color: #4B7399;
+ font-family: Verdana, Helvetica, Arial;
+ font-size: 14px;
+}
+
+a img {
+ border: none;
+}
+
+a {
+ color: #0000FF;
+}
+
+.clear {
+ clear: both;
+ height: 0;
+ overflow: hidden;
+}
+
+#container {
+ width: 75%;
+ margin: 0 auto;
+ background-color: #FFF;
+ padding: 20px 40px;
+ border: solid 1px black;
+ margin-top: 20px;
+}
+
+#flash_notice, #flash_error, #flash_alert {
+ padding: 5px 8px;
+ margin: 10px 0;
+}
+
+#flash_notice {
+ background-color: #CFC;
+ border: solid 1px #6C6;
+}
+
+#flash_error, #flash_alert {
+ background-color: #FCC;
+ border: solid 1px #C66;
+}
+
+.error_messages {
+ width: 400px;
+ border: 2px solid #CF0000;
+ padding: 0px;
+ padding-bottom: 12px;
+ margin-bottom: 20px;
+ background-color: #f0f0f0;
+ font-size: 12px;
+}
+
+.error_messages h2 {
+ text-align: left;
+ font-weight: bold;
+ padding: 5px 10px;
+ font-size: 12px;
+ margin: 0;
+ background-color: #c00;
+ color: #fff;
+}
+
+.error_messages p {
+ margin: 8px 10px;
+}
+
+.error_messages ul {
+ margin: 0;
+}
+
+.field_with_errors {
+ display: inline;
+}
+
+form .field, form .actions {
+ margin: 10px 0;
+}
+
+form label {
+ display: block;
+}
diff --git a/lib/generators/nifty/layout/templates/stylesheet.sass b/lib/generators/nifty/layout/templates/stylesheet.sass
new file mode 100644
index 0000000..383bfd3
--- /dev/null
+++ b/lib/generators/nifty/layout/templates/stylesheet.sass
@@ -0,0 +1,73 @@
+$primary_color: #4b7399
+
+body
+ background-color: $primary_color
+ font:
+ family: Verdana, Helvetica, Arial
+ size: 14px
+
+a
+ color: blue
+ img
+ border: none
+
+.clear
+ clear: both
+ height: 0
+ overflow: hidden
+
+#container
+ width: 75%
+ margin: 0 auto
+ background: white
+ padding: 20px 40px
+ border: solid 1px black
+ margin-top: 20px
+
+#flash_notice,
+#flash_error,
+#flash_alert
+ padding: 5px 8px
+ margin: 10px 0
+
+#flash_notice
+ background-color: #ccffcc
+ border: solid 1px #66cc66
+
+#flash_error,
+#flash_alert
+ background-color: #ffcccc
+ border: solid 1px #cc6666
+
+.error_messages
+ width: 400px
+ border: 2px solid #cf0000
+ padding: 0
+ padding-bottom: 12px
+ margin-bottom: 20px
+ background-color: #f0f0f0
+ font:
+ size: 12px
+ h2
+ text-align: left
+ padding: 5px 5px 5px 15px
+ margin: 0
+ font:
+ weight: bold
+ size: 12px
+ background-color: #cc0000
+ color: white
+ p
+ margin: 8px 10px
+ ul
+ margin: 0
+
+.field_with_errors
+ display: inline
+
+form .field,
+form .actions
+ margin: 10px 0
+
+form label
+ display: block
diff --git a/lib/generators/nifty/scaffold/USAGE b/lib/generators/nifty/scaffold/USAGE
new file mode 100644
index 0000000..363fd26
--- /dev/null
+++ b/lib/generators/nifty/scaffold/USAGE
@@ -0,0 +1,51 @@
+Description:
+ Scaffolds an entire resource, from model and migration to controller and
+ views. The resource is ready to use as a starting point for your restful,
+ resource-oriented application. Tests or specs are also generated depending
+ on if you have a "spec" directory or not.
+
+ IMPORTANT: This generator uses the "title" helper method which is generated
+ by the nifty_layout generator. You may want to run that generator first.
+
+Usage:
+ Pass the name of the model, either CamelCased or under_scored, as the first
+ argument along with an optional list of attribute pairs and controller actions.
+
+ If no controller actions are specified, they will default to index, show,
+ new, create, edit, update, and destroy.
+
+ IMPORTANT: If no attribute pairs are specified, no model will be generated.
+ It will try to determine the attributes from an existing model.
+
+ Attribute pairs are column_name:sql_type arguments specifying the
+ model's attributes. Timestamps are added by default, so you don't have to
+ specify them by hand as 'created_at:datetime updated_at:datetime'.
+
+ For example, `nifty:scaffold post name:string content:text hidden:boolean`
+ gives you a model with those three attributes, a controller that handles
+ the create/show/update/destroy, forms to create and edit your posts, and
+ an index that lists them all, as well as a map.resources :posts
+ declaration in config/routes.rb.
+
+ Adding an "!" in the mix of arguments will invert the passed controller
+ actions. This will include all 7 controller actitons except the ones
+ mentioned. This option doesn't affect model attributes.
+
+Examples:
+ rails generate nifty:scaffold post
+
+ Will create a controller called "posts" it will contain all seven
+ CRUD actions along with the views. A model will NOT be created,
+ instead it will look for an existing model and use those attributes.
+
+ rails generate nifty:scaffold post name:string content:text index new edit
+
+ Will create a Post model and migration file with the name and content
+ attributes. It will also create a controller with index, new, create,
+ edit, and update actions. Notice the create and update actions are
+ added automatically with new and edit.
+
+ rails generate nifty:scaffold post ! show new
+
+ Creates a posts controller (no model) with index, edit, update, and
+ destroy actions.
diff --git a/lib/generators/nifty/scaffold/scaffold_generator.rb b/lib/generators/nifty/scaffold/scaffold_generator.rb
new file mode 100644
index 0000000..1283e17
--- /dev/null
+++ b/lib/generators/nifty/scaffold/scaffold_generator.rb
@@ -0,0 +1,344 @@
+require 'generators/nifty'
+require 'rails/generators/migration'
+require 'rails/generators/generated_attribute'
+
+module Nifty
+ module Generators
+ class ScaffoldGenerator < Base
+ include Rails::Generators::Migration
+ no_tasks { attr_accessor :scaffold_name, :model_attributes, :controller_actions }
+
+ argument :scaffold_name, :type => :string, :required => true, :banner => 'ModelName'
+ argument :args_for_c_m, :type => :array, :default => [], :banner => 'controller_actions and model:attributes'
+
+ class_option :skip_model, :desc => 'Don\'t generate a model or migration file.', :type => :boolean
+ class_option :skip_migration, :desc => 'Don\'t generate migration file for model.', :type => :boolean
+ class_option :skip_timestamps, :desc => 'Don\'t add timestamps to migration file.', :type => :boolean
+ class_option :skip_controller, :desc => 'Don\'t generate controller, helper, or views.', :type => :boolean
+ class_option :invert, :desc => 'Generate all controller actions except these mentioned.', :type => :boolean
+ class_option :namespace_model, :desc => 'If the resource is namespaced, include the model in the namespace.', :type => :boolean
+ class_option :haml, :desc => 'Generate HAML views instead of ERB.', :type => :boolean, :default => true
+
+ class_option :testunit, :desc => 'Use test/unit for test files.', :group => 'Test framework', :type => :boolean
+ class_option :rspec, :desc => 'Use RSpec for test files.', :group => 'Test framework', :type => :boolean
+ class_option :shoulda, :desc => 'Use shoulda for test files.', :group => 'Test framework', :type => :boolean
+
+ def initialize(*args, &block)
+ super
+
+ print_usage unless scaffold_name.underscore =~ /^[a-z][a-z0-9_\/]+$/
+
+ @controller_actions = []
+ @model_attributes = []
+ @skip_model = options.skip_model?
+ @namespace_model = options.namespace_model?
+ @invert_actions = options.invert?
+
+ args_for_c_m.each do |arg|
+ if arg == '!'
+ @invert_actions = true
+ elsif arg.include?(':')
+ @model_attributes << Rails::Generators::GeneratedAttribute.new(*arg.split(':'))
+ else
+ @controller_actions << arg
+ @controller_actions << 'create' if arg == 'new'
+ @controller_actions << 'update' if arg == 'edit'
+ end
+ end
+
+ @controller_actions.uniq!
+ @model_attributes.uniq!
+
+ if @invert_actions || @controller_actions.empty?
+ @controller_actions = all_actions - @controller_actions
+ end
+
+ if @model_attributes.empty?
+ @skip_model = true # skip model if no attributes
+ if model_exists?
+ model_columns_for_attributes.each do |column|
+ @model_attributes << Rails::Generators::GeneratedAttribute.new(column.name.to_s, column.type.to_s)
+ end
+ else
+ @model_attributes << Rails::Generators::GeneratedAttribute.new('name', 'string')
+ end
+ end
+ end
+
+ def add_gems
+ # add_gem "mocha", :group => :test
+ add_gem 'haml'
+ add_gem 'simple_form'
+ add_gem 'cancan'
+ end
+
+ def create_model
+ unless @skip_model
+ template 'model.rb', "app/models/#{model_path}.rb"
+ if test_framework == :rspec
+ template "tests/rspec/model.rb", "spec/models/#{model_path}_spec.rb"
+ # FUCK YOU FIXTURES, WE USE FACTORY GIRL.
+ # template 'fixtures.yml', "spec/fixtures/#{model_path.pluralize}.yml"
+ else
+ template "tests/#{test_framework}/model.rb", "test/unit/#{model_path}_test.rb"
+ template 'fixtures.yml', "test/fixtures/#{model_path.pluralize}.yml"
+ end
+ end
+ end
+
+ def create_migration
+ unless @skip_model || options.skip_migration?
+ migration_template 'migration.rb', "db/migrate/create_#{model_path.pluralize.gsub('/', '_')}.rb"
+ end
+ end
+
+ def create_controller
+ unless options.skip_controller?
+ template 'controller.rb', "app/controllers/#{plural_name}_controller.rb"
+
+ template 'helper.rb', "app/helpers/#{plural_name}_helper.rb"
+
+ controller_actions.each do |action|
+ if %w[index show new edit].include?(action) # Actions with templates
+ template "views/#{view_language}/#{action}.html.#{view_language}", "app/views/#{plural_name}/#{action}.html.#{view_language}"
+ end
+ end
+
+ # Move the index_core (can't do it on the top.)
+ template "views/#{view_language}/_index_core.html.#{view_language}", "app/views/#{plural_name}/_index_core.html.#{view_language}"
+
+
+ if form_partial?
+ template "views/#{view_language}/_form.html.#{view_language}", "app/views/#{plural_name}/_form.html.#{view_language}"
+ template "views/#{view_language}/_form_core.html.#{view_language}", "app/views/#{plural_name}/_form_core.html.#{view_language}"
+ end
+
+ namespaces = plural_name.split('/')
+ resource = namespaces.pop
+ route namespaces.reverse.inject("resources :#{resource}") { |acc, namespace|
+ "namespace(:#{namespace}){ #{acc} }"
+ }
+
+ if test_framework == :rspec
+ template "tests/#{test_framework}/controller.rb", "spec/controllers/#{plural_name}_controller_spec.rb"
+ else
+ template "tests/#{test_framework}/controller.rb", "test/functional/#{plural_name}_controller_test.rb"
+ end
+ end
+ end
+
+ def create_locales
+ template 'locale.yml', "config/locales/views/#{plural_name}/en.yml"
+ template 'locale_de.yml', "config/locales/views/#{plural_name}/de.yml"
+ # template 'locale.yml', "config/locales/views/#{plural_name}/es.yml"
+ # gsub_file("config/locales/views/#{plural_name}/es.yml", 'en:', 'es:')
+ # gsub_file("config/locales/views/#{plural_name}/de.yml", 'en:', 'de:')
+ end
+
+ def configuration
+ gsub_file('config/application.rb', "# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]",
+ "config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '*', '*', '*.{rb,yml}').to_s]")
+ end
+
+ private
+
+ def form_partial?
+ actions? :new, :edit
+ end
+
+ def all_actions
+ %w[index show new create edit update destroy]
+ end
+
+ def action?(name)
+ controller_actions.include? name.to_s
+ end
+
+ def actions?(*names)
+ names.all? { |name| action? name }
+ end
+
+ def singular_name
+ scaffold_name.underscore
+ end
+
+ def plural_name
+ scaffold_name.underscore.pluralize
+ end
+
+ def human_name
+ scaffold_name.humanize
+ end
+
+ def table_name
+ if scaffold_name.include?('::') && @namespace_model
+ plural_name.gsub('/', '_')
+ end
+ end
+
+ def class_name
+ if @namespace_model
+ scaffold_name.camelize
+ else
+ scaffold_name.split('::').last.camelize
+ end
+ end
+
+ def model_path
+ class_name.underscore
+ end
+
+ def plural_class_name
+ plural_name.camelize
+ end
+
+ def instance_name
+ if @namespace_model
+ singular_name.gsub('/','_')
+ else
+ singular_name.split('/').last
+ end
+ end
+
+ def instances_name
+ instance_name.pluralize
+ end
+
+ def controller_methods(dir_name)
+ controller_actions.map do |action|
+ read_template("#{dir_name}/#{action}.rb")
+ end.join("\n").strip
+ end
+
+ def render_form
+ if form_partial?
+ if options.haml?
+ "= render \"form\""
+ else
+ "<%= render \"form\" %>"
+ end
+ else
+ read_template("views/#{view_language}/_form.html.#{view_language}")
+ end
+ end
+
+ def item_resource
+ scaffold_name.underscore.gsub('/','_')
+ end
+
+ def items_path
+ if action? :index
+ "#{item_resource.pluralize}_path"
+ else
+ "root_path"
+ end
+ end
+
+ def item_path(options = {})
+ name = options[:instance_variable] ? "@#{instance_name}" : instance_name
+ suffix = options[:full_url] ? "url" : "path"
+ if options[:action].to_s == "new"
+ "new_#{item_resource}_#{suffix}"
+ elsif options[:action].to_s == "edit"
+ "edit_#{item_resource}_#{suffix}(#{name})"
+ else
+ if scaffold_name.include?('::') && !@namespace_model
+ namespace = singular_name.split('/')[0..-2]
+ "[:#{namespace.join(', :')}, #{name}]"
+ else
+ name
+ end
+ end
+ end
+
+ def item_url
+ if action? :show
+ item_path(:full_url => true, :instance_variable => true)
+ else
+ items_url
+ end
+ end
+
+ def items_url
+ if action? :index
+ item_resource.pluralize + '_url'
+ else
+ "root_url"
+ end
+ end
+
+ def item_path_for_spec(suffix = 'path')
+ if action? :show
+ "#{item_resource}_#{suffix}(assigns[:#{instance_name}])"
+ else
+ if suffix == 'path'
+ items_path
+ else
+ items_url
+ end
+ end
+ end
+
+ def item_path_for_test(suffix = 'path')
+ if action? :show
+ "#{item_resource}_#{suffix}(assigns(:#{instance_name}))"
+ else
+ if suffix == 'path'
+ items_path
+ else
+ items_url
+ end
+ end
+ end
+
+ def model_columns_for_attributes
+ class_name.constantize.columns.reject do |column|
+ column.name.to_s =~ /^(id|created_at|updated_at)$/
+ end
+ end
+
+ def view_language
+ options.haml? ? 'haml' : 'erb'
+ end
+
+ def test_framework
+ return @test_framework if defined?(@test_framework)
+ if options.testunit?
+ return @test_framework = :testunit
+ elsif options.rspec?
+ return @test_framework = :rspec
+ elsif options.shoulda?
+ return @test_framework = :shoulda
+ else
+ return @test_framework = default_test_framework
+ end
+ end
+
+ def default_test_framework
+ File.exist?(destination_path("spec")) ? :rspec : :testunit
+ end
+
+ def model_exists?
+ File.exist? destination_path("app/models/#{singular_name}.rb")
+ end
+
+ def read_template(relative_path)
+ ERB.new(File.read(find_in_source_paths(relative_path)), nil, '-').result(binding)
+ end
+
+ def destination_path(path)
+ File.join(destination_root, path)
+ end
+
+ # FIXME: Should be proxied to ActiveRecord::Generators::Base
+ # Implement the required interface for Rails::Generators::Migration.
+ def self.next_migration_number(dirname) #:nodoc:
+ if ActiveRecord::Base.timestamped_migrations
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
+ else
+ "%.3d" % (current_migration_number(dirname) + 1)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/generators/nifty/scaffold/templates/actions/create.rb b/lib/generators/nifty/scaffold/templates/actions/create.rb
new file mode 100644
index 0000000..8365f0b
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/actions/create.rb
@@ -0,0 +1,8 @@
+ def create
+ @<%= instance_name %> = <%= class_name %>.new(params[:<%= instance_name %>])
+ if @<%= instance_name %>.save
+ redirect_to <%= item_url %>, :notice => t('<%= plural_name %>.controller.successfuly_created')
+ else
+ render :new
+ end
+ end
diff --git a/lib/generators/nifty/scaffold/templates/actions/destroy.rb b/lib/generators/nifty/scaffold/templates/actions/destroy.rb
new file mode 100644
index 0000000..8a236e0
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/actions/destroy.rb
@@ -0,0 +1,5 @@
+ def destroy
+ @<%= instance_name %> = <%= class_name %>.find(params[:id])
+ @<%= instance_name %>.destroy
+ redirect_to <%= items_url %>, :notice => t('<%= plural_name %>.controller.successfuly_destroyed')
+ end
diff --git a/lib/generators/nifty/scaffold/templates/actions/edit.rb b/lib/generators/nifty/scaffold/templates/actions/edit.rb
new file mode 100644
index 0000000..907e928
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/actions/edit.rb
@@ -0,0 +1,3 @@
+ def edit
+ @<%= instance_name %> = <%= class_name %>.find(params[:id])
+ end
diff --git a/lib/generators/nifty/scaffold/templates/actions/index.rb b/lib/generators/nifty/scaffold/templates/actions/index.rb
new file mode 100644
index 0000000..0a8420c
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/actions/index.rb
@@ -0,0 +1,3 @@
+ def index
+ @<%= instances_name %> = <%= class_name %>.all
+ end
diff --git a/lib/generators/nifty/scaffold/templates/actions/new.rb b/lib/generators/nifty/scaffold/templates/actions/new.rb
new file mode 100644
index 0000000..c0991bc
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/actions/new.rb
@@ -0,0 +1,3 @@
+ def new
+ @<%= instance_name %> = <%= class_name %>.new
+ end
diff --git a/lib/generators/nifty/scaffold/templates/actions/show.rb b/lib/generators/nifty/scaffold/templates/actions/show.rb
new file mode 100644
index 0000000..27a0467
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/actions/show.rb
@@ -0,0 +1,3 @@
+ def show
+ @<%= instance_name %> = <%= class_name %>.find(params[:id])
+ end
diff --git a/lib/generators/nifty/scaffold/templates/actions/update.rb b/lib/generators/nifty/scaffold/templates/actions/update.rb
new file mode 100644
index 0000000..a1473a6
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/actions/update.rb
@@ -0,0 +1,8 @@
+ def update
+ @<%= instance_name %> = <%= class_name %>.find(params[:id])
+ if @<%= instance_name %>.update_attributes(params[:<%= instance_name %>])
+ redirect_to <%= item_url %>, :notice => t('<%= plural_name %>.controller.successfuly_updated')
+ else
+ render :edit
+ end
+ end
diff --git a/lib/generators/nifty/scaffold/templates/controller.rb b/lib/generators/nifty/scaffold/templates/controller.rb
new file mode 100644
index 0000000..a54de70
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/controller.rb
@@ -0,0 +1,3 @@
+class <%= plural_class_name %>Controller < ApplicationController
+ <%= controller_methods :actions %>
+end
diff --git a/lib/generators/nifty/scaffold/templates/fixtures.yml b/lib/generators/nifty/scaffold/templates/fixtures.yml
new file mode 100644
index 0000000..447eaf9
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/fixtures.yml
@@ -0,0 +1,9 @@
+one:
+<%- for attribute in model_attributes -%>
+ <%= attribute.name %>: <%= attribute.default %>
+<%- end -%>
+
+two:
+<%- for attribute in model_attributes -%>
+ <%= attribute.name %>: <%= attribute.default %>
+<%- end -%>
diff --git a/lib/generators/nifty/scaffold/templates/helper.rb b/lib/generators/nifty/scaffold/templates/helper.rb
new file mode 100644
index 0000000..084b485
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/helper.rb
@@ -0,0 +1,2 @@
+module <%= plural_class_name %>Helper
+end
diff --git a/lib/generators/nifty/scaffold/templates/locale.yml b/lib/generators/nifty/scaffold/templates/locale.yml
new file mode 100644
index 0000000..46e4ce3
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/locale.yml
@@ -0,0 +1,46 @@
+en:
+ <%= plural_name %>:
+ name: '<%= human_name %>'
+ controller:
+ successfuly_created: 'Successfully created <%= human_name %>.'
+ successfuly_updated: 'Successfully updated <%= human_name %>.'
+ successfuly_destroyed: 'Successfully destroyed <%= human_name %>.'
+ index:
+ page_title: 'Listing <%= human_name %>'
+ <%- for attribute in model_attributes -%>
+ <%= attribute.name %>: '<%= attribute.human_name %>'
+ <%- end -%>
+ actions:
+ confirm: 'Are you sure you want to delete this <%= human_name %>?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ show: 'View'
+ create: 'New'
+ create_for: 'New <%= human_name %> for %{resource}'
+ show:
+ page_title: 'Show <%= human_name %>'
+ <%- for attribute in model_attributes -%>
+ <%= attribute.name %>: '<%= attribute.human_name %>'
+ <%- end -%>
+ actions:
+ confirm: 'Are you sure you want to delete this element?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ view_all: 'View All'
+ new:
+ page_title: 'New <%= human_name %>'
+ actions:
+ back_to_list: 'Back to Index'
+ edit:
+ page_title: 'Editing <%= human_name %>'
+ actions:
+ back_to_list: 'Back to Index'
+ edit: 'Edit'
+ view_all: 'View All'
+ form:
+ <%- for attribute in model_attributes -%>
+ <%= attribute.name %>:
+ label: '<%= attribute.human_name %>'
+ hint: ''
+ <%- end -%>
+ button: 'Submit' \ No newline at end of file
diff --git a/lib/generators/nifty/scaffold/templates/locale_de.yml b/lib/generators/nifty/scaffold/templates/locale_de.yml
new file mode 100644
index 0000000..027d36d
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/locale_de.yml
@@ -0,0 +1,46 @@
+de:
+ <%= plural_name %>:
+ name: '<%= human_name %>'
+ controller:
+ successfuly_created: '<%= human_name %> wurde angelegt.'
+ successfuly_updated: '<%= human_name %> wurde aktualisiert.'
+ successfuly_destroyed: '<%= human_name %> wurde gelöscht.'
+ index:
+ page_title: 'Übersicht von <%= human_name %>'
+ <%- for attribute in model_attributes -%>
+ <%= attribute.name %>: '<%= attribute.human_name %>'
+ <%- end -%>
+ actions:
+ confirm: 'Sind Sie sicher, dass Sie folgendes löschen möchten: <%= human_name %>'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ show: 'Anzeigen'
+ create: 'Neu anlegen'
+ create_for: '<%= human_name %> neu anlegen für %{resource}'
+ show:
+ page_title: '<%= human_name %> bearbeiten'
+ <%- for attribute in model_attributes -%>
+ <%= attribute.name %>: '<%= attribute.human_name %>'
+ <%- end -%>
+ actions:
+ confirm: 'Sind Sie sicher, dass die dieses Element löschen möchten?'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ new:
+ page_title: '<%= human_name %> neu anlegen'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit:
+ page_title: '<%= human_name %> bearbeiten'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ form:
+ <%- for attribute in model_attributes -%>
+ <%= attribute.name %>:
+ label: '<%= attribute.human_name %>'
+ hint: ''
+ <%- end -%>
+ button: 'Absenden' \ No newline at end of file
diff --git a/lib/generators/nifty/scaffold/templates/migration.rb b/lib/generators/nifty/scaffold/templates/migration.rb
new file mode 100644
index 0000000..02fd6bd
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/migration.rb
@@ -0,0 +1,16 @@
+class Create<%= class_name.pluralize.delete('::') %> < ActiveRecord::Migration
+ def self.up
+ create_table :<%= table_name || plural_name.split('/').last %> do |t|
+ <%- for attribute in model_attributes -%>
+ t.<%= attribute.type %> :<%= attribute.name %>
+ <%- end -%>
+ <%- unless options[:skip_timestamps] -%>
+ t.timestamps
+ <%- end -%>
+ end
+ end
+
+ def self.down
+ drop_table :<%= table_name || plural_name.split('/').last %>
+ end
+end
diff --git a/lib/generators/nifty/scaffold/templates/model.rb b/lib/generators/nifty/scaffold/templates/model.rb
new file mode 100644
index 0000000..fe5f980
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/model.rb
@@ -0,0 +1,4 @@
+class <%= class_name %> < ActiveRecord::Base
+<%= " set_table_name :#{table_name}\n" if table_name -%>
+ attr_accessible <%= model_attributes.map { |a| ":#{a.name}" }.join(", ") %>
+end
diff --git a/lib/generators/nifty/scaffold/templates/tests/rspec/actions/create.rb b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/create.rb
new file mode 100644
index 0000000..ef5a906
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/create.rb
@@ -0,0 +1,11 @@
+ it "create action should render new template when model is invalid" do
+ <%= class_name %>.any_instance.stubs(:valid?).returns(false)
+ post :create
+ response.should render_template(:new)
+ end
+
+ it "create action should redirect when model is valid" do
+ <%= class_name %>.any_instance.stubs(:valid?).returns(true)
+ post :create
+ response.should redirect_to(<%= item_path_for_spec('url') %>)
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/rspec/actions/destroy.rb b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/destroy.rb
new file mode 100644
index 0000000..8372953
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/destroy.rb
@@ -0,0 +1,6 @@
+ it "destroy action should destroy model and redirect to index action" do
+ <%= instance_name %> = <%= class_name %>.first
+ delete :destroy, :id => <%= instance_name %>
+ response.should redirect_to(<%= items_url %>)
+ <%= class_name %>.exists?(<%= instance_name %>.id).should be_false
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/rspec/actions/edit.rb b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/edit.rb
new file mode 100644
index 0000000..e144904
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/edit.rb
@@ -0,0 +1,4 @@
+ it "edit action should render edit template" do
+ get :edit, :id => <%= class_name %>.first
+ response.should render_template(:edit)
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/rspec/actions/index.rb b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/index.rb
new file mode 100644
index 0000000..a40ea16
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/index.rb
@@ -0,0 +1,4 @@
+ it "index action should render index template" do
+ get :index
+ response.should render_template(:index)
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/rspec/actions/new.rb b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/new.rb
new file mode 100644
index 0000000..22e1b40
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/new.rb
@@ -0,0 +1,4 @@
+ it "new action should render new template" do
+ get :new
+ response.should render_template(:new)
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/rspec/actions/show.rb b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/show.rb
new file mode 100644
index 0000000..eaa3d93
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/show.rb
@@ -0,0 +1,4 @@
+ it "show action should render show template" do
+ get :show, :id => <%= class_name %>.first
+ response.should render_template(:show)
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/rspec/actions/update.rb b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/update.rb
new file mode 100644
index 0000000..c919962
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/rspec/actions/update.rb
@@ -0,0 +1,11 @@
+ it "update action should render edit template when model is invalid" do
+ <%= class_name %>.any_instance.stubs(:valid?).returns(false)
+ put :update, :id => <%= class_name %>.first
+ response.should render_template(:edit)
+ end
+
+ it "update action should redirect when model is valid" do
+ <%= class_name %>.any_instance.stubs(:valid?).returns(true)
+ put :update, :id => <%= class_name %>.first
+ response.should redirect_to(<%= item_path_for_spec('url') %>)
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/rspec/controller.rb b/lib/generators/nifty/scaffold/templates/tests/rspec/controller.rb
new file mode 100644
index 0000000..5d97f63
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/rspec/controller.rb
@@ -0,0 +1,8 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe <%= plural_class_name %>Controller do
+ fixtures :all
+ render_views
+
+ <%= controller_methods 'tests/rspec/actions' %>
+end
diff --git a/lib/generators/nifty/scaffold/templates/tests/rspec/model.rb b/lib/generators/nifty/scaffold/templates/tests/rspec/model.rb
new file mode 100644
index 0000000..25c3cc4
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/rspec/model.rb
@@ -0,0 +1,7 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe <%= class_name %> do
+ it "should be valid" do
+ <%= class_name %>.new.should be_valid
+ end
+end
diff --git a/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/create.rb b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/create.rb
new file mode 100644
index 0000000..f305367
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/create.rb
@@ -0,0 +1,13 @@
+ context "create action" do
+ should "render new template when model is invalid" do
+ <%= class_name %>.any_instance.stubs(:valid?).returns(false)
+ post :create
+ assert_template 'new'
+ end
+
+ should "redirect when model is valid" do
+ <%= class_name %>.any_instance.stubs(:valid?).returns(true)
+ post :create
+ assert_redirected_to <%= item_path_for_test('url') %>
+ end
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/destroy.rb b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/destroy.rb
new file mode 100644
index 0000000..ea20133
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/destroy.rb
@@ -0,0 +1,8 @@
+ context "destroy action" do
+ should "destroy model and redirect to index action" do
+ <%= instance_name %> = <%= class_name %>.first
+ delete :destroy, :id => <%= instance_name %>
+ assert_redirected_to <%= items_url %>
+ assert !<%= class_name %>.exists?(<%= instance_name %>.id)
+ end
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/edit.rb b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/edit.rb
new file mode 100644
index 0000000..47597d0
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/edit.rb
@@ -0,0 +1,6 @@
+ context "edit action" do
+ should "render edit template" do
+ get :edit, :id => <%= class_name %>.first
+ assert_template 'edit'
+ end
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/index.rb b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/index.rb
new file mode 100644
index 0000000..44b056b
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/index.rb
@@ -0,0 +1,6 @@
+ context "index action" do
+ should "render index template" do
+ get :index
+ assert_template 'index'
+ end
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/new.rb b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/new.rb
new file mode 100644
index 0000000..5857a55
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/new.rb
@@ -0,0 +1,6 @@
+ context "new action" do
+ should "render new template" do
+ get :new
+ assert_template 'new'
+ end
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/show.rb b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/show.rb
new file mode 100644
index 0000000..75b37f6
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/show.rb
@@ -0,0 +1,6 @@
+ context "show action" do
+ should "render show template" do
+ get :show, :id => <%= class_name %>.first
+ assert_template 'show'
+ end
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/update.rb b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/update.rb
new file mode 100644
index 0000000..fc46f72
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/update.rb
@@ -0,0 +1,13 @@
+ context "update action" do
+ should "render edit template when model is invalid" do
+ <%= class_name %>.any_instance.stubs(:valid?).returns(false)
+ put :update, :id => <%= class_name %>.first
+ assert_template 'edit'
+ end
+
+ should "redirect when model is valid" do
+ <%= class_name %>.any_instance.stubs(:valid?).returns(true)
+ put :update, :id => <%= class_name %>.first
+ assert_redirected_to <%= item_path_for_test('url') %>
+ end
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/shoulda/controller.rb b/lib/generators/nifty/scaffold/templates/tests/shoulda/controller.rb
new file mode 100644
index 0000000..e9f9764
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/shoulda/controller.rb
@@ -0,0 +1,5 @@
+require 'test_helper'
+
+class <%= plural_class_name %>ControllerTest < ActionController::TestCase
+ <%= controller_methods 'tests/shoulda/actions' %>
+end
diff --git a/lib/generators/nifty/scaffold/templates/tests/shoulda/model.rb b/lib/generators/nifty/scaffold/templates/tests/shoulda/model.rb
new file mode 100644
index 0000000..9065963
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/shoulda/model.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class <%= class_name %>Test < ActiveSupport::TestCase
+ should "be valid" do
+ assert <%= class_name %>.new.valid?
+ end
+end
diff --git a/lib/generators/nifty/scaffold/templates/tests/testunit/actions/create.rb b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/create.rb
new file mode 100644
index 0000000..5a6d2ac
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/create.rb
@@ -0,0 +1,11 @@
+ def test_create_invalid
+ <%= class_name %>.any_instance.stubs(:valid?).returns(false)
+ post :create
+ assert_template 'new'
+ end
+
+ def test_create_valid
+ <%= class_name %>.any_instance.stubs(:valid?).returns(true)
+ post :create
+ assert_redirected_to <%= item_path_for_test('url') %>
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/testunit/actions/destroy.rb b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/destroy.rb
new file mode 100644
index 0000000..adedf91
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/destroy.rb
@@ -0,0 +1,6 @@
+ def test_destroy
+ <%= instance_name %> = <%= class_name %>.first
+ delete :destroy, :id => <%= instance_name %>
+ assert_redirected_to <%= items_url %>
+ assert !<%= class_name %>.exists?(<%= instance_name %>.id)
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/testunit/actions/edit.rb b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/edit.rb
new file mode 100644
index 0000000..55ed24a
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/edit.rb
@@ -0,0 +1,4 @@
+ def test_edit
+ get :edit, :id => <%= class_name %>.first
+ assert_template 'edit'
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/testunit/actions/index.rb b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/index.rb
new file mode 100644
index 0000000..22d3bad
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/index.rb
@@ -0,0 +1,4 @@
+ def test_index
+ get :index
+ assert_template 'index'
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/testunit/actions/new.rb b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/new.rb
new file mode 100644
index 0000000..c551327
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/new.rb
@@ -0,0 +1,4 @@
+ def test_new
+ get :new
+ assert_template 'new'
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/testunit/actions/show.rb b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/show.rb
new file mode 100644
index 0000000..b74f371
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/show.rb
@@ -0,0 +1,4 @@
+ def test_show
+ get :show, :id => <%= class_name %>.first
+ assert_template 'show'
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/testunit/actions/update.rb b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/update.rb
new file mode 100644
index 0000000..b588bfc
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/testunit/actions/update.rb
@@ -0,0 +1,11 @@
+ def test_update_invalid
+ <%= class_name %>.any_instance.stubs(:valid?).returns(false)
+ put :update, :id => <%= class_name %>.first
+ assert_template 'edit'
+ end
+
+ def test_update_valid
+ <%= class_name %>.any_instance.stubs(:valid?).returns(true)
+ put :update, :id => <%= class_name %>.first
+ assert_redirected_to <%= item_path_for_test('url') %>
+ end
diff --git a/lib/generators/nifty/scaffold/templates/tests/testunit/controller.rb b/lib/generators/nifty/scaffold/templates/tests/testunit/controller.rb
new file mode 100644
index 0000000..8b99836
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/testunit/controller.rb
@@ -0,0 +1,49 @@
+require 'test_helper'
+
+class <%= plural_class_name %>ControllerTest < ActionController::TestCase
+ setup do
+ <%= item_path :instance_variable => true %> = <%= plural_name %>(:one)
+ end
+
+ test "should get index" do
+ get :index
+ assert_response :success
+ assert_not_nil assigns(:<%= plural_name %>)
+ end
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should create <%= item_path %>" do
+ assert_difference('<%= class_name %>.count') do
+ post :create, <%= item_path %>: @<%= item_path %>.attributes
+ end
+
+ assert_redirected_to <%= item_path %>_path(assigns(:<%= item_path %>))
+ end
+
+ test "should show <%= item_path %>" do
+ get :show, id: @<%= item_path %>.to_param
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get :edit, id: @<%= item_path %>.to_param
+ assert_response :success
+ end
+
+ test "should update <%= item_path %>" do
+ put :update, id: @<%= item_path %>.to_param, <%= item_path %>: @<%= item_path %>.attributes
+ assert_redirected_to <%= item_path %>_path(assigns(:<%= item_path %>))
+ end
+
+ test "should destroy <%= item_path %>" do
+ assert_difference('<%= class_name %>.count', -1) do
+ delete :destroy, id: @<%= item_path %>.to_param
+ end
+
+ assert_redirected_to <%= plural_name %>_path
+ end
+end
diff --git a/lib/generators/nifty/scaffold/templates/tests/testunit/model.rb b/lib/generators/nifty/scaffold/templates/tests/testunit/model.rb
new file mode 100644
index 0000000..09b835c
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/tests/testunit/model.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class <%= class_name %>Test < ActiveSupport::TestCase
+ def test_should_be_valid
+ assert <%= class_name %>.new.valid?
+ end
+end
diff --git a/lib/generators/nifty/scaffold/templates/views/haml/_form.html.haml b/lib/generators/nifty/scaffold/templates/views/haml/_form.html.haml
new file mode 100644
index 0000000..57cb828
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/views/haml/_form.html.haml
@@ -0,0 +1,7 @@
+= simple_form_for(<%= item_path :instance_variable => true %>) do |f|
+ = f.error_notification
+
+ = render "form_core", :f => f
+
+ .actions
+ = f.button :submit, conditional_t('<%= plural_name %>.form.submit') \ No newline at end of file
diff --git a/lib/generators/nifty/scaffold/templates/views/haml/_form_core.html.haml b/lib/generators/nifty/scaffold/templates/views/haml/_form_core.html.haml
new file mode 100644
index 0000000..ca7f253
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/views/haml/_form_core.html.haml
@@ -0,0 +1,4 @@
+.inputs
+<%- model_attributes.each do |attribute| -%>
+ = f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %>, :label => t('<%= plural_name %>.form.<%= attribute.name %>.label'), :hint => conditional_hint('<%= plural_name %>.form.<%= attribute.name %>.hint')
+<%- end -%>
diff --git a/lib/generators/nifty/scaffold/templates/views/haml/_index_core.html.haml b/lib/generators/nifty/scaffold/templates/views/haml/_index_core.html.haml
new file mode 100644
index 0000000..9cbea63
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/views/haml/_index_core.html.haml
@@ -0,0 +1,13 @@
+%table
+ %tr
+ <%- for attribute in model_attributes -%>
+ %th= t('<%= plural_name %>.index.<%= attribute.name %>')
+ <%- end -%>
+
+ - reset_cycle
+ - for <%= instance_name %> in <%= instances_name %>
+ %tr{:class => cycle('odd', 'even')}
+ <%- for attribute in model_attributes -%>
+ %td= <%= instance_name %>.<%= attribute.name %>
+ <%- end -%>
+ =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:child => <%= instance_name %>} \ No newline at end of file
diff --git a/lib/generators/nifty/scaffold/templates/views/haml/edit.html.haml b/lib/generators/nifty/scaffold/templates/views/haml/edit.html.haml
new file mode 100644
index 0000000..dc7de62
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/views/haml/edit.html.haml
@@ -0,0 +1,3 @@
+- title t("<%= plural_name %>.edit.page_title")
+
+<%= render_form %> \ No newline at end of file
diff --git a/lib/generators/nifty/scaffold/templates/views/haml/index.html.haml b/lib/generators/nifty/scaffold/templates/views/haml/index.html.haml
new file mode 100644
index 0000000..86c6b9e
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/views/haml/index.html.haml
@@ -0,0 +1,6 @@
+- title t("<%= plural_name %>.index.page_title")
+
+- if @<%= instances_name %> && @<%= instances_name %>.count > 0
+ = render "index_core", :<%= instances_name %> => @<%= instances_name %>
+
+= render :partial => 'shared/create_link', :locals => {:child_class => <%= instances_name.classify %>} \ No newline at end of file
diff --git a/lib/generators/nifty/scaffold/templates/views/haml/new.html.haml b/lib/generators/nifty/scaffold/templates/views/haml/new.html.haml
new file mode 100644
index 0000000..4e7f871
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/views/haml/new.html.haml
@@ -0,0 +1,3 @@
+- title t("<%= plural_name %>.new.page_title")
+
+<%= render_form %> \ No newline at end of file
diff --git a/lib/generators/nifty/scaffold/templates/views/haml/show.html.haml b/lib/generators/nifty/scaffold/templates/views/haml/show.html.haml
new file mode 100644
index 0000000..3d01340
--- /dev/null
+++ b/lib/generators/nifty/scaffold/templates/views/haml/show.html.haml
@@ -0,0 +1,9 @@
+- title t("<%= plural_name %>.show.page_title")
+
+<%- for attribute in model_attributes -%>
+%p
+ %strong= t('<%= plural_name %>.show.<%= attribute.name %>') + ":"
+ = @<%= instance_name %>.<%= attribute.name %>
+<%- end -%>
+
+= render :partial => 'shared/show_edit_destroy_part', :locals => { :child => @<%= instance_name %> } \ No newline at end of file