beet 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/LICENSE +20 -0
- data/README.rdoc +13 -0
- data/Rakefile +59 -0
- data/TODO +17 -0
- data/VERSION +1 -0
- data/beet.gemspec +89 -0
- data/bin/beet +112 -0
- data/features/generating.feature +24 -0
- data/features/step_definitions/beet_steps.rb +7 -0
- data/features/step_definitions/common_steps.rb +172 -0
- data/features/support/common.rb +33 -0
- data/features/support/env.rb +25 -0
- data/lib/beet.rb +10 -0
- data/lib/beet/capistrano.rb +14 -0
- data/lib/beet/execution.rb +50 -0
- data/lib/beet/executor.rb +195 -0
- data/lib/beet/file_system.rb +143 -0
- data/lib/beet/gem_location_map.rb +64 -0
- data/lib/beet/interaction.rb +37 -0
- data/lib/beet/logger.rb +44 -0
- data/lib/beet/rails.rb +146 -0
- data/lib/beet/recipes/passenger/vhost.rb +17 -0
- data/lib/beet/recipes/rack/middleware.rb +17 -0
- data/lib/beet/recipes/rails/authlogic.rb +297 -0
- data/lib/beet/recipes/rails/clean_files.rb +4 -0
- data/lib/beet/recipes/rails/clearance.rb +22 -0
- data/lib/beet/recipes/rails/cms/bcms_blog.rb +21 -0
- data/lib/beet/recipes/rails/cms/bcms_event.rb +24 -0
- data/lib/beet/recipes/rails/css/blueprint.rb +5 -0
- data/lib/beet/recipes/rails/css/reset.rb +10 -0
- data/lib/beet/recipes/rails/db/mysql.rb +42 -0
- data/lib/beet/recipes/rails/db/postgres.rb +52 -0
- data/lib/beet/recipes/rails/git.rb +23 -0
- data/lib/beet/recipes/rails/jquery.rb +11 -0
- data/lib/beet/recipes/rails/rspec.rb +3 -0
- data/lib/beet/recipes/rails/shoulda.rb +1 -0
- data/lib/beet/scm.rb +36 -0
- data/lib/beet/scm/git.rb +15 -0
- data/lib/beet/scm/svn.rb +5 -0
- data/lib/beet/template_location_map.rb +13 -0
- data/test/executor_test.rb +24 -0
- data/test/file_system_test.rb +59 -0
- data/test/test_helper.rb +12 -0
- 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
|
data/lib/beet/logger.rb
ADDED
@@ -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
|
+
|