tft_rails_dbc 0.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 +90 -0
- data/Rakefile +25 -0
- data/lib/generators/chapter07/begin/USAGE +27 -0
- data/lib/generators/chapter07/begin/begin_generator.rb +39 -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 +9 -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 +39 -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 +65 -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/generators/chapter10/begin/USAGE +24 -0
- data/lib/generators/chapter10/begin/begin_generator.rb +41 -0
- data/lib/generators/chapter10/begin/instructions.md +47 -0
- data/lib/generators/chapter10/begin/snippets/custom.css +12 -0
- data/lib/generators/chapter10/begin/snippets/factories.rb +10 -0
- data/lib/generators/chapter10/begin/templates/app/views/layouts/application.html.erb +21 -0
- data/lib/generators/chapter10/begin/templates/lib/tasks/sample_data.rake +24 -0
- data/lib/generators/chapter10/begin/templates/spec/controllers/users_controller_10_spec.rb +110 -0
- data/lib/generators/chapter10/begin/templates/spec/models/user_10_spec.rb +24 -0
- data/lib/generators/chapter10/solutions/USAGE +18 -0
- data/lib/generators/chapter10/solutions/snippets/migration_add_admin_to_users.rb +9 -0
- data/lib/generators/chapter10/solutions/solutions_generator.rb +32 -0
- data/lib/generators/chapter10/solutions/templates/app/controllers/users_controller.rb +28 -0
- data/lib/generators/chapter10/solutions/templates/app/views/users/_user.html.erb +8 -0
- data/lib/generators/chapter10/solutions/templates/app/views/users/index.html.erb +9 -0
- data/lib/generators/chapter11_1/begin/USAGE +24 -0
- data/lib/generators/chapter11_1/begin/begin_generator.rb +24 -0
- data/lib/generators/chapter11_1/begin/instructions.md +39 -0
- data/lib/generators/chapter11_1/begin/templates/lib/tasks/sample_data.rake +29 -0
- data/lib/generators/chapter11_1/begin/templates/spec/models/microposts_11_1_spec.rb +45 -0
- data/lib/generators/chapter11_1/begin/templates/spec/models/user_11_1_spec.rb +30 -0
- data/lib/generators/chapter11_1/solutions/USAGE +18 -0
- data/lib/generators/chapter11_1/solutions/snippets/migration_create_microposts.rb +17 -0
- data/lib/generators/chapter11_1/solutions/solutions_generator.rb +25 -0
- data/lib/generators/chapter11_1/solutions/templates/app/models/micropost.rb +10 -0
- data/lib/generators/chapter11_1/solutions/templates/app/models/user.rb +14 -0
- data/lib/generators/chapter11_1/solutions/templates/spec/factories.rb +16 -0
- data/lib/generators/chapter11_2/begin/USAGE +24 -0
- data/lib/generators/chapter11_2/begin/begin_generator.rb +30 -0
- data/lib/generators/chapter11_2/begin/instructions.md +35 -0
- data/lib/generators/chapter11_2/begin/snippets/custom.css +59 -0
- data/lib/generators/chapter11_2/begin/templates/app/views/users/show.html.erb +23 -0
- data/lib/generators/chapter11_2/begin/templates/spec/controllers/users_controller_11_2_spec.rb +31 -0
- data/lib/generators/chapter11_2/solutions/USAGE +18 -0
- data/lib/generators/chapter11_2/solutions/solutions_generator.rb +12 -0
- data/lib/generators/chapter11_2/solutions/templates/app/controllers/users_controller.rb +29 -0
- data/lib/generators/chapter11_2/solutions/templates/app/views/microposts/_micropost.html.erb +8 -0
- data/lib/generators/chapter11_2/solutions/templates/app/views/users/show.html.erb +23 -0
- data/lib/generators/chapter11_3/begin/USAGE +24 -0
- data/lib/generators/chapter11_3/begin/begin_generator.rb +24 -0
- data/lib/generators/chapter11_3/begin/instructions.md +80 -0
- data/lib/generators/chapter11_3/begin/templates/app/views/pages/home.html.erb +24 -0
- data/lib/generators/chapter11_3/begin/templates/app/views/shared/_feed.html.erb +6 -0
- data/lib/generators/chapter11_3/begin/templates/app/views/shared/_feed_item.html.erb +14 -0
- data/lib/generators/chapter11_3/begin/templates/app/views/shared/_micropost_form.html.erb +9 -0
- data/lib/generators/chapter11_3/begin/templates/app/views/shared/_user_info.html.erb +11 -0
- data/lib/generators/chapter11_3/begin/templates/spec/controllers/microposts_controllers_11_3_spec.rb +103 -0
- data/lib/generators/chapter11_3/begin/templates/spec/controllers/pages_controller_11_3_spec.rb +14 -0
- data/lib/generators/chapter11_3/begin/templates/spec/models/user_11_3_spec.rb +31 -0
- data/lib/generators/chapter11_3/begin/templates/spec/requests/micropost_11_3_spec.rb +41 -0
- data/lib/generators/chapter11_3/solutions/USAGE +18 -0
- data/lib/generators/chapter11_3/solutions/solutions_generator.rb +30 -0
- data/lib/generators/chapter11_3/solutions/templates/app/controllers/microposts_controller.rb +20 -0
- data/lib/generators/chapter11_3/solutions/templates/app/controllers/pages_controller.rb +22 -0
- data/lib/generators/chapter11_3/solutions/templates/app/views/microposts/_micropost.html.erb +15 -0
- data/lib/generators/chapter11_3/solutions/templates/app/views/pages/home.html.erb +24 -0
- data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_error_messages.html.erb +13 -0
- data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_feed.html.erb +6 -0
- data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_feed_item.html.erb +21 -0
- data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_micropost_form.html.erb +9 -0
- data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_user_info.html.erb +11 -0
- data/lib/tft_rails.rb +2 -0
- metadata +217 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
/************************/
|
3
|
+
/* Through Chapter 11.2 */
|
4
|
+
/************************/
|
5
|
+
|
6
|
+
h1.micropost {
|
7
|
+
margin-bottom: 0.3em;
|
8
|
+
}
|
9
|
+
|
10
|
+
table.microposts {
|
11
|
+
margin-top: 1em;
|
12
|
+
}
|
13
|
+
|
14
|
+
table.microposts tr {
|
15
|
+
height: 70px;
|
16
|
+
}
|
17
|
+
|
18
|
+
table.microposts tr td.gravatar {
|
19
|
+
border-top: 1px solid #ccc;
|
20
|
+
vertical-align: top;
|
21
|
+
width: 50px;
|
22
|
+
}
|
23
|
+
|
24
|
+
table.microposts tr td.micropost {
|
25
|
+
border-top: 1px solid #ccc;
|
26
|
+
vertical-align: top;
|
27
|
+
padding-top: 10px;
|
28
|
+
}
|
29
|
+
|
30
|
+
table.microposts tr td.micropost span.timestamp {
|
31
|
+
display: block;
|
32
|
+
font-size: 85%;
|
33
|
+
color: #666;
|
34
|
+
}
|
35
|
+
|
36
|
+
div.user_info img {
|
37
|
+
padding-right: 0.1em;
|
38
|
+
}
|
39
|
+
|
40
|
+
div.user_info a {
|
41
|
+
text-decoration: none;
|
42
|
+
}
|
43
|
+
|
44
|
+
div.user_info span.user_name {
|
45
|
+
position: absolute;
|
46
|
+
}
|
47
|
+
|
48
|
+
div.user_info span.microposts {
|
49
|
+
font-size: 80%;
|
50
|
+
}
|
51
|
+
|
52
|
+
form.new_micropost {
|
53
|
+
margin-bottom: 2em;
|
54
|
+
}
|
55
|
+
|
56
|
+
form.new_micropost textarea {
|
57
|
+
height: 4em;
|
58
|
+
margin-bottom: 0;
|
59
|
+
}
|
@@ -0,0 +1,23 @@
|
|
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
|
+
<%# only if microposts exist, should the content below be rendered %>
|
9
|
+
<table class="microposts" summary="User microposts">
|
10
|
+
(The list of microposts should show up here, if there are any.)
|
11
|
+
</table>
|
12
|
+
<!--<%#= (pagination here, optional) %>-->
|
13
|
+
<%# end %>
|
14
|
+
</td>
|
15
|
+
<td class="sidebar round">
|
16
|
+
<strong>Name</strong> <%= @user.name %>
|
17
|
+
<br/>
|
18
|
+
<strong>URL</strong> <%= link_to user_path(@user.id), @user %>
|
19
|
+
<br/>
|
20
|
+
<strong>Microposts</strong> (The total count of Microposts should be here.)
|
21
|
+
</td>
|
22
|
+
</tr>
|
23
|
+
</table>
|
data/lib/generators/chapter11_2/begin/templates/spec/controllers/users_controller_11_2_spec.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UsersController do
|
4
|
+
|
5
|
+
describe "GET 'show'" do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@user = Factory(:user)
|
9
|
+
@mp1 = Factory(:micropost, :user => @user, :content => "Foo bar", :created_at => 1.day.ago)
|
10
|
+
@mp2 = Factory(:micropost, :user => @user, :content => "Baz quux",:created_at => 2.days.ago)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should populate the @microposts instance variable' do
|
14
|
+
get :show, :id => @user.id
|
15
|
+
# Note: in a controller test, we can access instance variables
|
16
|
+
# of the controller by using the assigns[] function
|
17
|
+
assigns[:microposts].should == [@mp1,@mp2]
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "HTML output" do
|
21
|
+
render_views
|
22
|
+
|
23
|
+
it "should show the user's microposts" do
|
24
|
+
get :show, :id => @user.id
|
25
|
+
response.should have_selector("span.content", :content => @mp1.content)
|
26
|
+
response.should have_selector("span.content", :content => @mp2.content)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Description:
|
2
|
+
Wraps up Test-First Teaching exercises adapted from Chapter 11.2 of the RailsTutorial by Michael Hartl.
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate chapter11:solutions
|
6
|
+
|
7
|
+
This copies the solutions and other necessary files (e.g. images, assets, helpers, etc.) into the project
|
8
|
+
to conclude Chapter 11.2. This should make all tests pass and bring you in sync to the application at
|
9
|
+
the end of Chapter 11.2.
|
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,29 @@
|
|
1
|
+
class UsersController < ApplicationController
|
2
|
+
|
3
|
+
before_filter :authenticate_user!, :only => [:index, :destroy]
|
4
|
+
before_filter :admin_user, :only => :destroy
|
5
|
+
|
6
|
+
def show
|
7
|
+
@user = User.find(params[:id])
|
8
|
+
@microposts = @user.microposts.paginate(:page => params[:page])
|
9
|
+
@title = @user.name
|
10
|
+
end
|
11
|
+
|
12
|
+
def index
|
13
|
+
@title = "All users"
|
14
|
+
@users = User.paginate(:page => params[:page])
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroy
|
18
|
+
User.find(params[:id]).destroy
|
19
|
+
flash[:notice] = "User destroyed."
|
20
|
+
redirect_to users_path
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def admin_user
|
26
|
+
redirect_to(root_path) unless current_user.admin?
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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
|
+
<% unless @user.microposts.empty? %>
|
9
|
+
<table class="microposts" summary="User microposts">
|
10
|
+
<%= render @microposts %>
|
11
|
+
</table>
|
12
|
+
<%= will_paginate @microposts %>
|
13
|
+
<% end %>
|
14
|
+
</td>
|
15
|
+
<td class="sidebar round">
|
16
|
+
<strong>Name</strong> <%= @user.name %>
|
17
|
+
<br/>
|
18
|
+
<strong>URL</strong> <%= link_to user_path(@user.id), @user %>
|
19
|
+
<br/>
|
20
|
+
<strong>Microposts</strong> <%= @user.microposts.count %>
|
21
|
+
</td>
|
22
|
+
</tr>
|
23
|
+
</table>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Description:
|
2
|
+
Begins Test-First Teaching exercises adapted from Chapter 11 of the RailsTutorial by Michael Hartl.
|
3
|
+
|
4
|
+
It is assumed that this generator is run after the exercises for Chapter 10 and all prior ones 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 chapter11: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 11 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 chapter10: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,24 @@
|
|
1
|
+
module Chapter11_3
|
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 generate_instructions
|
11
|
+
require 'rdiscount'
|
12
|
+
|
13
|
+
instr_md = File.expand_path('../instructions.md',self.class.source_root)
|
14
|
+
return unless File.exists?(instr_md)
|
15
|
+
dest = File.join(Rails.root,'doc','chapter11_3.html')
|
16
|
+
copy_file(instr_md, dest, :force => true) do |content|
|
17
|
+
RDiscount.new(content).to_html
|
18
|
+
end
|
19
|
+
say_status('Note',"Now open file://#{dest} in your web browser for instructions", :cyan)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
RailsTutorial Chapter 11.3 Test-First Teaching Instructions
|
2
|
+
===========================================================
|
3
|
+
|
4
|
+
Controller
|
5
|
+
----------
|
6
|
+
|
7
|
+
In this sub-chapter we're adding controllers and views to create and delete
|
8
|
+
microposts.
|
9
|
+
|
10
|
+
When you first run `rake spec`, you'll get an error like below and no specs will execute.
|
11
|
+
|
12
|
+
uninitialized constant MicropostsController (NameError)
|
13
|
+
|
14
|
+
This is because we don't have this class defined yet. So, go ahead and create it using the rails generators:
|
15
|
+
|
16
|
+
_Note_: **Microposts is in plural here** (Rails convention for controllers).
|
17
|
+
|
18
|
+
rails g controller Microposts --controller-specs=false --view-specs=false --helper-specs=false
|
19
|
+
|
20
|
+
Note: The controller generatore (unlike the model generator), we can instruct to suppress
|
21
|
+
the spec files.
|
22
|
+
|
23
|
+
Routing
|
24
|
+
-------
|
25
|
+
|
26
|
+
The next error will have to do with routing. Add a resource route for microposts.
|
27
|
+
Consider which actions are needed, by checking what tests case exist and
|
28
|
+
by carefully reading the test failure messages.
|
29
|
+
Then use the `:only => [...]` option to restrict the routes generated.
|
30
|
+
|
31
|
+
Views
|
32
|
+
-----
|
33
|
+
|
34
|
+
The tests will fail then complaining of missing view templates. Before you
|
35
|
+
go on to create micropost view templates, view the design mock-up
|
36
|
+
in Rails Tutorial [Chapter 11.3.2][chapter_11_3_2]. What view template
|
37
|
+
should hold the form fields to entering a micropost? If not a micropost
|
38
|
+
view, how can we tell the controller to render another view?
|
39
|
+
|
40
|
+
For a reference on the view templates, check [Listing 11.27][listing_11_27],
|
41
|
+
[Listing 11.28][listing_11_28] and [Listing 11.29][listing_11_29]
|
42
|
+
|
43
|
+
Controller Actions
|
44
|
+
------------------
|
45
|
+
|
46
|
+
Next you'll need to implement the controller actions. For `create` there
|
47
|
+
are two branches, one for when saving the new record succeeds, i.e.
|
48
|
+
when validations pass, and one for when it fails.
|
49
|
+
|
50
|
+
Also, review the test cases carefully and consider if any of the actions
|
51
|
+
are supposed to be access controlled. Some test failures may look a bit
|
52
|
+
obscure when access control is not implemented.
|
53
|
+
|
54
|
+
The `destroy` action needs to make sure that only the use who created
|
55
|
+
the post can also delete it. Consider using the association methods
|
56
|
+
to constrain the seach for microposts to the currently signed-in user.
|
57
|
+
|
58
|
+
Display
|
59
|
+
-------
|
60
|
+
|
61
|
+
Take a moment to think about how you could show the user's posts
|
62
|
+
on the home page. There is no test for this, take a stab at it with
|
63
|
+
the tools and knowledge you now have.
|
64
|
+
|
65
|
+
Rails Concepts Covered
|
66
|
+
======================
|
67
|
+
|
68
|
+
* Using controller generator
|
69
|
+
* Resource routes
|
70
|
+
* Controller render method
|
71
|
+
* Difference render & redirect, also redirect_to :back
|
72
|
+
* Access control
|
73
|
+
* Accessing records through an association (Association Proxy Methods)
|
74
|
+
* Controller create/update action pattern: success/failure branches
|
75
|
+
* find_by_id vs. find
|
76
|
+
|
77
|
+
[chapter_11_3_2]: http://ruby.railstutorial.org/chapters/user-microposts#sec:creating_microposts "Chapter 11.3.2"
|
78
|
+
[listing_11_27]: http://ruby.railstutorial.org/chapters/user-microposts#code:microposts_home_page "Listing 11.27"
|
79
|
+
[listing_11_28]: http://ruby.railstutorial.org/chapters/user-microposts#code:micropost_form "Listing 11.28"
|
80
|
+
[listing_11_29]: http://ruby.railstutorial.org/chapters/user-microposts#code:user_info "Listing 11.29"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<% if signed_in? %>
|
2
|
+
<table class="front" summary="For signed-in users">
|
3
|
+
<tr>
|
4
|
+
<td class="main">
|
5
|
+
<h1 class="micropost">What's up?</h1>
|
6
|
+
<%#= micropost form %>
|
7
|
+
<%#= feed of microposts %>
|
8
|
+
</td>
|
9
|
+
<td class="sidebar round">
|
10
|
+
<%#= sidebar with user info (name, image link) %>
|
11
|
+
</td>
|
12
|
+
</tr>
|
13
|
+
</table>
|
14
|
+
<% else %>
|
15
|
+
<h1>Sample App</h1>
|
16
|
+
|
17
|
+
<p>
|
18
|
+
This is the home page for the
|
19
|
+
<a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
|
20
|
+
sample application.
|
21
|
+
</p>
|
22
|
+
|
23
|
+
<%= link_to "Sign up now!", signup_path, :class => "signup_button round" %>
|
24
|
+
<% end %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<tr>
|
2
|
+
<td class="gravatar">
|
3
|
+
<%# image %>
|
4
|
+
</td>
|
5
|
+
<td class="micropost">
|
6
|
+
<span class="user">
|
7
|
+
<%#= link to user %>
|
8
|
+
</span>
|
9
|
+
<span class="content"><%#= content of feed entry (i.e. a micropost) %></span>
|
10
|
+
<span class="timestamp">
|
11
|
+
Posted <%#= posting time of micropost %> ago.
|
12
|
+
</span>
|
13
|
+
</td>
|
14
|
+
</tr>
|
data/lib/generators/chapter11_3/begin/templates/spec/controllers/microposts_controllers_11_3_spec.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MicropostsController do
|
4
|
+
render_views
|
5
|
+
|
6
|
+
describe "access control" do
|
7
|
+
|
8
|
+
it "should deny access to 'create'" do
|
9
|
+
post :create
|
10
|
+
response.should redirect_to(new_user_session_path)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should deny access to 'destroy'" do
|
14
|
+
delete :destroy, :id => 1
|
15
|
+
response.should redirect_to(new_user_session_path)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "POST 'create'" do
|
20
|
+
|
21
|
+
before(:each) do
|
22
|
+
@user = Factory(:user)
|
23
|
+
sign_in(@user)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "failure" do
|
27
|
+
|
28
|
+
before(:each) do
|
29
|
+
@attr = { :content => "" }
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not create a micropost" do
|
33
|
+
lambda do
|
34
|
+
post :create, :micropost => @attr
|
35
|
+
end.should_not change(Micropost, :count)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should render the home page" do
|
39
|
+
post :create, :micropost => @attr
|
40
|
+
response.should render_template('pages/home')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "success" do
|
45
|
+
|
46
|
+
before(:each) do
|
47
|
+
@attr = { :content => "Lorem ipsum" }
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should create a micropost" do
|
51
|
+
lambda do
|
52
|
+
post :create, :micropost => @attr
|
53
|
+
end.should change(Micropost, :count).by(1)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should redirect to the home page" do
|
57
|
+
post :create, :micropost => @attr
|
58
|
+
response.should redirect_to(root_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should have a flash message" do
|
62
|
+
post :create, :micropost => @attr
|
63
|
+
flash[:success].should =~ /micropost created/i
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "DELETE 'destroy'" do
|
69
|
+
|
70
|
+
describe "for an unauthorized user" do
|
71
|
+
|
72
|
+
before(:each) do
|
73
|
+
@user = Factory(:user)
|
74
|
+
wrong_user = Factory(:user, :email => Factory.next(:email))
|
75
|
+
sign_in(wrong_user)
|
76
|
+
@micropost = Factory(:micropost, :user => @user)
|
77
|
+
request.env["HTTP_REFERER"] = root_path
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should deny access" do
|
81
|
+
delete :destroy, :id => @micropost
|
82
|
+
response.should redirect_to(root_path)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "for an authorized user" do
|
87
|
+
|
88
|
+
before(:each) do
|
89
|
+
@user = Factory(:user)
|
90
|
+
sign_in(@user)
|
91
|
+
@micropost = Factory(:micropost, :user => @user)
|
92
|
+
request.env["HTTP_REFERER"] = user_path(@user) # for redirect_to :back
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should destroy the micropost" do
|
96
|
+
lambda do
|
97
|
+
delete :destroy, :id => @micropost
|
98
|
+
end.should change(Micropost, :count).by(-1)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe User do
|
4
|
+
|
5
|
+
describe "micropost associations" do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@user = Factory(:user)
|
9
|
+
@mp1 = Factory(:micropost, :user => @user, :created_at => 1.day.ago)
|
10
|
+
@mp2 = Factory(:micropost, :user => @user, :created_at => 1.hour.ago)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "status feed" do
|
14
|
+
|
15
|
+
it "should have a feed" do
|
16
|
+
@user.should respond_to(:feed)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should include the user's microposts" do
|
20
|
+
@user.feed.include?(@mp1).should be_true
|
21
|
+
@user.feed.include?(@mp2).should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not include a different user's microposts" do
|
25
|
+
mp3 = Factory(:micropost,
|
26
|
+
:user => Factory(:user, :email => Factory.next(:email)))
|
27
|
+
@user.feed.include?(mp3).should be_false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Microposts" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
user = Factory(:user)
|
7
|
+
visit signin_path
|
8
|
+
fill_in :email, :with => user.email
|
9
|
+
fill_in :password, :with => user.password
|
10
|
+
click_button
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "creation" do
|
14
|
+
|
15
|
+
describe "failure" do
|
16
|
+
|
17
|
+
it "should not make a new micropost" do
|
18
|
+
lambda do
|
19
|
+
visit root_path
|
20
|
+
fill_in :micropost_content, :with => ""
|
21
|
+
click_button
|
22
|
+
response.should render_template('pages/home')
|
23
|
+
response.should have_selector("div#error_explanation")
|
24
|
+
end.should_not change(Micropost, :count)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "success" do
|
29
|
+
|
30
|
+
it "should make a new micropost" do
|
31
|
+
content = "Lorem ipsum dolor sit amet"
|
32
|
+
lambda do
|
33
|
+
visit root_path
|
34
|
+
fill_in :micropost_content, :with => content
|
35
|
+
click_button
|
36
|
+
response.should have_selector("span.content", :content => content)
|
37
|
+
end.should change(Micropost, :count).by(1)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Description:
|
2
|
+
Wraps up Test-First Teaching exercises adapted from Chapter 10 of the RailsTutorial by Michael Hartl.
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate chapter11:solutions
|
6
|
+
|
7
|
+
This copies the solutions and other necessary files (e.g. images, assets, helpers, etc.) into the project
|
8
|
+
to conclude Chapter 11. This should make all tests pass and bring you in sync to the application at
|
9
|
+
the end of Chapter 11.
|
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,30 @@
|
|
1
|
+
module Chapter11_3
|
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_microposts_resource
|
11
|
+
dest = File.join(Rails.root,'config','routes.rb')
|
12
|
+
insert_into_file(dest, :after => %r{resources\s+:users.*$}) do
|
13
|
+
"\n resources :microposts, :only => [:create, :destroy]"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_feed_method_to_user
|
18
|
+
dest = File.join(Rails.root, 'app', 'models', 'user.rb')
|
19
|
+
insert_into_file(dest, :before => /end\s*\Z/) do # insert before end
|
20
|
+
<<-CODE.gsub(/^\s+\|/,' ')
|
21
|
+
|def feed
|
22
|
+
| microposts
|
23
|
+
|end
|
24
|
+
CODE
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class MicropostsController < ApplicationController
|
2
|
+
before_filter :authenticate_user!
|
3
|
+
|
4
|
+
def create
|
5
|
+
@micropost = current_user.microposts.build(params[:micropost])
|
6
|
+
if @micropost.save
|
7
|
+
flash[:success] = "Micropost created!"
|
8
|
+
redirect_to root_path
|
9
|
+
else
|
10
|
+
render 'pages/home'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def destroy
|
15
|
+
# .try will call the method given, unless the caller is nil
|
16
|
+
current_user.microposts.find_by_id(params[:id]).try(:destroy)
|
17
|
+
redirect_to :back
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|