Last update on April 1th, 2010
Rails is a wonderful framework which help us to develop a modern web application. However, when you create a new one, you should perform several pretty boring operations: add plugins / gems, rescue a starting layout and whatever you usually use in yours applications.
To solve this, from version 2.3 you may use templates. You find lots of examples on internet, i give you another that show you how to take advantage of it combining with a cool rails generator. This guide explains how to make one. If you are impatient you can choose something already done, forking an existing project so did I. I customized Ryan Bates’s nifty-generators adding some new features:
- nifty_layout now supports multiple styles: classic, and blackwhite cloudy. It are only a starting point
- nifty_layout: I added the configuration file config.rb which is a container for all the application constants for example application name, the default style etc..
- I introduced localization support: nifty_layout added YAML files for language en and it. To manage, some code is inserted into application controller: with the lang parameter you change the language setting (for example ?lang=en) that will be maintained throughout the session. The nifty_scaffold adds resources and its attributes, ready to be translated.
- nifty_layout: the posts division has been moved into a partial in the shared folder. I preferred to do this to use it even through ajax
- nifty_scaffold: the “new” and “edit” views now use two partial: render @ model which calls the second with the fields inside. So do the original version, it supports haml and sass, furthermore, I added support for formtastic. So you can choose the preferred combination!
The template I will show you download these new generators for you, however, these are the sources or you can even download latest gem and template.
What the generator should do and what the template?
Well, templates should be a container of things to do, executed only one time after creating a new project. Generators should create something like adding new files or customize something that already exists and can be executes whenever you want as well as within a template.
If you never have used a template before, you could start with a simple one or a tutorial could be even better:
this screencast show you how to make a template.
This is an article in html format.
I see many examples on internet which are filled with configuration’s parameters, that cause me strong headaches. I opted for one that ask me what i want. Surely, isn’t perfect yet but I think it’s a good base :
#This is a Rails 2.3 template #Written by Marco Mastrodonato, last update on 01/04/2010 # # USAGE: rails yourapp -m template.rb #This is the unique parameter, after first execution use FALSE to avoid installation install_gems = false git_http = true WINDOWS = (RUBY_PLATFORM =~ /dos|win32|cygwin/i) || (RUBY_PLATFORM =~ /(:?mswin|mingw)/) #plugin/install doesn't work on my windows systems def myplugin(name, url) url.sub! 'git://', 'http://' if git_http if WINDOWS #run "ruby script/plugin install #{url}" run "git clone #{url} vendor/plugins/#{name}" else plugin name, :git => url end end puts '*' * 40 puts "* Processing template#{WINDOWS ? ' on windows system': ''}..." puts '*' * 40 use_git = yes?("Do you think to use git ?") if use_git git :init file ".gitignore", <<-EOS.gsub(/^ /, '') .DS_Store log/*.log tmp/**/* config/database.yml db/*.sqlite3 nbproject/* EOS end #Everyone must to have it! plugin 'will_paginate', :git => "git://github.com/mislav/will_paginate.git" if yes?("Will Paginate ?") # Attachments with no extra database tables, only one library to install for image processing plugin 'paperclip', :git => "git://github.com/thoughtbot/paperclip.git" if yes?("Paperclip ?") formtastic = yes?("Formtastic ?") if formtastic #gem 'justinfrench-formtastic', :lib => 'formtastic', :source => 'http://gems.github.com' #rake "gems:install" if install_gem #A Rails FormBuilder DSL (with some other goodies) to make it far easier to create beautiful, semantically rich, syntactically awesome, readily stylable and wonderfully accessible HTML forms in your Rails applications. plugin 'formtastic', :git => "git://github.com/justinfrench/formtastic.git" #Adds reflective access to validations plugin 'validation_reflection', :git => "git://github.com/redinger/validation_reflection.git" generate "formtastic" end if yes?("Add testing framework ?") # RSpec's official Ruby on Rails plugin plugin 'rspec', :git => 'git://github.com/dchelimsky/rspec.git' plugin 'rspec-rails', :git => "git://github.com/dchelimsky/rspec-rails.git" generate "rspec" # BDD that talks to domain experts first and code 2nd plugin 'cucumber', :git => "git://github.com/aslakhellesoy/cucumber.git" end if yes?("Add authentication ?") puts "0. None" puts "1. Devise/warden" puts "2. Authlogic" puts "3. Restful authentication" choose = ask("Choose one:") case choose when "1" gem "warden", :version => "0.9.6" gem "devise", :version => "1.0.4" rake "gems:install" if install_gems generate "devise_install" generate "devise", "User" generate "devise_views" #User.create!(:email => 'admin@administrator.com', :password => 'secret') when "2" gem "authlogic" rake "gems:install" if install_gems generate "session", "user_session" generate "model", "user" generate "controller", "user_sessions" route "map.resource :user_session" create_users_file = Dir['db/migrate/*_create_users.rb'].first file create_users_file, <<-EOS.gsub(/^ /, '') class CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.string :login, :null => false # optional, you can use email instead, or both t.string :email, :null => false # optional, you can use login instead, or both t.string :crypted_password, :null => false # optional, see below t.string :password_salt, :null => false # optional, but highly recommended t.string :persistence_token, :null => false # required t.string :single_access_token, :null => false # optional, see Authlogic::Session::Params t.string :perishable_token, :null => false # optional, see Authlogic::Session::Perishability # Magic columns, just like ActiveRecord's created_at and updated_at. These are automatically maintained by Authlogic if they are present. t.integer :login_count, :null => false, :default => 0 # optional, see Authlogic::Session::MagicColumns t.integer :failed_login_count, :null => false, :default => 0 # optional, see Authlogic::Session::MagicColumns t.datetime :last_request_at # optional, see Authlogic::Session::MagicColumns t.datetime :current_login_at # optional, see Authlogic::Session::MagicColumns t.datetime :last_login_at # optional, see Authlogic::Session::MagicColumns t.string :current_login_ip # optional, see Authlogic::Session::MagicColumns t.string :last_login_ip # optional, see Authlogic::Session::MagicColumns t.timestamps end add_index :users, :email add_index :users, :login, :unique => true end def self.down drop_table :users end end EOS file 'app/models/user.rb', <<-EOS.gsub(/^ /, '') class User < ActiveRecord::Base acts_as_authentic end EOS file 'spec/models/user_spec.rb', <<-EOS.gsub(/^ /, '') require 'spec_helper' describe User do before(:each) do @valid_attributes = { :login => "login", :email => "some@thing.com", :password => "password", :password_confirmation => "password" } end it "should create a new instance given valid attributes" do User.create!(@valid_attributes) end end EOS when "3" plugin 'restful-authentication-i18n', :git => "git://github.com/dcrec1/restful-authentication-i18n.git" #—include-activation \ —stateful \ —rspec \ —skip-migration \ —skip-routes \ —old-passwords generate "authenticated", "user", "sessions", "—include-activation" end if yes?("Authorization ?") gem "cancan" rake "gems:install" if install_gems #plugin 'cancan', :git => "git://github.com/ryanb/cancan.git" file 'spec/models/ability.rb', <<-EOS.gsub(/^ /, '') class Ability include CanCan::Ability def initialize(user) user ||= User.new # Guest user if user.role? :admin can :manage, :all else can :read, :all end end end EOS generate "migration", "add_roles_mask_to_users roles_mask:integer" puts "Add these lines to user model:" puts <<-EOS.gsub(/^ /, '') named_scope :with_role, lambda { |role| {:conditions => "roles_mask & \#{2**ROLES.index(role.to_s)} > 0 "} } def roles=(roles) self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum end def roles ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? } end def role_symbols roles.map(&:to_sym) end EOS end end haml = yes?("Haml?") if haml # The world's greatest templating system #plugin 'haml', :git => "git://github.com/nex3/haml.git" gem "haml", :lib => "haml" rake "gems:install" if install_gems run "haml --rails ." end if yes?("Layout ?") plugin "marcomd-nifty-generators", :lib => "marcomd-nifty-generators", :git => "git://github.com/marcomd/nifty-generators.git" puts " 1. classic" puts " 2. cloudy" puts " 3. blackwhite" puts "or. write names separed by space" style = ask("Choose style:") style = case style when "1" then "classic" when "2" then "cloudy" when "3" then "blackwhite" else style end generate "nifty_layout", "application #{style} #{haml ? '--haml' : ''} #{formtastic ? '--formtastic' : ''}" end # Link to local copy of edge rails #inside('vendor') { run 'ln -s ~/dev/rails/rails rails' } if yes?("Rails ?") rake("rails:freeze:gems") if yes?("Freeze rails gems ?") # Mailer dummy config initializer "mailer.rb", <<-EOS.gsub(/^ /, '') mailer_options = YAML.load_file("\#{Rails.root}/config/mailer.yml") ActionMailer::Base.smtp_settings = mailer_options EOS file "config/mailer.yml", <<-EOS.gsub(/^ /, '') :address: mail.authsmtp.com :domain: yourdomain.com :authentication: :login :user_name: USERNAME :password: PASSWORD EOS if yes?("Generate controller home ? (suggested)") generate "controller", "home", "index" route "map.root :controller => :home" else end rake "gems:install" if install_gems # Unpack all gems to vendor/gems rake "gems:unpack" if yes?("Unpack to vendor/gems ?") rake "db:create:all" rake "db:migrate" File.unlink "public/index.html" git :add => ".", :commit => "-m 'initial commit'" if use_git puts "ENJOY!"
This is a result:
marco@d9400:~/Rails$ rails Blog -m marcomd.rb
create bla bla bla
applying template: marcomd.rb
Processing template...
plugin will_paginate
Unpacking objects: 100% (57/57), done.
From git://github.com/mislav/will_paginate
* branch HEAD -> FETCH_HEAD
Paperclip ?
y
plugin paperclip
Unpacking objects: 100% (78/78), done.
From git://github.com/thoughtbot/paperclip
* branch HEAD -> FETCH_HEAD
Formtastic ?
y
gem justinfrench-formtastic
generating formtastic_stylesheets
Add testing framework ?
y
plugin rspec
From git://github.com/dchelimsky/rspec
* branch HEAD -> FETCH_HEAD
plugin rspec-rails
From git://github.com/dchelimsky/rspec-rails
* branch HEAD -> FETCH_HEAD
plugin cucumber
From git://github.com/aslakhellesoy/cucumber
* branch HEAD -> FETCH_HEAD
Add authentication ?
y
0. None
1. Devise/warden
2. Authlogic
3. Restful authentication
Choose one:
1
gem warden
gem devise
generating devise_install
Authorization ?
n
Haml?
n
Layout ?
y
plugin marcomd-nifty-generators
From git://github.com/marcomd/nifty-generators
* branch HEAD -> FETCH_HEAD
1. classic
2. cloudy
3. blackwhite
or. write names separed by space
Choose style:
2
generating nifty_layout
Freeze rails gems ?
n
initializer mailer.rb
file config/mailer.yml
Generate controller home ? (suggested)
y
generating controller
route map.root :controller => :home
Unpack to vendor/gems ?
n
rake db:create:all
rake db:migrate
ENJOY!
applied marcomd.rb
And here we are! Now let’s start up mongrel…
marco@d9400:~/Rails$ cd Blog/
marco@d9400:~/Rails/Blog$ script/server
=> Booting Mongrel
=> Rails 2.3.5 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
Now, let’s add the post resource and migrate:
marco@d9400:~/Rails$ cd Blog/
marco@d9400:~/Rails/Blog$ script/generate nifty_scaffold post title:string body:text
exists app/models
create app/models/post.rb
exists db/migrate
create db/migrate/20100319175545_create_posts.rb
exists test/unit
create test/unit/post_test.rb
exists test/fixtures
create test/fixtures/posts.yml
exists app/controllers
create app/controllers/posts_controller.rb
exists app/helpers
create app/helpers/posts_helper.rb
create app/views/posts
create app/views/posts/index.html.erb
create app/views/posts/show.html.erb
create app/views/posts/new.html.erb
create app/views/posts/edit.html.erb
create app/views/posts/_post.html.erb
create app/views/posts/_fields.html.erb
route map.resources :posts
exists test/functional
create test/functional/posts_controller_test.rb
marco@d9400:~/Rails/Blog$ rake db:migrate
(in /home/marco/Rails/Blog)
== CreatePosts: migrating ====================================================
-- create_table(:posts)
-> 0.0016s
== CreatePosts: migrated (0.0017s) ===========================================
Controllers and views uses I18n messages, for this reason, the new resource must be add to localization files. Nifty_scaffold will do it for you :
#config/locales/en.yml
en:
activerecord:
models: &models
post: "Post"
posts: "Posts"
#DO NOT REMOVE MODELS
attributes: &attributes
title: "Title"
body: "Body"
#DO NOT REMOVE ATTRIBUTES
formtastic:
titles:
labels:
hints:
post:
title: "Choose a good title for your article"
body: "Choose a good body for your article"
#DO NOT REMOVE HINTS
actions: &actions
create: "Create my {{model}}"
update: "Save changes"
<<: *models
<<: *attributes
<<: *actions
#config/locales/it.yml
it:
activerecord:
models: &models
post: "Messaggio"
posts: "Messaggi"
#DO NOT REMOVE MODELS
attributes: &attributes
title: "Titolo"
body: "Corpo"
#DO NOT REMOVE ATTRIBUTES
formtastic:
titles:
labels:
hints:
post:
title: "Choose a good title for your article"
body: "Choose a good body for your article"
#DO NOT REMOVE HINTS
actions: &actions
create: "Crea {{model}}"
update: "Salva le modifiche"
#DO NOT REMOVE FORMTASTIC
<<: *models
<<: *attributes
<<: *actionsI have to use tag #DO NOT REMOVE ecc. to put attributes and resource name inside so please don’t remove it.
I recently began testing Haml and Sass version for which there may be still some bugs.
I hope this can be helpful, enjoy!




English
Italiano