beet 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +2 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +13 -0
  4. data/Rakefile +59 -0
  5. data/TODO +17 -0
  6. data/VERSION +1 -0
  7. data/beet.gemspec +89 -0
  8. data/bin/beet +112 -0
  9. data/features/generating.feature +24 -0
  10. data/features/step_definitions/beet_steps.rb +7 -0
  11. data/features/step_definitions/common_steps.rb +172 -0
  12. data/features/support/common.rb +33 -0
  13. data/features/support/env.rb +25 -0
  14. data/lib/beet.rb +10 -0
  15. data/lib/beet/capistrano.rb +14 -0
  16. data/lib/beet/execution.rb +50 -0
  17. data/lib/beet/executor.rb +195 -0
  18. data/lib/beet/file_system.rb +143 -0
  19. data/lib/beet/gem_location_map.rb +64 -0
  20. data/lib/beet/interaction.rb +37 -0
  21. data/lib/beet/logger.rb +44 -0
  22. data/lib/beet/rails.rb +146 -0
  23. data/lib/beet/recipes/passenger/vhost.rb +17 -0
  24. data/lib/beet/recipes/rack/middleware.rb +17 -0
  25. data/lib/beet/recipes/rails/authlogic.rb +297 -0
  26. data/lib/beet/recipes/rails/clean_files.rb +4 -0
  27. data/lib/beet/recipes/rails/clearance.rb +22 -0
  28. data/lib/beet/recipes/rails/cms/bcms_blog.rb +21 -0
  29. data/lib/beet/recipes/rails/cms/bcms_event.rb +24 -0
  30. data/lib/beet/recipes/rails/css/blueprint.rb +5 -0
  31. data/lib/beet/recipes/rails/css/reset.rb +10 -0
  32. data/lib/beet/recipes/rails/db/mysql.rb +42 -0
  33. data/lib/beet/recipes/rails/db/postgres.rb +52 -0
  34. data/lib/beet/recipes/rails/git.rb +23 -0
  35. data/lib/beet/recipes/rails/jquery.rb +11 -0
  36. data/lib/beet/recipes/rails/rspec.rb +3 -0
  37. data/lib/beet/recipes/rails/shoulda.rb +1 -0
  38. data/lib/beet/scm.rb +36 -0
  39. data/lib/beet/scm/git.rb +15 -0
  40. data/lib/beet/scm/svn.rb +5 -0
  41. data/lib/beet/template_location_map.rb +13 -0
  42. data/test/executor_test.rb +24 -0
  43. data/test/file_system_test.rb +59 -0
  44. data/test/test_helper.rb +12 -0
  45. metadata +110 -0
