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.
Files changed (159) hide show
  1. data/.gitignore +6 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +8 -0
  4. data/LICENSE +57 -0
  5. data/README.md +90 -0
  6. data/Rakefile +25 -0
  7. data/lib/generators/chapter07/begin/USAGE +27 -0
  8. data/lib/generators/chapter07/begin/begin_generator.rb +39 -0
  9. data/lib/generators/chapter07/begin/instructions.md +74 -0
  10. data/lib/generators/chapter07/begin/templates/app/controllers/application_controller.rb +8 -0
  11. data/lib/generators/chapter07/begin/templates/app/controllers/pages_controller.rb +11 -0
  12. data/lib/generators/chapter07/begin/templates/app/controllers/users_controller.rb +3 -0
  13. data/lib/generators/chapter07/begin/templates/app/helpers/application_helper.rb +12 -0
  14. data/lib/generators/chapter07/begin/templates/app/helpers/pages_helper.rb +2 -0
  15. data/lib/generators/chapter07/begin/templates/app/helpers/users_helper.rb +7 -0
  16. data/lib/generators/chapter07/begin/templates/app/models/user.rb +9 -0
  17. data/lib/generators/chapter07/begin/templates/app/views/layouts/_footer.html.erb +9 -0
  18. data/lib/generators/chapter07/begin/templates/app/views/layouts/_header.html.erb +10 -0
  19. data/lib/generators/chapter07/begin/templates/app/views/layouts/_stylesheets.html.erb +7 -0
  20. data/lib/generators/chapter07/begin/templates/app/views/layouts/application.html.erb +17 -0
  21. data/lib/generators/chapter07/begin/templates/app/views/pages/about.html.erb +7 -0
  22. data/lib/generators/chapter07/begin/templates/app/views/pages/contact.html.erb +5 -0
  23. data/lib/generators/chapter07/begin/templates/app/views/pages/home.html.erb +7 -0
  24. data/lib/generators/chapter07/begin/templates/app/views/users/show.html.erb +15 -0
  25. data/lib/generators/chapter07/begin/templates/config/initializers/devise.rb +194 -0
  26. data/lib/generators/chapter07/begin/templates/config/locales/devise.en.yml +50 -0
  27. data/lib/generators/chapter07/begin/templates/config/routes.rb.tt +17 -0
  28. data/lib/generators/chapter07/begin/templates/db/migrate/20110608224650_devise_create_users.rb +29 -0
  29. data/lib/generators/chapter07/begin/templates/db/schema.rb +34 -0
  30. data/lib/generators/chapter07/begin/templates/public/images/logo.png +0 -0
  31. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/ie.css +36 -0
  32. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/icons/cross.png +0 -0
  33. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/icons/key.png +0 -0
  34. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/icons/tick.png +0 -0
  35. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/readme.txt +32 -0
  36. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/buttons/screen.css +97 -0
  37. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/fancy-type/readme.txt +14 -0
  38. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/fancy-type/screen.css +71 -0
  39. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/doc.png +0 -0
  40. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/email.png +0 -0
  41. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/external.png +0 -0
  42. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/feed.png +0 -0
  43. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/im.png +0 -0
  44. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/lock.png +0 -0
  45. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/pdf.png +0 -0
  46. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/visited.png +0 -0
  47. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/icons/xls.png +0 -0
  48. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/readme.txt +18 -0
  49. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/link-icons/screen.css +42 -0
  50. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/rtl/readme.txt +10 -0
  51. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/plugins/rtl/screen.css +110 -0
  52. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/print.css +29 -0
  53. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/screen.css +265 -0
  54. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/forms.css +82 -0
  55. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/grid.css +280 -0
  56. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/grid.png +0 -0
  57. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/ie.css +79 -0
  58. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/print.css +92 -0
  59. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/reset.css +65 -0
  60. data/lib/generators/chapter07/begin/templates/public/stylesheets/blueprint/src/typography.css +123 -0
  61. data/lib/generators/chapter07/begin/templates/public/stylesheets/custom.css +137 -0
  62. data/lib/generators/chapter07/begin/templates/spec/controllers/pages_controller_07_spec.rb +48 -0
  63. data/lib/generators/chapter07/begin/templates/spec/controllers/users_controller_07_spec.rb +38 -0
  64. data/lib/generators/chapter07/begin/templates/spec/factories.rb +9 -0
  65. data/lib/generators/chapter07/begin/templates/spec/models/user_07_spec.rb +38 -0
  66. data/lib/generators/chapter07/begin/templates/spec/requests/layout_links_07_spec.rb +44 -0
  67. data/lib/generators/chapter07/begin/templates/spec/spec_helper.rb +39 -0
  68. data/lib/generators/chapter07/solutions/USAGE +21 -0
  69. data/lib/generators/chapter07/solutions/solutions_generator.rb +23 -0
  70. data/lib/generators/chapter07/solutions/templates/app/controllers/pages_controller.rb +18 -0
  71. data/lib/generators/chapter07/solutions/templates/app/controllers/users_controller.rb +8 -0
  72. data/lib/generators/chapter07/solutions/templates/app/models/user.rb +11 -0
  73. data/lib/generators/chapter07/solutions/templates/app/views/layouts/_footer.html.erb +10 -0
  74. data/lib/generators/chapter07/solutions/templates/app/views/layouts/_header.html.erb +11 -0
  75. data/lib/generators/chapter07/solutions/templates/app/views/pages/help.html.erb +4 -0
  76. data/lib/generators/chapter07/solutions/templates/app/views/pages/home.html.erb +7 -0
  77. data/lib/generators/chapter07/solutions/templates/app/views/users/show.html.erb +15 -0
  78. data/lib/generators/chapter08_09/begin/USAGE +24 -0
  79. data/lib/generators/chapter08_09/begin/begin_generator.rb +29 -0
  80. data/lib/generators/chapter08_09/begin/instructions.md +65 -0
  81. data/lib/generators/chapter08_09/begin/snippets/custom.css +49 -0
  82. data/lib/generators/chapter08_09/begin/templates/spec/controllers/devise/registrations_controller_08_spec.rb +83 -0
  83. data/lib/generators/chapter08_09/begin/templates/spec/requests/layout_links_09_spec.rb +35 -0
  84. data/lib/generators/chapter08_09/begin/templates/spec/requests/users_signup_08_spec.rb +36 -0
  85. data/lib/generators/chapter08_09/solutions/USAGE +18 -0
  86. data/lib/generators/chapter08_09/solutions/solutions_generator.rb +12 -0
  87. data/lib/generators/chapter08_09/solutions/templates/app/helpers/application_helper.rb +16 -0
  88. data/lib/generators/chapter08_09/solutions/templates/app/views/devise/passwords/edit.html.erb +16 -0
  89. data/lib/generators/chapter08_09/solutions/templates/app/views/devise/passwords/new.html.erb +12 -0
  90. data/lib/generators/chapter08_09/solutions/templates/app/views/devise/registrations/_fields.html.erb +16 -0
  91. data/lib/generators/chapter08_09/solutions/templates/app/views/devise/registrations/edit.html.erb +28 -0
  92. data/lib/generators/chapter08_09/solutions/templates/app/views/devise/registrations/new.html.erb +13 -0
  93. data/lib/generators/chapter08_09/solutions/templates/app/views/devise/sessions/new.html.erb +17 -0
  94. data/lib/generators/chapter08_09/solutions/templates/app/views/devise/shared/_links.erb +25 -0
  95. data/lib/generators/chapter08_09/solutions/templates/app/views/layouts/_header.html.erb +19 -0
  96. data/lib/generators/chapter08_09/solutions/templates/app/views/layouts/application.html.erb +20 -0
  97. data/lib/generators/chapter10/begin/USAGE +24 -0
  98. data/lib/generators/chapter10/begin/begin_generator.rb +41 -0
  99. data/lib/generators/chapter10/begin/instructions.md +47 -0
  100. data/lib/generators/chapter10/begin/snippets/custom.css +12 -0
  101. data/lib/generators/chapter10/begin/snippets/factories.rb +10 -0
  102. data/lib/generators/chapter10/begin/templates/app/views/layouts/application.html.erb +21 -0
  103. data/lib/generators/chapter10/begin/templates/lib/tasks/sample_data.rake +24 -0
  104. data/lib/generators/chapter10/begin/templates/spec/controllers/users_controller_10_spec.rb +110 -0
  105. data/lib/generators/chapter10/begin/templates/spec/models/user_10_spec.rb +24 -0
  106. data/lib/generators/chapter10/solutions/USAGE +18 -0
  107. data/lib/generators/chapter10/solutions/snippets/migration_add_admin_to_users.rb +9 -0
  108. data/lib/generators/chapter10/solutions/solutions_generator.rb +32 -0
  109. data/lib/generators/chapter10/solutions/templates/app/controllers/users_controller.rb +28 -0
  110. data/lib/generators/chapter10/solutions/templates/app/views/users/_user.html.erb +8 -0
  111. data/lib/generators/chapter10/solutions/templates/app/views/users/index.html.erb +9 -0
  112. data/lib/generators/chapter11_1/begin/USAGE +24 -0
  113. data/lib/generators/chapter11_1/begin/begin_generator.rb +24 -0
  114. data/lib/generators/chapter11_1/begin/instructions.md +39 -0
  115. data/lib/generators/chapter11_1/begin/templates/lib/tasks/sample_data.rake +29 -0
  116. data/lib/generators/chapter11_1/begin/templates/spec/models/microposts_11_1_spec.rb +45 -0
  117. data/lib/generators/chapter11_1/begin/templates/spec/models/user_11_1_spec.rb +30 -0
  118. data/lib/generators/chapter11_1/solutions/USAGE +18 -0
  119. data/lib/generators/chapter11_1/solutions/snippets/migration_create_microposts.rb +17 -0
  120. data/lib/generators/chapter11_1/solutions/solutions_generator.rb +25 -0
  121. data/lib/generators/chapter11_1/solutions/templates/app/models/micropost.rb +10 -0
  122. data/lib/generators/chapter11_1/solutions/templates/app/models/user.rb +14 -0
  123. data/lib/generators/chapter11_1/solutions/templates/spec/factories.rb +16 -0
  124. data/lib/generators/chapter11_2/begin/USAGE +24 -0
  125. data/lib/generators/chapter11_2/begin/begin_generator.rb +30 -0
  126. data/lib/generators/chapter11_2/begin/instructions.md +35 -0
  127. data/lib/generators/chapter11_2/begin/snippets/custom.css +59 -0
  128. data/lib/generators/chapter11_2/begin/templates/app/views/users/show.html.erb +23 -0
  129. data/lib/generators/chapter11_2/begin/templates/spec/controllers/users_controller_11_2_spec.rb +31 -0
  130. data/lib/generators/chapter11_2/solutions/USAGE +18 -0
  131. data/lib/generators/chapter11_2/solutions/solutions_generator.rb +12 -0
  132. data/lib/generators/chapter11_2/solutions/templates/app/controllers/users_controller.rb +29 -0
  133. data/lib/generators/chapter11_2/solutions/templates/app/views/microposts/_micropost.html.erb +8 -0
  134. data/lib/generators/chapter11_2/solutions/templates/app/views/users/show.html.erb +23 -0
  135. data/lib/generators/chapter11_3/begin/USAGE +24 -0
  136. data/lib/generators/chapter11_3/begin/begin_generator.rb +24 -0
  137. data/lib/generators/chapter11_3/begin/instructions.md +80 -0
  138. data/lib/generators/chapter11_3/begin/templates/app/views/pages/home.html.erb +24 -0
  139. data/lib/generators/chapter11_3/begin/templates/app/views/shared/_feed.html.erb +6 -0
  140. data/lib/generators/chapter11_3/begin/templates/app/views/shared/_feed_item.html.erb +14 -0
  141. data/lib/generators/chapter11_3/begin/templates/app/views/shared/_micropost_form.html.erb +9 -0
  142. data/lib/generators/chapter11_3/begin/templates/app/views/shared/_user_info.html.erb +11 -0
  143. data/lib/generators/chapter11_3/begin/templates/spec/controllers/microposts_controllers_11_3_spec.rb +103 -0
  144. data/lib/generators/chapter11_3/begin/templates/spec/controllers/pages_controller_11_3_spec.rb +14 -0
  145. data/lib/generators/chapter11_3/begin/templates/spec/models/user_11_3_spec.rb +31 -0
  146. data/lib/generators/chapter11_3/begin/templates/spec/requests/micropost_11_3_spec.rb +41 -0
  147. data/lib/generators/chapter11_3/solutions/USAGE +18 -0
  148. data/lib/generators/chapter11_3/solutions/solutions_generator.rb +30 -0
  149. data/lib/generators/chapter11_3/solutions/templates/app/controllers/microposts_controller.rb +20 -0
  150. data/lib/generators/chapter11_3/solutions/templates/app/controllers/pages_controller.rb +22 -0
  151. data/lib/generators/chapter11_3/solutions/templates/app/views/microposts/_micropost.html.erb +15 -0
  152. data/lib/generators/chapter11_3/solutions/templates/app/views/pages/home.html.erb +24 -0
  153. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_error_messages.html.erb +13 -0
  154. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_feed.html.erb +6 -0
  155. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_feed_item.html.erb +21 -0
  156. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_micropost_form.html.erb +9 -0
  157. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_user_info.html.erb +11 -0
  158. data/lib/tft_rails.rb +2 -0
  159. metadata +217 -0
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe UsersController do
4
+ render_views
5
+
6
+ describe "GET 'index'" do
7
+
8
+ describe "for non-signed-in users" do
9
+ it "should deny access" do
10
+ get :index
11
+ response.should redirect_to(new_user_session_path)
12
+ flash[:alert].should =~ /sign in/i
13
+ end
14
+ end
15
+
16
+ describe "for signed-in users" do
17
+
18
+ before(:each) do
19
+ @user = Factory(:user)
20
+ sign_in(@user)
21
+
22
+ second = Factory(:user, :name => "Bob", :email => "another@example.com")
23
+ third = Factory(:user, :name => "Ben", :email => "another@example.net")
24
+
25
+ @users = [@user, second, third]
26
+ @users = [@user, second, third]
27
+ 30.times do
28
+ @users << Factory(:user, :email => Factory.next(:email))
29
+ end
30
+ end
31
+
32
+ it "should be successful" do
33
+ get :index
34
+ response.should be_success
35
+ end
36
+
37
+ it "should have the right title" do
38
+ get :index
39
+ response.should render_template('index')
40
+ end
41
+
42
+ it "should have an element for each user" do
43
+ get :index
44
+ @users[0..2].each do |user|
45
+ response.should have_selector("li", :content => user.name)
46
+ end
47
+ end
48
+
49
+ it "should paginate users" do
50
+ get :index
51
+ response.should have_selector("div.pagination")
52
+ response.should have_selector("span.disabled", :content => "Previous")
53
+ response.should have_selector("a", :href => "/users?page=2",
54
+ :content => "2")
55
+ response.should have_selector("a", :href => "/users?page=2",
56
+ :content => "Next")
57
+ end
58
+ end
59
+ end
60
+
61
+ describe "DELETE 'destroy'" do
62
+
63
+ before(:each) do
64
+ @user = Factory(:user)
65
+ end
66
+
67
+ describe "as a non-signed-in user" do
68
+ it "should deny access" do
69
+ delete :destroy, :id => @user
70
+ response.should redirect_to(new_user_session_path)
71
+ end
72
+ end
73
+
74
+ describe "as a non-admin user" do
75
+ before do
76
+ sign_in(@user)
77
+ end
78
+
79
+ it "should protect the page" do
80
+ delete :destroy, :id => @user
81
+ response.should redirect_to(root_path)
82
+ end
83
+
84
+ it 'should not destroy the user' do
85
+ expect {
86
+ delete :destroy, :id => @user
87
+ }.to_not change(User,:count)
88
+ end
89
+ end
90
+
91
+ describe "as an admin user" do
92
+
93
+ before(:each) do
94
+ admin = Factory(:user, :email => "admin@example.com", :admin => true)
95
+ sign_in(admin)
96
+ end
97
+
98
+ it "should destroy the user" do
99
+ expect {
100
+ delete :destroy, :id => @user
101
+ }.to change(User, :count).by(-1)
102
+ end
103
+
104
+ it "should redirect to the users page" do
105
+ delete :destroy, :id => @user
106
+ response.should redirect_to(users_path)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe User do
4
+
5
+ describe "admin attribute" do
6
+
7
+ before(:each) do
8
+ @user = Factory(:user)
9
+ end
10
+
11
+ it "should respond to admin" do
12
+ @user.should respond_to(:admin)
13
+ end
14
+
15
+ it "should not be an admin by default" do
16
+ @user.should_not be_admin
17
+ end
18
+
19
+ it "should be convertible to an admin" do
20
+ @user.toggle!(:admin)
21
+ @user.should be_admin
22
+ end
23
+ end
24
+ 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 chapter10:solutions
6
+
7
+ This copies the solutions and other necessary files (e.g. images, assets, helpers, etc.) into the project
8
+ to conclude Chapter 10. This should make all tests pass and bring you in sync to the application at
9
+ the end of Chapter 10.
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,9 @@
1
+ class AddAdminToUsers < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :admin, :boolean, :default => false, :null => false
4
+ end
5
+
6
+ def self.down
7
+ remove_column :users, :admin
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ module Chapter10
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_destroy_action_to_users_resource
11
+ dest = File.join(Rails.root,'config','routes.rb')
12
+ insert_into_file(dest, :after => %r{:index,\s*:show}) do
13
+ ", :destroy"
14
+ end
15
+ end
16
+
17
+ def add_migration
18
+ found_candidate = Dir.glob(File.join(Rails.root,'db','migrate','*_admin_*')).present?
19
+
20
+ if (found_candidate &&
21
+ yes?("We found a migration file containing the word '_admin_'. We think you have the correct migration. Do you still way to copy the solution anyway? (yes/no)", :yellow)) \
22
+ or !found_candidate
23
+
24
+ src = File.expand_path("../snippets/migration_add_admin_to_users.rb", __FILE__)
25
+ dest = File.join(Rails.root,'db','migrate',Time.now.strftime("%Y%m%d%H%M%S")+'_add_admin_to_users.rb')
26
+ copy_file(src,dest)
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,28 @@
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
+ @title = @user.name
9
+ end
10
+
11
+ def index
12
+ @title = "All users"
13
+ @users = User.paginate(:page => params[:page])
14
+ end
15
+
16
+ def destroy
17
+ User.find(params[:id]).destroy
18
+ flash[:notice] = "User destroyed."
19
+ redirect_to users_path
20
+ end
21
+
22
+ private
23
+
24
+ def admin_user
25
+ redirect_to(root_path) unless current_user.admin?
26
+ end
27
+
28
+ end
@@ -0,0 +1,8 @@
1
+ <li>
2
+ <%= gravatar_for user, :size => 30 %>
3
+ <%= link_to user.name, user %>
4
+ <% if current_user.admin? %>
5
+ | <%= link_to "delete", user, :method => :delete, :confirm => "You sure?",
6
+ :title => "Delete #{user.name}" %>
7
+ <% end %>
8
+ </li>
@@ -0,0 +1,9 @@
1
+ <h1>All users</h1>
2
+
3
+ <%= will_paginate %>
4
+
5
+ <ul class="users">
6
+ <%= render @users %>
7
+ </ul>
8
+
9
+ <%= will_paginate %>
@@ -0,0 +1,24 @@
1
+ Description:
2
+ Begins Test-First Teaching exercises adapted from Chapter 11.1 of the RailsTutorial by Michael Hartl.
3
+
4
+ It is assumed that this generator is run after the exercises for all prior chapters 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_1: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.1 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 chapter11_1: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_1
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_1.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,39 @@
1
+ RailsTutorial Chapter 11.1 Test-First Teaching Instructions
2
+ =========================================================
3
+
4
+ Chapter 11.1 covers adding a Micropost model and setting up an association between
5
+ User and Micropost.
6
+
7
+ When you first run `rake spec`, you'll get an error like below and no specs will execute.
8
+
9
+ uninitialized constant Micropost (NameError)
10
+
11
+ This is because we don't have this class defined yet. So, go ahead and create it using the rails generators:
12
+
13
+ rails generate model Micropost content:string user_id:integer
14
+
15
+ This will generate a migration file, a model file and a spec file for Micropost. Note that for the TFT
16
+ exercises, a spec file is already provided, and we don't need the generated spec file. So, go ahead
17
+ and _remove:_ `spec/models/micropost_spec.rb`
18
+
19
+ Add indexes to the migration file, see [Chapter 11.1.1][chapter_11_1_1]. Indices should be added for each
20
+ column that will be used for record lookup or ordering. For instance, if we want to sort Microposts by
21
+ creation date, then there should be an index on the `created_at` column. (Note that the `timestamps` migration
22
+ methods created two columns, `created_at` and `updated_at`.)
23
+
24
+ Then migrate the database:
25
+
26
+ rake db:migrate
27
+
28
+
29
+ Rails Concepts Covered
30
+ ======================
31
+
32
+ * Using the model generator (for Microposts)
33
+ * Adding indexes to the database
34
+ * Associations, has_many (dep't destroy) and belongs_to
35
+ * Validations for format
36
+ * Factories with associations
37
+ * Scopes (simple, default scope), order
38
+
39
+ [chapter_11_1_1]: http://ruby.railstutorial.org/chapters/user-microposts#sec:the_basic_model "RailsTutorial Chapter 11.1.1"
@@ -0,0 +1,29 @@
1
+ namespace :db do
2
+ desc "Fill database with sample data"
3
+ task :populate => :environment do
4
+ Rake::Task['db:reset'].invoke
5
+ make_users
6
+ end
7
+ end
8
+
9
+ def make_users
10
+ admin = User.create!(:name => "Example User",
11
+ :email => "example@railstutorial.org",
12
+ :password => "password",
13
+ :password_confirmation => "password")
14
+ admin.toggle!(:admin)
15
+ 99.times do |n|
16
+ name = Faker::Name.name
17
+ email = "example-#{n+1}@railstutorial.org"
18
+ password = "password"
19
+ User.create!(:name => name,
20
+ :email => email,
21
+ :password => password,
22
+ :password_confirmation => password)
23
+ end
24
+ User.all(:limit => 6).each do |user|
25
+ 50.times do
26
+ user.microposts.create!(:content => Faker::Lorem.sentence(5))
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Micropost do
4
+
5
+ before(:each) do
6
+ @user = Factory(:user)
7
+ @attr = { :content => "value for content" }
8
+ end
9
+
10
+ it "should create a new instance given valid attributes" do
11
+ @user.microposts.create!(@attr)
12
+ end
13
+
14
+ describe "user associations" do
15
+
16
+ before(:each) do
17
+ @micropost = @user.microposts.create(@attr)
18
+ end
19
+
20
+ it "should have a user attribute" do
21
+ @micropost.should respond_to(:user)
22
+ end
23
+
24
+ it "should have the right associated user" do
25
+ @micropost.user_id.should == @user.id
26
+ @micropost.user.should == @user
27
+ end
28
+ end
29
+
30
+ describe "validations" do
31
+
32
+ it "should require a user id" do
33
+ Micropost.new(@attr).should_not be_valid
34
+ end
35
+
36
+ it "should require nonblank content" do
37
+ @user.microposts.build(:content => " ").should_not be_valid
38
+ end
39
+
40
+ it "should reject long content" do
41
+ @user.microposts.build(:content => "a" * 141).should_not be_valid
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,30 @@
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
+ it "should have a microposts attribute" do
14
+ @user.should respond_to(:microposts)
15
+ end
16
+
17
+ it "should have the right microposts in the right order" do
18
+ @user.microposts.should == [@mp2, @mp1]
19
+ end
20
+
21
+ it "should destroy associated microposts" do
22
+ @user.destroy
23
+ [@mp1, @mp2].each do |micropost|
24
+ Micropost.find_by_id(micropost.id).should be_nil
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,18 @@
1
+ Description:
2
+ Wraps up Test-First Teaching exercises adapted from Chapter 11.1 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.1. This should make all tests pass and bring you in sync to the application at
9
+ the end of Chapter 11.1.
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,17 @@
1
+ class CreateMicroposts < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :microposts do |t|
4
+ t.string :content
5
+ t.integer :user_id
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :microposts, :user_id
11
+ add_index :microposts, :created_at
12
+ end
13
+
14
+ def self.down
15
+ drop_table :microposts
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ module Chapter11_1
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_migration
11
+ found_candidate = Dir.glob(File.join(Rails.root,'db','migrate','*create_micropost*')).present?
12
+
13
+ if (found_candidate &&
14
+ yes?("We found a migration file containing the word '_admin_'. We think you have the correct migration. Do you still way to copy the solution anyway? (yes/no)", :yellow)) \
15
+ or !found_candidate
16
+
17
+ src = File.expand_path("../snippets/migration_create_microposts.rb", __FILE__)
18
+ dest = File.join(Rails.root,'db','migrate',Time.now.strftime("%Y%m%d%H%M%S")+'_create_microposts.rb')
19
+ copy_file(src,dest)
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ class Micropost < ActiveRecord::Base
2
+
3
+ belongs_to :user
4
+
5
+ default_scope order('microposts.created_at DESC')
6
+
7
+ validates :user_id, :presence => true
8
+ validates :content, :presence => true, :length => {:maximum => 140}
9
+
10
+ end
@@ -0,0 +1,14 @@
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
+
12
+ has_many :microposts, :dependent => :destroy
13
+
14
+ end
@@ -0,0 +1,16 @@
1
+ # By using the symbol ':user', we get Factory Girl to simulate the User model.
2
+ Factory.define :user do |user|
3
+ user.name "Michael Hartl"
4
+ user.email "mhartl@example.com"
5
+ user.password "foobar"
6
+ user.password_confirmation "foobar"
7
+ end
8
+
9
+ Factory.sequence :email do |n|
10
+ "person-#{n}@example.com"
11
+ end
12
+
13
+ Factory.define :micropost do |mp|
14
+ mp.content "This is a new post"
15
+ mp.association :user
16
+ end
@@ -0,0 +1,24 @@
1
+ Description:
2
+ Begins Test-First Teaching exercises adapted from Chapter 11.2 of the RailsTutorial by Michael Hartl.
3
+
4
+ It is assumed that this generator is run after the exercises for all prior chapters 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_2: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.2 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 chapter11_2: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,30 @@
1
+ module Chapter11_2
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
+ return unless File.exists?(instr_md)
21
+ dest = File.join(Rails.root,'doc','chapter11_2.html')
22
+ copy_file(instr_md, dest, :force => true) do |content|
23
+ RDiscount.new(content).to_html
24
+ end
25
+ say_status('Note',"Now open file://#{dest} in your web browser for instructions", :cyan)
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ RailsTutorial Chapter 11.2 Test-First Teaching Instructions
2
+ ===========================================================
3
+
4
+ When you first run `rake spec`, you'll get an error like below and no specs will execute.
5
+
6
+ uninitialized constant MicropostsController (NameError)
7
+
8
+ This is because we don't have this class defined yet. So, go ahead and create it using the rails generators:
9
+
10
+ _Note_: **Microposts is in plural here** (Rails convention for controllers).
11
+
12
+ rails g controller Microposts --controller-specs=false --view-specs=false --helper-specs=false
13
+
14
+ Note: The controller generatore (unlike the model generator), we can instruct to suppress
15
+ the spec files.
16
+
17
+ For the particular markup to make the micropost display look pretty,
18
+ refer to Rails Tutorial [Chapter 11.2.1][chapter_11_2_1]
19
+
20
+ Extra Credit
21
+ ------------
22
+
23
+ Review how pagination for the users index page was done in Chapter 10.
24
+ Apply the same technique to the microposts displayed on the user show page.
25
+
26
+ Rails Concepts Covered
27
+ ======================
28
+
29
+ * Using controller generator
30
+ * Testing for instance variables in the controller
31
+ * More association methods, :empty?, :count
32
+ * Rendering partials by object collection
33
+ * Time helper
34
+
35
+ [chapter_11_2_1]: http://ruby.railstutorial.org/chapters/user-microposts#sec:augmenting_the_user_show_page "Chapter 11.2.1"