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,137 @@
|
|
1
|
+
.container {
|
2
|
+
width: 710px;
|
3
|
+
}
|
4
|
+
|
5
|
+
body {
|
6
|
+
background: #cff;
|
7
|
+
}
|
8
|
+
|
9
|
+
header {
|
10
|
+
padding-top: 20px;
|
11
|
+
}
|
12
|
+
|
13
|
+
header img {
|
14
|
+
padding: 1em;
|
15
|
+
background: #fff;
|
16
|
+
}
|
17
|
+
|
18
|
+
section {
|
19
|
+
margin-top: 1em;
|
20
|
+
font-size: 120%;
|
21
|
+
padding: 20px;
|
22
|
+
background: #fff;
|
23
|
+
}
|
24
|
+
|
25
|
+
section h1 {
|
26
|
+
font-size: 200%;
|
27
|
+
}
|
28
|
+
|
29
|
+
/* Links */
|
30
|
+
|
31
|
+
a {
|
32
|
+
color: #09c;
|
33
|
+
text-decoration: none;
|
34
|
+
}
|
35
|
+
|
36
|
+
a:hover {
|
37
|
+
color: #069;
|
38
|
+
text-decoration: underline;
|
39
|
+
}
|
40
|
+
|
41
|
+
a:visited {
|
42
|
+
color: #069;
|
43
|
+
}
|
44
|
+
|
45
|
+
/* Navigation */
|
46
|
+
|
47
|
+
nav {
|
48
|
+
float: right;
|
49
|
+
}
|
50
|
+
|
51
|
+
nav {
|
52
|
+
background-color: white;
|
53
|
+
padding: 0 0.7em;
|
54
|
+
white-space: nowrap;
|
55
|
+
}
|
56
|
+
|
57
|
+
nav ul {
|
58
|
+
margin: 0;
|
59
|
+
padding: 0;
|
60
|
+
}
|
61
|
+
|
62
|
+
nav ul li {
|
63
|
+
list-style-type: none;
|
64
|
+
display: inline-block;
|
65
|
+
padding: 0.2em 0;
|
66
|
+
}
|
67
|
+
|
68
|
+
nav ul li a {
|
69
|
+
padding: 0 5px;
|
70
|
+
font-weight: bold;
|
71
|
+
}
|
72
|
+
|
73
|
+
nav ul li a:visited {
|
74
|
+
color: #09c;
|
75
|
+
}
|
76
|
+
|
77
|
+
nav ul li a:hover {
|
78
|
+
text-decoration: underline;
|
79
|
+
}
|
80
|
+
|
81
|
+
/* Sign up button */
|
82
|
+
|
83
|
+
a.signup_button {
|
84
|
+
margin-left: auto;
|
85
|
+
margin-right: auto;
|
86
|
+
display: block;
|
87
|
+
text-align: center;
|
88
|
+
width: 190px;
|
89
|
+
color: #fff;
|
90
|
+
background: #006400;
|
91
|
+
font-size: 150%;
|
92
|
+
font-weight: bold;
|
93
|
+
padding: 20px;
|
94
|
+
}
|
95
|
+
|
96
|
+
/* Round corners */
|
97
|
+
|
98
|
+
.round {
|
99
|
+
-moz-border-radius: 10px;
|
100
|
+
-webkit-border-radius: 10px;
|
101
|
+
border-radius: 10px;
|
102
|
+
}
|
103
|
+
|
104
|
+
footer {
|
105
|
+
text-align: center;
|
106
|
+
margin-top: 10px;
|
107
|
+
width: 710px;
|
108
|
+
margin-left: auto;
|
109
|
+
margin-right: auto;
|
110
|
+
}
|
111
|
+
|
112
|
+
footer nav {
|
113
|
+
float: none;
|
114
|
+
}
|
115
|
+
|
116
|
+
/* User show page */
|
117
|
+
table.profile {
|
118
|
+
width: 100%;
|
119
|
+
margin-bottom: 0;
|
120
|
+
}
|
121
|
+
|
122
|
+
td.main {
|
123
|
+
width: 70%;
|
124
|
+
padding: 1em;
|
125
|
+
}
|
126
|
+
|
127
|
+
td.sidebar {
|
128
|
+
width: 30%;
|
129
|
+
padding: 1em;
|
130
|
+
vertical-align: top;
|
131
|
+
background: #ffc;
|
132
|
+
}
|
133
|
+
|
134
|
+
.profile img.gravatar {
|
135
|
+
border: 1px solid #999;
|
136
|
+
margin-bottom: -15px;
|
137
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PagesController do
|
4
|
+
render_views
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@base_title = 'Ruby on Rails Tutorial Sample App'
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "GET 'home'" do
|
11
|
+
it "should be successful" do
|
12
|
+
get 'home'
|
13
|
+
response.should be_success
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have the right title" do
|
17
|
+
get 'home'
|
18
|
+
response.should have_selector("title",
|
19
|
+
:content => @base_title + " | Home")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "GET 'contact'" do
|
24
|
+
it "should be successful" do
|
25
|
+
get 'contact'
|
26
|
+
response.should be_success
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should have the right title" do
|
30
|
+
get 'contact'
|
31
|
+
response.should have_selector("title",
|
32
|
+
:content => @base_title + " | Contact")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "GET 'about'" do
|
37
|
+
it "should be successful" do
|
38
|
+
get 'about'
|
39
|
+
response.should be_success
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should have the right title" do
|
43
|
+
get 'about'
|
44
|
+
response.should have_selector("title",
|
45
|
+
:content => @base_title + " | About")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UsersController do
|
4
|
+
render_views
|
5
|
+
|
6
|
+
describe "GET 'show'" do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@user = Factory(:user)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be successful" do
|
13
|
+
get :show, :id => @user
|
14
|
+
response.should be_success
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should find the right user" do
|
18
|
+
get :show, :id => @user
|
19
|
+
assigns(:user).should == @user
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have the right title" do
|
23
|
+
get :show, :id => @user
|
24
|
+
response.should have_selector("title", :content => @user.name)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should include the user's name" do
|
28
|
+
get :show, :id => @user
|
29
|
+
response.should have_selector("h1", :content => @user.name)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have a profile image" do
|
33
|
+
get :show, :id => @user
|
34
|
+
response.should have_selector("h1>img", :class => "gravatar")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe User do
|
4
|
+
|
5
|
+
it "has a name method" do
|
6
|
+
# Note: Ruby has a way to ask a class if it has a certain method defined,
|
7
|
+
# like User.respond_to?(:name) returns true or false depending on whether the
|
8
|
+
# class has a method called "name" defined on it
|
9
|
+
# RSpec's way of asserting this is with "should respond_to(:method_name)"
|
10
|
+
|
11
|
+
# Question: How does ActiveRecord know there is a name method? There is no such
|
12
|
+
# method explicitly defined in the class (user.rb)
|
13
|
+
User.should respond_to(:name)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "can set and read back name" do
|
17
|
+
u = User.new
|
18
|
+
u.name = 'Joe Smith'
|
19
|
+
u.name.should == 'Joe Smith'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "requires a name" do
|
23
|
+
no_name_user = User.new # Note: no attributes set at all, i.e. name is nil
|
24
|
+
# Note: the errors array on a model object is populated when valid? is called
|
25
|
+
# RSpec's be_valid is a fancy way of saying valid?.should == true
|
26
|
+
# This will call valid, and populate the error array, so we can check
|
27
|
+
# what failure occurred
|
28
|
+
no_name_user.should_not be_valid
|
29
|
+
no_name_user.errors[:name].should == ["can't be blank"]
|
30
|
+
end
|
31
|
+
|
32
|
+
it "rejects names that are too long" do
|
33
|
+
long_name_user = User.new(:name => 'a' * 51)
|
34
|
+
long_name_user.should_not be_valid
|
35
|
+
long_name_user.errors[:name].should == ["is too long (maximum is 50 characters)"]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "LayoutLinks" do
|
4
|
+
|
5
|
+
it "should have a Home page at '/'" do
|
6
|
+
get '/'
|
7
|
+
response.should have_selector('title', :content => "Home")
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should have a Contact page at '/contact'" do
|
11
|
+
get '/contact'
|
12
|
+
response.should have_selector('title', :content => "Contact")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have an About page at '/about'" do
|
16
|
+
get '/about'
|
17
|
+
response.should have_selector('title', :content => "About")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have a Help page at '/help'" do
|
21
|
+
get '/help'
|
22
|
+
response.should have_selector('title', :content => "Help")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have a signup page at '/signup'" do
|
26
|
+
get '/signup'
|
27
|
+
response.should be_success
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should have the right links on the layout" do
|
31
|
+
visit root_path
|
32
|
+
click_link "About"
|
33
|
+
response.should have_selector('title', :content => "About")
|
34
|
+
click_link "Help"
|
35
|
+
response.should have_selector('title', :content => "Help")
|
36
|
+
click_link "Contact"
|
37
|
+
response.should have_selector('title', :content => "Contact")
|
38
|
+
click_link "Home"
|
39
|
+
response.should have_selector('title', :content => "Home")
|
40
|
+
click_link "Sign up now!"
|
41
|
+
response.should be_success
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
2
|
+
ENV["RAILS_ENV"] ||= 'test'
|
3
|
+
require File.expand_path("../../config/environment", __FILE__)
|
4
|
+
require 'rspec/rails'
|
5
|
+
|
6
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
7
|
+
# in spec/support/ and its subdirectories.
|
8
|
+
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
|
9
|
+
|
10
|
+
Webrat.configure do |config|
|
11
|
+
config.mode = :rack
|
12
|
+
end
|
13
|
+
|
14
|
+
module Webrat::Logging
|
15
|
+
def logger
|
16
|
+
Rails.logger # log to test.log, rather than webrat.log
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
# == Mock Framework
|
22
|
+
#
|
23
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
24
|
+
#
|
25
|
+
# config.mock_with :mocha
|
26
|
+
# config.mock_with :flexmock
|
27
|
+
# config.mock_with :rr
|
28
|
+
config.mock_with :rspec
|
29
|
+
|
30
|
+
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
31
|
+
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
32
|
+
|
33
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
34
|
+
# examples within a transaction, remove the following line or assign false
|
35
|
+
# instead of true.
|
36
|
+
config.use_transactional_fixtures = true
|
37
|
+
|
38
|
+
config.include Devise::TestHelpers, :type => :controller
|
39
|
+
end
|
@@ -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 Chapters 08, 09 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_09: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 Chapters 08, 09 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_09: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_09.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,65 @@
|
|
1
|
+
RailsTutorial Chapters 08, 09 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
|
+
[Devise][devise] offers the controller methods `signed_in?` and `current_user`
|
54
|
+
to report on the current login status. The first method returns `true` or `false`
|
55
|
+
depending on whether a user logged in, the second returns the actual user object,
|
56
|
+
or `nil` if no user is logged in.
|
57
|
+
|
58
|
+
(Note that Devise supports multiple sign-in scopes, e.g. for regular users and
|
59
|
+
for admins. The method `signed_in?` checks that any scope is signed in. To
|
60
|
+
check for a specific scope, the method `user_signed_in?` is available. For the
|
61
|
+
purpose of RailsTutorial with Devise, this distinction is not important since
|
62
|
+
we only have one type of user. Admin privileges are implemented differently,
|
63
|
+
with the admin flag)
|
64
|
+
|
65
|
+
[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
|
+
}
|