beet 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|