@@ -0,0 +1,64 @@
1
+ GEM_LOCATIONS = {
2
+ 'restful-authentcation' => 'git://github.com/technoweenie/restful-authentication.git',
3
+ 'authlogic' => 'git://github.com/binarylogic/authlogic.git',
4
+ 'clearance' => 'git://github.com/thoughtbot/clearance.git',
5
+ 'will_paginate' => 'git://github.com/mislav/will_paginate.git',
6
+ 'paperclip' => 'git://github.com/thoughtbot/paperclip.git',
7
+ 'attachment_fu' => 'git://github.com/technoweenie/attachment_fu.git',
8
+ 'rspec' => 'git://github.com/dchelimsky/rspec.git',
9
+ 'rspec-rails' => 'git://github.com/dchelimsky/rspec-rails.git',
10
+ 'cucumber' => 'git://github.com/aslakhellesoy/cucumber.git',
11
+ 'shoulda' => 'git://github.com/thoughtbot/shoulda.git',
12
+ 'matchy' => 'git://github.com/jeremymcanally/matchy.git',
13
+ 'context' => 'git://github.com/jeremymcanally/context.git',
14
+ 'exception-notifier' => 'git://github.com/Lipsiasoft/exception-notifier.git',
15
+ 'asset_packager' => 'git://github.com/sbecker/asset_packager.git',
16
+ 'acts_as_list' => 'git://github.com/rails/acts_as_list.git',
17
+ 'acts_as_tree' => 'git://github.com/rails/acts_as_tree.git',
18
+ 'webrat' => 'git://github.com/brynary/webrat.git',
19
+ 'rcov' => 'git://github.com/relevance/rcov.git',
20
+ 'rcov_plugin' => 'git://github.com/commondream/rcov_plugin.git',
21
+ 'flog' => 'git://github.com/seattlerb/flog.git',
22
+ 'flay' => 'git://github.com/seattlerb/flay.git',
23
+ 'hoe' => 'git://github.com/seattlerb/hoe.git',
24
+ 'integrity' => 'git://github.com/integrity/integrity.git',
25
+ 'active_merchant' => 'git://github.com/Shopify/active_merchant.git',
26
+ 'spree' => 'git://github.com/railsdog/spree.git',
27
+ 'exception_notification' => 'git://github.com/rails/exception_notification.git',
28
+ 'hoptoad_notifier' => 'git://github.com/thoughtbot/hoptoad_notifier.git',
29
+ 'exception_logger' => 'git://github.com/defunkt/exception_logger.git',
30
+ 'jeweler' => 'git://github.com/technicalpickles/jeweler.git',
31
+ 'newgem' => 'git://github.com/drnic/newgem.git',
32
+ 'bones' => 'git://github.com/TwP/bones.git',
33
+ 'echoe' => 'git://github.com/fauna/echoe.git',
34
+ 'nokogiri' => 'git://github.com/tenderlove/nokogiri.git',
35
+ 'hpricot' => 'git://github.com/why/hpricot.git',
36
+ 'httparty' => 'git://github.com/jnunemaker/httparty.git',
37
+ 'rest-client' => 'git://github.com/adamwiggins/rest-client.git',
38
+ 'typoeus' => 'git://github.com/pauldix/typhoeus.git',
39
+ 'redcloth' => 'git://github.com/jgarber/redcloth.git',
40
+ 'rdiscount' => 'git://github.com/rtomayko/rdiscount.git',
41
+ 'bluecloth' => 'git://github.com/mislav/bluecloth.git',
42
+ 'rr' => 'git://github.com/btakita/rr.git',
43
+ 'mocha' => 'git://github.com/floehopper/mocha.git',
44
+ 'stump' => 'git://github.com/jeremymcanally/stump.git',
45
+ 'active_scaffold' => 'git://github.com/activescaffold/active_scaffold.git',
46
+ 'delayed_job' => 'git://github.com/tobi/delayed_job.git',
47
+ 'starling' => 'git://github.com/starling/starling.git',
48
+ 'amqp' => 'git://github.com/tmm1/amqp.git',
49
+ 'negative-captcha' => 'git://github.com/subwindow/negative-captcha.git',
50
+ 'factory_girl' => 'git://github.com/thoughtbot/factory_girl.git',
51
+ 'machinist' => 'git://github.com/notahat/machinist.git',
52
+ 'thinking-sphinx' => 'git://github.com/freelancing-god/thinking-sphinx.git',
53
+ 'acts-as-taggable-on' => 'git://github.com/mbleigh/acts-as-taggable-on.git',
54
+ 'is_taggable' => 'git://github.com/giraffesoft/is_taggable.git',
55
+ 'forgery' => 'git://github.com/sevenwire/forgery.git',
56
+ 'faker' => 'git://github.com/yyyc514/faker.git',
57
+ 'whenever' => 'git://github.com/javan/whenever.git',
58
+ 'aasm' => 'git://github.com/rubyist/aasm.git',
59
+ 'workflow' => 'git://github.com/ryan-allen/workflow.git',
60
+ 'chef' => 'git://github.com/opscode/chef.git',
61
+ 'passenger' => 'git://github.com/FooBarWidget/passenger.git',
62
+ 'thin' => 'git://github.com/macournoyer/thin.git',
63
+ 'happymapper' => 'git://github.com/jnunemaker/happymapper.git',
64
+ }
@@ -0,0 +1,37 @@
1
+ module Beet
2
+ module Interaction
3
+ # Get a user's input
4
+ #
5
+ # ==== Example
6
+ #
7
+ # answer = ask("Should I freeze the latest Rails?")
8
+ # freeze! if ask("Should I freeze the latest Rails?") == "yes"
9
+ #
10
+ def ask(string)
11
+ log '', string
12
+ print '> '
13
+ STDIN.gets.strip
14
+ end
15
+
16
+ # Helper to test if the user says yes(y)?
17
+ #
18
+ # ==== Example
19
+ #
20
+ # freeze! if yes?("Should I freeze the latest Rails?")
21
+ #
22
+ def yes?(question)
23
+ answer = ask(question).downcase
24
+ answer == "y" || answer == "yes"
25
+ end
26
+
27
+ # Helper to test if the user does NOT say yes(y)?
28
+ #
29
+ # ==== Example
30
+ #
31
+ # capify! if no?("Will you be using vlad to deploy your application?")
32
+ #
33
+ def no?(question)
34
+ !yes?(question)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,44 @@
1
+ module Beet
2
+ class Logger # :nodoc:
3
+ attr_reader :out
4
+ attr_accessor :quiet
5
+
6
+ def initialize(out = $stdout)
7
+ @out = out
8
+ @quiet = false
9
+ @level = 0
10
+ end
11
+
12
+ def log(status, message, &block)
13
+ @out.print("%12s %s%s\n" % [status, ' ' * @level, message]) unless quiet
14
+ indent(&block) if block_given?
15
+ end
16
+
17
+ def indent(&block)
18
+ @level += 1
19
+ if block_given?
20
+ begin
21
+ block.call
22
+ ensure
23
+ outdent
24
+ end
25
+ end
26
+ end
27
+
28
+ def outdent
29
+ @level -= 1
30
+ if block_given?
31
+ begin
32
+ block.call
33
+ ensure
34
+ indent
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+ def method_missing(method, *args, &block)
41
+ log(method.to_s, args.first, &block)
42
+ end
43
+ end
44
+ end
data/lib/beet/rails.rb ADDED
@@ -0,0 +1,146 @@
1
+ module Beet
2
+ module Rails
3
+ # Make an entry in Rails routing file conifg/routes.rb
4
+ #
5
+ # === Example
6
+ #
7
+ # route "map.root :controller => :welcome"
8
+ #
9
+ def route(routing_code)
10
+ log 'route', routing_code
11
+ sentinel = 'ActionController::Routing::Routes.draw do |map|'
12
+
13
+ in_root do
14
+ gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
15
+ "#{match}\n #{routing_code}\n"
16
+ end
17
+ end
18
+ end
19
+
20
+ # Add Rails to /vendor/rails
21
+ #
22
+ # ==== Example
23
+ #
24
+ # freeze!
25
+ #
26
+ def freeze!(args = {})
27
+ log 'vendor', 'rails edge'
28
+ in_root { run('rake rails:freeze:edge', false) }
29
+ end
30
+
31
+ # Install a plugin. You must provide either a Subversion url or Git url.
32
+ # For a Git-hosted plugin, you can specify if it should be added as a submodule instead of cloned.
33
+ #
34
+ # ==== Examples
35
+ #
36
+ # plugin 'restful-authentication', :git => 'git://github.com/technoweenie/restful-authentication.git'
37
+ # plugin 'restful-authentication', :git => 'git://github.com/technoweenie/restful-authentication.git', :submodule => true
38
+ # plugin 'restful-authentication', :svn => 'svn://svnhub.com/technoweenie/restful-authentication/trunk'
39
+ #
40
+ def plugin(name, options)
41
+ log 'plugin', name
42
+
43
+ if options[:git] && options[:submodule]
44
+ in_root do
45
+ Git.run("submodule add #{options[:git]} vendor/plugins/#{name}")
46
+ end
47
+ elsif options[:git] || options[:svn]
48
+ in_root do
49
+ run_ruby_script("script/plugin install #{options[:svn] || options[:git]}", false)
50
+ end
51
+ else
52
+ log "! no git or svn provided for #{name}. skipping..."
53
+ end
54
+ end
55
+
56
+ # Adds an entry into config/environment.rb for the supplied gem :
57
+ def gem(name, options = {})
58
+ log 'gem', name
59
+ env = options.delete(:env)
60
+
61
+ gems_code = "config.gem '#{name}'"
62
+
63
+ if options.any?
64
+ opts = options.inject([]) {|result, h| result << [":#{h[0]} => #{h[1].inspect.gsub('"',"'")}"] }.sort.join(", ")
65
+ gems_code << ", #{opts}"
66
+ end
67
+
68
+ environment gems_code, :env => env
69
+ end
70
+
71
+ # Adds a line inside the Initializer block for config/environment.rb. Used by #gem
72
+ # If options :env is specified, the line is appended to the corresponding
73
+ # file in config/environments/#{env}.rb
74
+ def environment(data = nil, options = {}, &block)
75
+ sentinel = 'Rails::Initializer.run do |config|'
76
+
77
+ data = block.call if !data && block_given?
78
+
79
+ in_root do
80
+ if options[:env].nil?
81
+ gsub_file 'config/environment.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
82
+ "#{match}\n " << data
83
+ end
84
+ else
85
+ Array.wrap(options[:env]).each do|env|
86
+ append_file "config/environments/#{env}.rb", "\n#{data}"
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ # Create a new file in the vendor/ directory. Code can be specified
93
+ # in a block or a data string can be given.
94
+ #
95
+ # ==== Examples
96
+ #
97
+ # vendor("sekrit.rb") do
98
+ # sekrit_salt = "#{Time.now}--#{3.years.ago}--#{rand}--"
99
+ # "salt = '#{sekrit_salt}'"
100
+ # end
101
+ #
102
+ # vendor("foreign.rb", "# Foreign code is fun")
103
+ #
104
+ def vendor(filename, data = nil, &block)
105
+ log 'vendoring', filename
106
+ file("vendor/#{filename}", data, false, &block)
107
+ end
108
+
109
+
110
+ # Create a new initializer with the provided code (either in a block or a string).
111
+ #
112
+ # ==== Examples
113
+ #
114
+ # initializer("globals.rb") do
115
+ # data = ""
116
+ #
117
+ # ['MY_WORK', 'ADMINS', 'BEST_COMPANY_EVAR'].each do
118
+ # data << "#{const} = :entp"
119
+ # end
120
+ #
121
+ # data
122
+ # end
123
+ #
124
+ # initializer("api.rb", "API_KEY = '123456'")
125
+ #
126
+ def initializer(filename, data = nil, &block)
127
+ log 'initializer', filename
128
+ file("config/initializers/#{filename}", data, false, &block)
129
+ end
130
+
131
+ # Generate something using a generator from Rails or a plugin.
132
+ # The second parameter is the argument string that is passed to
133
+ # the generator or an Array that is joined.
134
+ #
135
+ # ==== Example
136
+ #
137
+ # generate(:authenticated, "user session")
138
+ #
139
+ def generate(what, *args)
140
+ log 'generating', what
141
+ argument = args.map {|arg| arg.to_s }.flatten.join(" ")
142
+
143
+ in_root { run_ruby_script("script/generate #{what} #{argument}", false) }
144
+ end
145
+ end # Rails
146
+ end # Beet
@@ -0,0 +1,17 @@
1
+ file "#{project_name}.local.vhost.conf" do
2
+ %{
3
+ <VirtualHost *:80>
4
+ ServerName #{project_name}.local
5
+ DocumentRoot "#{root}/public"
6
+ RackEnv development
7
+ <directory "#{root}/public">
8
+ Order allow,deny
9
+ Allow from all
10
+ </directory>
11
+ </VirtualHost>
12
+ }.strip
13
+ end
14
+ default_to = "/etc/apache2/passenger_pane_vhosts"
15
+ answer = ask "Write file to: [#{default_to} default]"
16
+ filename = answer.empty? ? default_to : answer
17
+ sudo "mv ./#{project_name}.local.vhost.conf #{filename}"
@@ -0,0 +1,17 @@
1
+ file project_name + ".rb" do
2
+ %{
3
+ module Rack
4
+ class #{project_name}
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ [200, {'Content-Type' => 'text/html', 'Content-Length' => 100}, ['Hello World']]
12
+ end
13
+ end
14
+ end
15
+ }.strip
16
+ end
17
+
@@ -0,0 +1,297 @@
1
+ file "app/models/user_session.rb" do
2
+ %{
3
+ class UserSession < Authlogic::Session::Base
4
+ logout_on_timeout true # default is false
5
+ end
6
+ }.strip
7
+ end
8
+
9
+ file "app/models/user.rb" do
10
+ %{
11
+ class User < ActiveRecord::Base
12
+ acts_as_authentic do |c|
13
+ c.logged_in_timeout = 10.minutes # default is 10.minutes
14
+ end
15
+ end
16
+ }.strip
17
+ end
18
+
19
+ file "app/controllers/user_sessions_controller.rb" do
20
+ %{
21
+ class UserSessionsController < ApplicationController
22
+ before_filter :require_no_user, :only => [:new, :create]
23
+ before_filter :require_user, :only => :destroy
24
+
25
+ def new
26
+ @user_session = UserSession.new
27
+ end
28
+
29
+ def create
30
+ @user_session = UserSession.new(params[:user_session])
31
+ if @user_session.save
32
+ flash[:notice] = "Login successful!"
33
+ redirect_back_or_default account_url
34
+ else
35
+ render :action => :new
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ current_user_session.destroy
41
+ flash[:notice] = "Logout successful!"
42
+ redirect_back_or_default new_user_session_url
43
+ end
44
+ end
45
+ }.strip
46
+ end
47
+
48
+
49
+ file "app/views/user_sessions/new.html.erb" do
50
+ %{
51
+ <h1>Login</h1>
52
+
53
+ <% form_for @user_session, :url => user_session_path do |f| %>
54
+ <%= f.error_messages %>
55
+ <%= f.label :email %><br />
56
+ <%= f.text_field :email %><br />
57
+ <br />
58
+ <%= f.label :password %><br />
59
+ <%= f.password_field :password %><br />
60
+ <br />
61
+ <%= f.check_box :remember_me %><%= f.label :remember_me %><br />
62
+ <br />
63
+ <%= f.submit "Login" %>
64
+ <% end %>
65
+ }.strip
66
+ end
67
+
68
+ # Setup some routes
69
+ route 'map.resource :user_session'
70
+ route 'map.resource :account, :controller => "users"'
71
+ route 'map.resources :users'
72
+ route 'map.register "/register", :controller => "users", :action => "new"'
73
+ route 'map.login "/login", :controller => "user_sessions", :action => "new"'
74
+ route 'map.logout "/logout", :controller => "user_sessions", :action => "destroy"'
75
+
76
+ file "app/controllers/application_controller.rb" do
77
+ %{
78
+ # Filters added to this controller apply to all controllers in the application.
79
+ # Likewise, all the methods added will be available for all controllers.
80
+
81
+ class ApplicationController < ActionController::Base
82
+ helper :all
83
+ helper_method :current_user_session, :current_user
84
+ filter_parameter_logging :password, :password_confirmation
85
+
86
+ private
87
+ def current_user_session
88
+ return @current_user_session if defined?(@current_user_session)
89
+ @current_user_session = UserSession.find
90
+ end
91
+
92
+ def current_user
93
+ return @current_user if defined?(@current_user)
94
+ @current_user = current_user_session && current_user_session.record
95
+ end
96
+
97
+ def require_user
98
+ unless current_user
99
+ store_location
100
+ flash[:notice] = "You must be logged in to access this page"
101
+ redirect_to new_user_session_url
102
+ return false
103
+ end
104
+ end
105
+
106
+ def require_no_user
107
+ if current_user
108
+ store_location
109
+ flash[:notice] = "You must be logged out to access this page"
110
+ redirect_to account_url
111
+ return false
112
+ end
113
+ end
114
+
115
+ def store_location
116
+ session[:return_to] = request.request_uri
117
+ end
118
+
119
+ def redirect_back_or_default(default)
120
+ redirect_to(session[:return_to] || default)
121
+ session[:return_to] = nil
122
+ end
123
+ end
124
+ }.strip
125
+ end
126
+
127
+ file "app/controllers/users_controller.rb" do
128
+ %{
129
+ class UsersController < ApplicationController
130
+ before_filter :require_no_user, :only => [:new, :create]
131
+ before_filter :require_user, :only => [:show, :edit, :update]
132
+
133
+ def new
134
+ @user = User.new
135
+ end
136
+
137
+ def create
138
+ @user = User.new(params[:user])
139
+ if @user.save
140
+ flash[:notice] = "Account registered!"
141
+ redirect_back_or_default account_url
142
+ else
143
+ render :action => :new
144
+ end
145
+ end
146
+
147
+ def show
148
+ @user = @current_user
149
+ end
150
+
151
+ def edit
152
+ @user = @current_user
153
+ end
154
+
155
+ def update
156
+ @user = @current_user # makes our views "cleaner" and more consistent
157
+ if @user.update_attributes(params[:user])
158
+ flash[:notice] = "Account updated!"
159
+ redirect_to account_url
160
+ else
161
+ render :action => :edit
162
+ end
163
+ end
164
+ end
165
+ }.strip
166
+ end
167
+
168
+ file "app/views/users/_form.html.erb" do
169
+ %{
170
+ <%= form.label :email %><br />
171
+ <%= form.text_field :email %><br />
172
+ <br />
173
+ <%= form.label :password, form.object.new_record? ? nil : "Change password" %><br />
174
+ <%= form.password_field :password %><br />
175
+ <br />
176
+ <%= form.label :password_confirmation %><br />
177
+ <%= form.password_field :password_confirmation %><br />
178
+ }.strip
179
+ end
180
+
181
+ file "app/views/users/edit.html.erb" do
182
+ %{
183
+ <h1>Edit My Account</h1>
184
+
185
+ <% form_for @user, :url => account_path do |f| %>
186
+ <%= f.error_messages %>
187
+ <%= render :partial => "form", :object => f %>
188
+ <%= f.submit "Update" %>
189
+ <% end %>
190
+
191
+ <br /><%= link_to "My Profile", account_path %>
192
+ }.strip
193
+ end
194
+
195
+ file "app/views/users/new.html.erb" do
196
+ %{
197
+ <h1>Register</h1>
198
+
199
+ <% form_for @user, :url => account_path do |f| %>
200
+ <%= f.error_messages %>
201
+ <%= render :partial => "form", :object => f %>
202
+ <%= f.submit "Register" %>
203
+ <% end %>
204
+ }.strip
205
+ end
206
+
207
+ file "app/views/users/show.html.erb" do
208
+ %{
209
+ <p>
210
+ <b>Email:</b>
211
+ <%=h @user.email %>
212
+ </p>
213
+
214
+ <p>
215
+ <b>Login count:</b>
216
+ <%=h @user.login_count %>
217
+ </p>
218
+
219
+ <p>
220
+ <b>Last request at:</b>
221
+ <%=h @user.last_request_at %>
222
+ </p>
223
+
224
+ <p>
225
+ <b>Last login at:</b>
226
+ <%=h @user.last_login_at %>
227
+ </p>
228
+
229
+ <p>
230
+ <b>Current login at:</b>
231
+ <%=h @user.current_login_at %>
232
+ </p>
233
+
234
+ <p>
235
+ <b>Last login ip:</b>
236
+ <%=h @user.last_login_ip %>
237
+ </p>
238
+
239
+ <p>
240
+ <b>Current login ip:</b>
241
+ <%=h @user.current_login_ip %>
242
+ </p>
243
+
244
+
245
+ <%= link_to 'Edit', edit_account_path %>
246
+ }.strip
247
+ end
248
+
249
+ # can't rely on internal rails migration generation, so we do it this way
250
+
251
+ #Dir.chdir("script") #for ruby 1.9.2 08/07/2009 . no need for ruby1.9.1p129
252
+ #run "./generate migration beet_authlogic_create_user" # for ruby 1.9.2 08/07/2009. no need for ruby1.9.1p129
253
+
254
+ run "script/generate migration beet_authlogic_create_user"
255
+
256
+ #now open it
257
+ #Dir.chdir("..") # for ruby 1.9.2 08/07/2009. no need for ruby1.9.1p129
258
+
259
+ file(Dir.glob('db/migrate/*beet_authlogic_create_user*').first) do
260
+ %{
261
+ class BeetAuthlogicCreateUser < ActiveRecord::Migration
262
+ def self.up
263
+ unless table_exists?(:users)
264
+ create_table :users do |t|
265
+ t.string :email, :null => false # optional, you can use login instead, or both
266
+ t.string :crypted_password, :null => false # optional, see below
267
+ t.string :password_salt, :null => false # optional, but highly recommended
268
+ t.string :persistence_token, :null => false # required
269
+ t.string :single_access_token, :null => false # optional, see Authlogic::Session::Params
270
+ t.string :perishable_token, :null => false # optional, see Authlogic::Session::Perishability
271
+
272
+ # Magic columns, just like ActiveRecord's created_at and updated_at. These are automatically maintained by Authlogic if they are present.
273
+ t.integer :login_count, :null => false, :default => 0 # optional, see Authlogic::Session::MagicColumns
274
+ t.integer :failed_login_count, :null => false, :default => 0 # optional, see Authlogic::Session::MagicColumns
275
+ t.datetime :last_request_at # optional, see Authlogic::Session::MagicColumns
276
+ t.datetime :current_login_at # optional, see Authlogic::Session::MagicColumns
277
+ t.datetime :last_login_at # optional, see Authlogic::Session::MagicColumns
278
+ t.string :current_login_ip # optional, see Authlogic::Session::MagicColumns
279
+ t.string :last_login_ip # optional, see Authlogic::Session::MagicColumns
280
+ end
281
+ end
282
+ end
283
+
284
+ def self.down
285
+ drop_table :users
286
+ end
287
+ end
288
+ }.strip
289
+ end
290
+
291
+
292
+ gem 'authlogic', :version => '~> 2.0.0'
293
+
294
+ rake "gems:install", :sudo => true
295
+ rake "db:create:all"
296
+ rake "db:migrate"
297
+