tft_rails 0.5.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 +6 -0
- data/.rvmrc +1 -0
- data/Gemfile +8 -0
- data/LICENSE +57 -0
- data/README.md +72 -0
- data/Rakefile +25 -0
- data/lib/generators/chapter07/begin/USAGE +27 -0
- data/lib/generators/chapter07/begin/begin_generator.rb +32 -0
- data/lib/generators/chapter07/begin/instructions.md +74 -0
- data/lib/generators/chapter07/begin/templates/app/controllers/application_controller.rb +8 -0
- data/lib/generators/chapter07/begin/templates/app/controllers/pages_controller.rb +11 -0
- data/lib/generators/chapter07/begin/templates/app/controllers/users_controller.rb +3 -0
- data/lib/generators/chapter07/begin/templates/app/helpers/application_helper.rb +12 -0
- data/lib/generators/chapter07/begin/templates/app/helpers/pages_helper.rb +2 -0
- data/lib/generators/chapter07/begin/templates/app/helpers/users_helper.rb +7 -0
- data/lib/generators/chapter07/begin/templates/app/models/user.rb +9 -0
- data/lib/generators/chapter07/begin/templates/app/views/layouts/_footer.html.erb +9 -0
- data/lib/generators/chapter07/begin/templates/app/views/layouts/_header.html.erb +10 -0
- data/lib/generators/chapter07/begin/templates/app/views/layouts/_stylesheets.html.erb +7 -0
- data/lib/generators/chapter07/begin/templates/app/views/layouts/application.html.erb +17 -0
- data/lib/generators/chapter07/begin/templates/app/views/pages/about.html.erb +7 -0
- data/lib/generators/chapter07/begin/templates/app/views/pages/contact.html.erb +5 -0
- data/lib/generators/chapter07/begin/templates/app/views/pages/home.html.erb +7 -0
- data/lib/generators/chapter07/begin/templates/app/views/users/show.html.erb +15 -0
- data/lib/generators/chapter07/begin/templates/config/initializers/devise.rb +194 -0
- data/lib/generators/chapter07/begin/templates/config/locales/devise.en.yml +50 -0
- data/lib/generators/chapter07/begin/templates/config/routes.rb.tt +17 -0
- data/lib/generators/chapter07/begin/templates/db/migrate/20110608224650_devise_create_users.rb +29 -0
- data/lib/generators/chapter07/begin/templates/db/schema.rb +34 -0
- data/lib/generators/chapter07/begin/templates/public/images/logo.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/ie.css +36 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/icons/cross.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/icons/key.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/icons/tick.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/readme.txt +32 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/screen.css +97 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/fancy-type/readme.txt +14 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/fancy-type/screen.css +71 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/doc.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/email.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/external.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/feed.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/im.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/lock.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/pdf.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/visited.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/xls.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/readme.txt +18 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/screen.css +42 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/rtl/readme.txt +10 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/rtl/screen.css +110 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/print.css +29 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/screen.css +265 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/forms.css +82 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/grid.css +280 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/grid.png +0 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/ie.css +79 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/print.css +92 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/reset.css +65 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/typography.css +123 -0
- data/lib/generators/chapter07/begin/templates/public/stylesheets/custom.css +137 -0
- data/lib/generators/chapter07/begin/templates/spec/controllers/pages_controller_07_spec.rb +48 -0
- data/lib/generators/chapter07/begin/templates/spec/controllers/users_controller_07_spec.rb +38 -0
- data/lib/generators/chapter07/begin/templates/spec/factories.rb +7 -0
- data/lib/generators/chapter07/begin/templates/spec/models/user_07_spec.rb +38 -0
- data/lib/generators/chapter07/begin/templates/spec/requests/layout_links_07_spec.rb +44 -0
- data/lib/generators/chapter07/begin/templates/spec/spec_helper.rb +29 -0
- data/lib/generators/chapter07/solutions/USAGE +21 -0
- data/lib/generators/chapter07/solutions/solutions_generator.rb +23 -0
- data/lib/generators/chapter07/solutions/templates/app/controllers/pages_controller.rb +18 -0
- data/lib/generators/chapter07/solutions/templates/app/controllers/users_controller.rb +8 -0
- data/lib/generators/chapter07/solutions/templates/app/models/user.rb +11 -0
- data/lib/generators/chapter07/solutions/templates/app/views/layouts/_footer.html.erb +10 -0
- data/lib/generators/chapter07/solutions/templates/app/views/layouts/_header.html.erb +11 -0
- data/lib/generators/chapter07/solutions/templates/app/views/pages/help.html.erb +4 -0
- data/lib/generators/chapter07/solutions/templates/app/views/pages/home.html.erb +7 -0
- data/lib/generators/chapter07/solutions/templates/app/views/users/show.html.erb +15 -0
- data/lib/generators/chapter08_09/begin/USAGE +24 -0
- data/lib/generators/chapter08_09/begin/begin_generator.rb +29 -0
- data/lib/generators/chapter08_09/begin/instructions.md +54 -0
- data/lib/generators/chapter08_09/begin/snippets/custom.css +49 -0
- data/lib/generators/chapter08_09/begin/templates/spec/controllers/devise/registrations_controller_08_spec.rb +83 -0
- data/lib/generators/chapter08_09/begin/templates/spec/requests/layout_links_09_spec.rb +35 -0
- data/lib/generators/chapter08_09/begin/templates/spec/requests/users_signup_08_spec.rb +36 -0
- data/lib/generators/chapter08_09/solutions/USAGE +18 -0
- data/lib/generators/chapter08_09/solutions/solutions_generator.rb +12 -0
- data/lib/generators/chapter08_09/solutions/templates/app/helpers/application_helper.rb +16 -0
- data/lib/generators/chapter08_09/solutions/templates/app/views/devise/passwords/edit.html.erb +16 -0
- data/lib/generators/chapter08_09/solutions/templates/app/views/devise/passwords/new.html.erb +12 -0
- data/lib/generators/chapter08_09/solutions/templates/app/views/devise/registrations/_fields.html.erb +16 -0
- data/lib/generators/chapter08_09/solutions/templates/app/views/devise/registrations/edit.html.erb +28 -0
- data/lib/generators/chapter08_09/solutions/templates/app/views/devise/registrations/new.html.erb +13 -0
- data/lib/generators/chapter08_09/solutions/templates/app/views/devise/sessions/new.html.erb +17 -0
- data/lib/generators/chapter08_09/solutions/templates/app/views/devise/shared/_links.erb +25 -0
- data/lib/generators/chapter08_09/solutions/templates/app/views/layouts/_header.html.erb +19 -0
- data/lib/generators/chapter08_09/solutions/templates/app/views/layouts/application.html.erb +20 -0
- data/lib/tft_rails.rb +2 -0
- metadata +160 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
Wraps up Test-First Teaching exercises adapted from Chapter 07 of the RailsTutorial by Michael Hartl.
|
|
3
|
+
|
|
4
|
+
Example:
|
|
5
|
+
rails generate chapter07:solutions
|
|
6
|
+
|
|
7
|
+
This copies the solutions and other necessary files (e.g. images, assets, helpers, etc.) into the project
|
|
8
|
+
to conclude chapter 07. This should make all tests pass and bring you in sync to the application at
|
|
9
|
+
the end of chapter 07.
|
|
10
|
+
|
|
11
|
+
If you already have a solution file, you'll be prompted whether you want to overwrite your file,
|
|
12
|
+
see the difference, or keep your file.
|
|
13
|
+
|
|
14
|
+
It's a good idea to commit your changes to git, prior to running finish, in case you accidentally choose to
|
|
15
|
+
overwrite files you wanted to keep. Assuming your project is already git-controlled, you can commit changes with:
|
|
16
|
+
|
|
17
|
+
git add .
|
|
18
|
+
git commit -m "comment here explaining WHY you made the changes"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Chapter07
|
|
2
|
+
module Generators
|
|
3
|
+
class SolutionsGenerator < Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
5
|
+
|
|
6
|
+
def copy_app_tree
|
|
7
|
+
directory(self.class.source_root, Rails.root)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def add_help_route
|
|
11
|
+
|
|
12
|
+
dest = File.join(Rails.root,'config','routes.rb')
|
|
13
|
+
insert_into_file(dest, :after => %r{/about.*:to.*pages#about.*$}) do
|
|
14
|
+
"\n match '/help', :to => 'pages#help'"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def remove_static_index_html_file
|
|
19
|
+
remove_file(File.join(Rails.root, 'public', 'index.html'))
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class User < ActiveRecord::Base
|
|
2
|
+
# Include default devise modules. Others available are:
|
|
3
|
+
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
|
|
4
|
+
devise :database_authenticatable, :registerable,
|
|
5
|
+
:recoverable, :rememberable, :trackable, :validatable
|
|
6
|
+
|
|
7
|
+
validates :name, :presence => true, :length => { :maximum => 50 }
|
|
8
|
+
|
|
9
|
+
# Setup accessible (or protected) attributes for your model
|
|
10
|
+
attr_accessible :name, :email, :password, :password_confirmation, :remember_me
|
|
11
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<footer>
|
|
2
|
+
<nav class="round">
|
|
3
|
+
<ul>
|
|
4
|
+
<li><%= link_to "About", about_path %></li>
|
|
5
|
+
<li><%= link_to "Contact", contact_path %></li>
|
|
6
|
+
<li><a href="http://news.railstutorial.org/">News</a></li>
|
|
7
|
+
<li><a href="http://www.railstutorial.org/">Rails Tutorial</a></li>
|
|
8
|
+
</ul>
|
|
9
|
+
</nav>
|
|
10
|
+
</footer>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<header>
|
|
2
|
+
<% logo = image_tag("logo.png", :alt => "Sample App", :class => "round") %>
|
|
3
|
+
<%= link_to logo, root_path %>
|
|
4
|
+
<nav class="round">
|
|
5
|
+
<ul>
|
|
6
|
+
<li><%= link_to "Home", root_path %></li>
|
|
7
|
+
<li><%= link_to "Help", help_path %></li>
|
|
8
|
+
<li><%= link_to "Sign in", '#' %></li>
|
|
9
|
+
</ul>
|
|
10
|
+
</nav>
|
|
11
|
+
</header>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<table class="profile" summary="Profile information">
|
|
2
|
+
<tr>
|
|
3
|
+
<td class="main">
|
|
4
|
+
<h1>
|
|
5
|
+
<%= gravatar_for @user %>
|
|
6
|
+
<%= @user.name %>
|
|
7
|
+
</h1>
|
|
8
|
+
</td>
|
|
9
|
+
<td class="sidebar round">
|
|
10
|
+
<strong>Name</strong> <%= @user.name %>
|
|
11
|
+
<br/>
|
|
12
|
+
<strong>URL</strong> <%= link_to user_path(@user.id), @user %>
|
|
13
|
+
</td>
|
|
14
|
+
</tr>
|
|
15
|
+
</table>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
Begins Test-First Teaching exercises adapted from Chapter 08 of the RailsTutorial by Michael Hartl.
|
|
3
|
+
|
|
4
|
+
It is assumed that this generator is run after the exercises for Chapter 07 have been completed, and the solutions are implemented.
|
|
5
|
+
|
|
6
|
+
Successive chapters are expected to be run sequentially. Each chapter's generators comes with a delta
|
|
7
|
+
to the next chapter, in two phase, the "begin" one will create tests, the "finish" one includes the solution files.
|
|
8
|
+
If all tests pass, the "finish" phase is optional.
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
rails generate chapter08:begin
|
|
12
|
+
|
|
13
|
+
This copies new tests into the project, which are failing.
|
|
14
|
+
The student's task is to write code to make the test pass. The material covered by the tests is consistent
|
|
15
|
+
with Chapter 08 of the RailsTutorial, however adapted for Devise as authentication solution.
|
|
16
|
+
|
|
17
|
+
When you're done, and all tests pass, or you just want to skip ahead, run:
|
|
18
|
+
|
|
19
|
+
rails generate chapter08:solutions
|
|
20
|
+
|
|
21
|
+
This will copy solutions files into the application tree. If you already have a solution file,
|
|
22
|
+
you'll be prompted whether you want to overwrite your file, see the difference, or keep your file.
|
|
23
|
+
|
|
24
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Chapter08_09
|
|
2
|
+
module Generators
|
|
3
|
+
class BeginGenerator < Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
5
|
+
|
|
6
|
+
def copy_app_tree
|
|
7
|
+
directory(self.class.source_root, Rails.root)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def insert_css
|
|
11
|
+
src = File.expand_path("../snippets/custom.css", __FILE__)
|
|
12
|
+
dest = File.join(Rails.root,'public','stylesheets','custom.css')
|
|
13
|
+
insert_into_file(dest, File.binread(src), :before => /\Z/) # insert before end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def generate_instructions
|
|
17
|
+
require 'rdiscount'
|
|
18
|
+
|
|
19
|
+
instr_md = File.expand_path('../instructions.md',self.class.source_root)
|
|
20
|
+
dest = File.join(Rails.root,'doc','chapter08.html')
|
|
21
|
+
copy_file(instr_md, dest, :force => true) do |content|
|
|
22
|
+
RDiscount.new(content).to_html
|
|
23
|
+
end
|
|
24
|
+
say_status('Note',"Now open file://#{dest} in your web browser for instructions", :cyan)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
RailsTutorial Chapter 08 Test-First Teaching Instructions
|
|
2
|
+
=========================================================
|
|
3
|
+
|
|
4
|
+
Sign up
|
|
5
|
+
-------
|
|
6
|
+
|
|
7
|
+
In the adapted version of RailsTutorial that we're using
|
|
8
|
+
here, the user registration and user authentication tasks
|
|
9
|
+
are not implemented in the application itself, but
|
|
10
|
+
instead handled by a gem called [Devise](devise) that is an
|
|
11
|
+
industry-standard Rails authentication solution.
|
|
12
|
+
|
|
13
|
+
Devise provides its own controllers, models and views that
|
|
14
|
+
are seamlessly loaded into the running appliction.
|
|
15
|
+
|
|
16
|
+
Devise's native views, however, do not quite conform to our needs.
|
|
17
|
+
Many tests pass out of the box, but the few that aren't give
|
|
18
|
+
important clues as to how we need to customize Devise's default
|
|
19
|
+
view templates.
|
|
20
|
+
|
|
21
|
+
Run the server:
|
|
22
|
+
|
|
23
|
+
rails server
|
|
24
|
+
|
|
25
|
+
and then browse to <http://localhost:3000/signup>. Try signing
|
|
26
|
+
up. What problem do you see? What is going wrong here?
|
|
27
|
+
|
|
28
|
+
This issue is replicated in the new test file for Chapter 08,
|
|
29
|
+
`specs/controllers/devise/registrations_controller_08_spec.rb`.
|
|
30
|
+
|
|
31
|
+
Notice how the test refers to `Devise::RegistrationsController`
|
|
32
|
+
which is the controller handling registration provided by
|
|
33
|
+
Devise in the gem.
|
|
34
|
+
|
|
35
|
+
Even though the controller sits in Devise, we can still run
|
|
36
|
+
our own test against it. This was done here.
|
|
37
|
+
|
|
38
|
+
Take a look at the [Devise instructions on github](devise)
|
|
39
|
+
to learn about how to customize views. That what we'll
|
|
40
|
+
need to do. Hint: You'll need to run a Devise generator.
|
|
41
|
+
|
|
42
|
+
Sign in
|
|
43
|
+
-------
|
|
44
|
+
|
|
45
|
+
Chapter 09 of RailsTutorial covers sign-in, but we cover it together with sign-up,
|
|
46
|
+
because Devise provides both in one fell swoop.
|
|
47
|
+
|
|
48
|
+
The Devise sign-in page meets our needs and doesn't need customizing.
|
|
49
|
+
|
|
50
|
+
However, we need to work on the layout to make sure that it shows a "Sign out" link
|
|
51
|
+
if a user is logged in, and a "Sign in" link only if a user is not logged in.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
[devise]: https://github.com/plataformatec/devise "Devise on github"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
/**********************/
|
|
3
|
+
/* Through Chapter 08 */
|
|
4
|
+
/**********************/
|
|
5
|
+
|
|
6
|
+
div.field, div.actions {
|
|
7
|
+
margin-bottom: 10px;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.field_with_errors {
|
|
11
|
+
margin-top: 10px;
|
|
12
|
+
padding: 2px;
|
|
13
|
+
background-color: red;
|
|
14
|
+
display: table;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.field_with_errors label {
|
|
18
|
+
color: #fff;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#error_explanation {
|
|
22
|
+
width: 400px;
|
|
23
|
+
border: 2px solid red;
|
|
24
|
+
padding: 7px;
|
|
25
|
+
padding-bottom: 12px;
|
|
26
|
+
margin-bottom: 20px;
|
|
27
|
+
background-color: #f0f0f0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#error_explanation h2 {
|
|
31
|
+
text-align: left;
|
|
32
|
+
font-weight: bold;
|
|
33
|
+
padding: 5px 5px 5px 15px;
|
|
34
|
+
font-size: 12px;
|
|
35
|
+
margin: -7px;
|
|
36
|
+
background-color: #c00;
|
|
37
|
+
color: #fff;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#error_explanation p {
|
|
41
|
+
color: #333;
|
|
42
|
+
margin-bottom: 0;
|
|
43
|
+
padding: 5px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
#error_explanation ul li {
|
|
47
|
+
font-size: 12px;
|
|
48
|
+
list-style: square;
|
|
49
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Devise::RegistrationsController do
|
|
4
|
+
render_views
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
# The following request parameter is necessary for testing, according to:
|
|
8
|
+
# https://github.com/plataformatec/devise/wiki/How-To:-Controllers-and-Views-tests-with-Rails-3-(and-rspec)
|
|
9
|
+
request.env["devise.mapping"] = Devise.mappings[:user]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "GET 'new'" do
|
|
13
|
+
|
|
14
|
+
it "should be successful" do
|
|
15
|
+
get :new
|
|
16
|
+
response.should be_success
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should have h1 tag with Sign up" do
|
|
20
|
+
get :new
|
|
21
|
+
response.should have_selector("h1", :content => "Sign up")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
%w(name email password password_confirmation).each do |attr|
|
|
25
|
+
it "should have a #{attr} field" do
|
|
26
|
+
get :new
|
|
27
|
+
response.should have_selector("input[name='user[#{attr}]']")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
describe "POST 'create'" do
|
|
34
|
+
|
|
35
|
+
describe "failure" do
|
|
36
|
+
|
|
37
|
+
before(:each) do
|
|
38
|
+
@attr = { :name => "", :email => "", :password => "",
|
|
39
|
+
:password_confirmation => "" }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should not create a user" do
|
|
43
|
+
expect {
|
|
44
|
+
post :create, :user => @attr
|
|
45
|
+
}.to_not change(User, :count)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should render the 'new' page" do
|
|
49
|
+
post :create, :user => @attr
|
|
50
|
+
response.should render_template('new')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should show errors" do
|
|
54
|
+
post :create, :user => @attr
|
|
55
|
+
response.should have_selector("div#error_explanation")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "success" do
|
|
60
|
+
|
|
61
|
+
before(:each) do
|
|
62
|
+
@attr = { :name => "New User", :email => "user@example.com",
|
|
63
|
+
:password => "foobar", :password_confirmation => "foobar" }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should create a user" do
|
|
67
|
+
expect {
|
|
68
|
+
post :create, :user => @attr
|
|
69
|
+
}.to change(User, :count).by(1)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "should redirect to the user show page" do
|
|
73
|
+
post :create, :user => @attr
|
|
74
|
+
response.should redirect_to(user_path(assigns(:user)))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should have a welcome message" do
|
|
78
|
+
post :create, :user => @attr
|
|
79
|
+
flash[:notice].should == "Welcome! You have signed up successfully."
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Layout links" do
|
|
4
|
+
|
|
5
|
+
describe "when not signed in" do
|
|
6
|
+
it "should have a signin link" do
|
|
7
|
+
visit root_path
|
|
8
|
+
response.should have_selector("a", :href => signin_path,
|
|
9
|
+
:content => "Sign in")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "when signed in" do
|
|
14
|
+
|
|
15
|
+
before(:each) do
|
|
16
|
+
@user = Factory(:user)
|
|
17
|
+
visit signin_path
|
|
18
|
+
fill_in :email, :with => @user.email
|
|
19
|
+
fill_in :password, :with => @user.password
|
|
20
|
+
click_button
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should have a signout link" do
|
|
24
|
+
visit root_path
|
|
25
|
+
response.should have_selector("a", :href => signout_path,
|
|
26
|
+
:content => "Sign out")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should have a profile link" do
|
|
30
|
+
visit root_path
|
|
31
|
+
response.should have_selector("a", :href => user_path(@user),
|
|
32
|
+
:content => "Profile")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Users" do
|
|
4
|
+
|
|
5
|
+
describe "signup" do
|
|
6
|
+
|
|
7
|
+
describe "success" do
|
|
8
|
+
|
|
9
|
+
it "should make a new user" do
|
|
10
|
+
lambda do
|
|
11
|
+
visit signup_path
|
|
12
|
+
fill_in "Name", :with => "Example User"
|
|
13
|
+
fill_in "Email", :with => "user@example.com"
|
|
14
|
+
fill_in "Password", :with => "foobar"
|
|
15
|
+
fill_in "Confirmation", :with => "foobar"
|
|
16
|
+
click_button
|
|
17
|
+
response.should render_template('users/show')
|
|
18
|
+
end.should change(User, :count).by(1)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should print a welcome message" do
|
|
22
|
+
visit signup_path
|
|
23
|
+
fill_in "Name", :with => "Example User"
|
|
24
|
+
fill_in "Email", :with => "user@example.com"
|
|
25
|
+
fill_in "Password", :with => "foobar"
|
|
26
|
+
fill_in "Confirmation", :with => "foobar"
|
|
27
|
+
click_button
|
|
28
|
+
response.should have_selector("div.flash.notice",
|
|
29
|
+
:content => "Welcome! You have signed up successfully.")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
Wraps up Test-First Teaching exercises adapted from Chapter 08 of the RailsTutorial by Michael Hartl.
|
|
3
|
+
|
|
4
|
+
Example:
|
|
5
|
+
rails generate chapter08:solutions
|
|
6
|
+
|
|
7
|
+
This copies the solutions and other necessary files (e.g. images, assets, helpers, etc.) into the project
|
|
8
|
+
to conclude chapter 08. This should make all tests pass and bring you in sync to the application at
|
|
9
|
+
the end of chapter 08.
|
|
10
|
+
|
|
11
|
+
If you already have a solution file, you'll be prompted whether you want to overwrite your file,
|
|
12
|
+
see the difference, or keep your file.
|
|
13
|
+
|
|
14
|
+
It's a good idea to commit your changes to git, prior to running finish, in case you accidentally choose to
|
|
15
|
+
overwrite files you wanted to keep. Assuming your project is already git-controlled, you can commit changes with:
|
|
16
|
+
|
|
17
|
+
git add .
|
|
18
|
+
git commit -m "comment here explaining WHY you made the changes"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module ApplicationHelper
|
|
2
|
+
|
|
3
|
+
def title
|
|
4
|
+
base_title = "Ruby on Rails Tutorial Sample App"
|
|
5
|
+
if @title.nil?
|
|
6
|
+
base_title
|
|
7
|
+
else
|
|
8
|
+
"#{base_title} | #{@title}"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def logo
|
|
13
|
+
image_tag("logo.png", :alt => "Sample App", :class => "round")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<h2>Change your password</h2>
|
|
2
|
+
|
|
3
|
+
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %>
|
|
4
|
+
<%= devise_error_messages! %>
|
|
5
|
+
<%= f.hidden_field :reset_password_token %>
|
|
6
|
+
|
|
7
|
+
<p><%= f.label :password, "New password" %><br />
|
|
8
|
+
<%= f.password_field :password %></p>
|
|
9
|
+
|
|
10
|
+
<p><%= f.label :password_confirmation, "Confirm new password" %><br />
|
|
11
|
+
<%= f.password_field :password_confirmation %></p>
|
|
12
|
+
|
|
13
|
+
<p><%= f.submit "Change my password" %></p>
|
|
14
|
+
<% end %>
|
|
15
|
+
|
|
16
|
+
<%= render :partial => "devise/shared/links" %>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<h2>Forgot your password?</h2>
|
|
2
|
+
|
|
3
|
+
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
|
|
4
|
+
<%= devise_error_messages! %>
|
|
5
|
+
|
|
6
|
+
<p><%= f.label :email %><br />
|
|
7
|
+
<%= f.email_field :email %></p>
|
|
8
|
+
|
|
9
|
+
<p><%= f.submit "Send me reset password instructions" %></p>
|
|
10
|
+
<% end %>
|
|
11
|
+
|
|
12
|
+
<%= render :partial => "devise/shared/links" %>
|
data/lib/generators/chapter08_09/solutions/templates/app/views/devise/registrations/_fields.html.erb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<div class="field">
|
|
2
|
+
<%= f.label :name %><br />
|
|
3
|
+
<%= f.text_field :name %>
|
|
4
|
+
</div>
|
|
5
|
+
<div class="field">
|
|
6
|
+
<%= f.label :email %><br />
|
|
7
|
+
<%= f.text_field :email %>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="field">
|
|
10
|
+
<%= f.label :password %><br />
|
|
11
|
+
<%= f.password_field :password %>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="field">
|
|
14
|
+
<%= f.label :password_confirmation, "Confirmation" %><br />
|
|
15
|
+
<%= f.password_field :password_confirmation %>
|
|
16
|
+
</div>
|
data/lib/generators/chapter08_09/solutions/templates/app/views/devise/registrations/edit.html.erb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<h1>Edit user</h1>
|
|
2
|
+
|
|
3
|
+
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
|
|
4
|
+
|
|
5
|
+
<%= devise_error_messages! %>
|
|
6
|
+
<%= render 'fields', :f => f %>
|
|
7
|
+
|
|
8
|
+
<div class="field">
|
|
9
|
+
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
|
|
10
|
+
<%= f.password_field :current_password %>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div class="actions">
|
|
14
|
+
<%= f.submit "Update" %>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<% end %>
|
|
18
|
+
|
|
19
|
+
<div>
|
|
20
|
+
<%= gravatar_for @user %>
|
|
21
|
+
<a href="http://gravatar.com/emails">change</a>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<h3>Cancel my account</h3>
|
|
25
|
+
|
|
26
|
+
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
|
|
27
|
+
|
|
28
|
+
<%= link_to "Back", :back %>
|
data/lib/generators/chapter08_09/solutions/templates/app/views/devise/registrations/new.html.erb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<h1>Sign up</h1>
|
|
2
|
+
|
|
3
|
+
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
|
|
4
|
+
|
|
5
|
+
<%= devise_error_messages! %>
|
|
6
|
+
<%= render 'fields', :f => f %>
|
|
7
|
+
<div class="actions">
|
|
8
|
+
<%= f.submit "Sign up" %>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<% end %>
|
|
12
|
+
|
|
13
|
+
<%= render :partial => "devise/shared/links" %>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<h2>Sign in</h2>
|
|
2
|
+
|
|
3
|
+
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
|
4
|
+
<p><%= f.label :email %><br />
|
|
5
|
+
<%= f.email_field :email %></p>
|
|
6
|
+
|
|
7
|
+
<p><%= f.label :password %><br />
|
|
8
|
+
<%= f.password_field :password %></p>
|
|
9
|
+
|
|
10
|
+
<% if devise_mapping.rememberable? -%>
|
|
11
|
+
<p><%= f.check_box :remember_me %> <%= f.label :remember_me %></p>
|
|
12
|
+
<% end -%>
|
|
13
|
+
|
|
14
|
+
<p><%= f.submit "Sign in" %></p>
|
|
15
|
+
<% end %>
|
|
16
|
+
|
|
17
|
+
<%= render :partial => "devise/shared/links" %>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<%- if controller_name != 'sessions' %>
|
|
2
|
+
<%= link_to "Sign in", new_session_path(resource_name) %><br />
|
|
3
|
+
<% end -%>
|
|
4
|
+
|
|
5
|
+
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
|
|
6
|
+
New User? <%= link_to "Sign up", new_registration_path(resource_name) %><br />
|
|
7
|
+
<% end -%>
|
|
8
|
+
|
|
9
|
+
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
|
|
10
|
+
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
|
|
11
|
+
<% end -%>
|
|
12
|
+
|
|
13
|
+
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
|
|
14
|
+
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
|
|
15
|
+
<% end -%>
|
|
16
|
+
|
|
17
|
+
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
|
|
18
|
+
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
|
|
19
|
+
<% end -%>
|
|
20
|
+
|
|
21
|
+
<%- if devise_mapping.omniauthable? %>
|
|
22
|
+
<%- resource_class.omniauth_providers.each do |provider| %>
|
|
23
|
+
<%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
|
|
24
|
+
<% end -%>
|
|
25
|
+
<% end -%>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<header>
|
|
2
|
+
<%= link_to logo, root_path %>
|
|
3
|
+
<nav class="round">
|
|
4
|
+
<ul>
|
|
5
|
+
<li><%= link_to "Home", root_path %></li>
|
|
6
|
+
<% if signed_in? %>
|
|
7
|
+
<li><%= link_to "Profile", user_path(current_user) %></li>
|
|
8
|
+
<li><%= link_to "Users", users_path %></li>
|
|
9
|
+
<li><%= link_to "Settings", edit_user_registration_path(current_user.id) %></li>
|
|
10
|
+
<% end %>
|
|
11
|
+
<li><%= link_to "Help", help_path %></li>
|
|
12
|
+
<% if signed_in? %>
|
|
13
|
+
<li><%= link_to "Sign out", signout_path %></li>
|
|
14
|
+
<% else %>
|
|
15
|
+
<li><%= link_to "Sign in", signin_path %></li>
|
|
16
|
+
<% end %>
|
|
17
|
+
</ul>
|
|
18
|
+
</nav>
|
|
19
|
+
</header>
|