tft_rails 0.6.1 → 0.6.2

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 (29) hide show
  1. data/README.md +14 -0
  2. data/lib/generators/chapter07/begin/begin_generator.rb +7 -0
  3. data/lib/generators/chapter07/begin/templates/spec/spec_helper.rb +10 -0
  4. data/lib/generators/chapter08_09/begin/instructions.md +8 -1
  5. data/lib/generators/chapter10/begin/templates/lib/tasks/{same_data.rake → sample_data.rake} +0 -0
  6. data/lib/generators/chapter10/solutions/snippets/migration_add_admin_to_users.rb +1 -1
  7. data/lib/generators/chapter11_1/begin/templates/lib/tasks/{same_data.rake → sample_data.rake} +0 -0
  8. data/lib/generators/chapter11_1/solutions/templates/app/{model → models}/micropost.rb +1 -1
  9. data/lib/generators/chapter11_1/solutions/templates/app/{model → models}/user.rb +0 -0
  10. data/lib/generators/chapter11_2/solutions/solutions_generator.rb +6 -0
  11. data/lib/generators/chapter11_3/begin/templates/app/views/pages/home.html.erb +24 -0
  12. data/lib/generators/chapter11_3/begin/templates/app/views/shared/_feed.html.erb +6 -0
  13. data/lib/generators/chapter11_3/begin/templates/app/views/shared/_feed_item.html.erb +14 -0
  14. data/lib/generators/chapter11_3/begin/templates/app/views/shared/_micropost_form.html.erb +9 -0
  15. data/lib/generators/chapter11_3/begin/templates/app/views/shared/_user_info.html.erb +11 -0
  16. data/lib/generators/chapter11_3/begin/templates/spec/controllers/microposts_controllers_11_3_spec.rb +1 -0
  17. data/lib/generators/chapter11_3/begin/templates/spec/models/user_11_3_spec.rb +31 -0
  18. data/lib/generators/chapter11_3/begin/templates/spec/requests/micropost_11_3_spec.rb +41 -0
  19. data/lib/generators/chapter11_3/solutions/solutions_generator.rb +22 -0
  20. data/lib/generators/chapter11_3/solutions/templates/app/controllers/microposts_controller.rb +20 -0
  21. data/lib/generators/chapter11_3/solutions/templates/app/controllers/pages_controller.rb +22 -0
  22. data/lib/generators/chapter11_3/solutions/templates/app/views/microposts/_micropost.html.erb +15 -0
  23. data/lib/generators/chapter11_3/solutions/templates/app/views/pages/home.html.erb +24 -0
  24. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_error_messages.html.erb +13 -0
  25. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_feed.html.erb +6 -0
  26. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_feed_item.html.erb +21 -0
  27. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_micropost_form.html.erb +9 -0
  28. data/lib/generators/chapter11_3/solutions/templates/app/views/shared/_user_info.html.erb +11 -0
  29. metadata +22 -6
data/README.md CHANGED
@@ -60,6 +60,20 @@ a wonderful job to illustrate many concepts for teaching, but it is no replaceme
60
60
  that has been peer-reviewed by many experienced developers and is in use in many commercial applications. Devise is the
61
61
  current industry standard solution and was used here.
62
62
 
63
+ Adding to TFT Rails
64
+ -------------------
65
+
66
+ To modify the exercises, make your code changes, then run all chapters in
67
+ successive order in a few rails app. After every solutions generator, the
68
+ specs should run clean.
69
+
70
+ TODO: Rig up a test suite which will create a new rails app, then install
71
+ all chapters and solutions in successive order and run the spec suite every time.
72
+ This may necessitate construction our own Test Runner or similar. I'm not
73
+ sure how to do this.
74
+
75
+ TODO: Add Chapter 12. The project currently contains Chapters 7 through 11, adapted for Devise.
76
+
63
77
  Sponsors
64
78
  --------
65
79
 
@@ -7,6 +7,13 @@ module Chapter07
7
7
  directory(self.class.source_root, Rails.root, :force => true)
8
8
  end
9
9
 
10
+ def insert_gitignore
11
+ dest = File.join(Rails.root,'.gitignore')
12
+ insert_into_file(dest, :before => /\Z/) do # insert before end
13
+ "\n.idea\n"
14
+ end
15
+ end
16
+
10
17
  def augment_gemfile
11
18
  gem 'devise', '~> 1.3.4'
12
19
  gem 'gravatar_image_tag', '~> 1.0.0'
@@ -7,6 +7,16 @@ require 'rspec/rails'
7
7
  # in spec/support/ and its subdirectories.
8
8
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
9
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
+
10
20
  RSpec.configure do |config|
11
21
  # == Mock Framework
12
22
  #
@@ -50,9 +50,16 @@ The Devise sign-in page meets our needs and doesn't need customizing.
50
50
  However, we need to work on the layout to make sure that it shows a "Sign out" link
51
51
  if a user is logged in, and a "Sign in" link only if a user is not logged in.
52
52
 
53
- [Devise][devise] offers the controller methods `user_signed_in?` and `current_user`
53
+ [Devise][devise] offers the controller methods `signed_in?` and `current_user`
54
54
  to report on the current login status. The first method returns `true` or `false`
55
55
  depending on whether a user logged in, the second returns the actual user object,
56
56
  or `nil` if no user is logged in.
57
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
+
58
65
  [devise]: https://github.com/plataformatec/devise "Devise on github"
@@ -1,6 +1,6 @@
1
1
  class AddAdminToUsers < ActiveRecord::Migration
2
2
  def self.up
3
- add_column :users, :admin, :boolean
3
+ add_column :users, :admin, :boolean, :default => false, :null => false
4
4
  end
5
5
 
6
6
  def self.down
@@ -2,7 +2,7 @@ class Micropost < ActiveRecord::Base
2
2
 
3
3
  belongs_to :user
4
4
 
5
- default_scope order('created_at DESC')
5
+ default_scope order('microposts.created_at DESC')
6
6
 
7
7
  validates :user_id, :presence => true
8
8
  validates :content, :presence => true, :length => {:maximum => 140}
@@ -1,6 +1,12 @@
1
1
  module Chapter11_2
2
2
  module Generators
3
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
+
4
10
  end
5
11
  end
6
12
  end
@@ -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,6 @@
1
+ <%# if there are feed items %>
2
+ <table class="microposts" summary="User microposts">
3
+ <%#= display feed items here %>
4
+ </table>
5
+ <%#= pagination ? %>
6
+ <%# 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>
@@ -0,0 +1,9 @@
1
+ <%#= form helper %>
2
+ <%#= error display %>
3
+ <div class="field">
4
+ <%#= content form field %>
5
+ </div>
6
+ <div class="actions">
7
+ <%#= submit button %>
8
+ </div>
9
+ <%# end %>
@@ -0,0 +1,11 @@
1
+ <div class="user_info">
2
+ <a href="<%#= link to user %>">
3
+ <%#= user's image %>
4
+ <span class="user_name">
5
+ <%#= user's name %>
6
+ </span>
7
+ <span class="microposts">
8
+ <%# number of user's microposts %>
9
+ </span>
10
+ </a>
11
+ </div>
@@ -74,6 +74,7 @@ describe MicropostsController do
74
74
  wrong_user = Factory(:user, :email => Factory.next(:email))
75
75
  sign_in(wrong_user)
76
76
  @micropost = Factory(:micropost, :user => @user)
77
+ request.env["HTTP_REFERER"] = root_path
77
78
  end
78
79
 
79
80
  it "should deny access" do
@@ -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
@@ -1,7 +1,29 @@
1
1
  module Chapter11_3
2
2
  module Generators
3
3
  class SolutionsGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
4
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
5
27
 
6
28
  end
7
29
  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
@@ -0,0 +1,22 @@
1
+ class PagesController < ApplicationController
2
+ def home
3
+ @title = "Home"
4
+ if signed_in?
5
+ @micropost = current_user.microposts.build
6
+ @feed_items = current_user.feed.paginate(:page => params[:page])
7
+ end
8
+ end
9
+
10
+ def contact
11
+ @title = 'Contact'
12
+ end
13
+
14
+ def about
15
+ @title = 'About'
16
+ end
17
+
18
+ def help
19
+ @title = 'Help'
20
+ end
21
+
22
+ end
@@ -0,0 +1,15 @@
1
+ <tr>
2
+ <td class="micropost">
3
+ <span class="content"><%= micropost.content %></span>
4
+ <span class="timestamp">
5
+ Posted <%= time_ago_in_words(micropost.created_at) %> ago.
6
+ </span>
7
+ </td>
8
+ <% if signed_in? && current_user.id == micropost.user_id %>
9
+ <td>
10
+ <%= link_to "delete", micropost, :method => :delete,
11
+ :confirm => "You sure?",
12
+ :title => micropost.content %>
13
+ </td>
14
+ <% end %>
15
+ </tr>
@@ -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
+ <%= render 'shared/micropost_form' %>
7
+ <%= render 'shared/feed' %>
8
+ </td>
9
+ <td class="sidebar round">
10
+ <%= render 'shared/user_info' %>
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,13 @@
1
+ <% if object.errors.any? %>
2
+ <div id="error_explanation">
3
+ <h2><%= pluralize(object.errors.count, "error") %>
4
+ prohibited this <%= object.class.to_s.underscore.humanize.downcase %>
5
+ from being saved:</h2>
6
+ <p>There were problems with the following fields:</p>
7
+ <ul>
8
+ <% object.errors.full_messages.each do |msg| %>
9
+ <li><%= msg %></li>
10
+ <% end %>
11
+ </ul>
12
+ </div>
13
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <% if @feed_items.present? %>
2
+ <table class="microposts" summary="User microposts">
3
+ <%= render :partial => 'shared/feed_item', :collection => @feed_items %>
4
+ </table>
5
+ <%= will_paginate @feed_items %>
6
+ <% end %>
@@ -0,0 +1,21 @@
1
+ <tr>
2
+ <td class="gravatar">
3
+ <%= link_to gravatar_for(feed_item.user), feed_item.user %>
4
+ </td>
5
+ <td class="micropost">
6
+ <span class="user">
7
+ <%= link_to feed_item.user.name, feed_item.user %>
8
+ </span>
9
+ <span class="content"><%= feed_item.content %></span>
10
+ <span class="timestamp">
11
+ Posted <%= time_ago_in_words(feed_item.created_at) %> ago.
12
+ </span>
13
+ </td>
14
+ <% if signed_in? && current_user.id == feed_item.user_id %>
15
+ <td>
16
+ <%= link_to "delete", feed_item, :method => :delete,
17
+ :confirm => "You sure?",
18
+ :title => feed_item.content %>
19
+ </td>
20
+ <% end %>
21
+ </tr>
@@ -0,0 +1,9 @@
1
+ <%= form_for @micropost do |f| %>
2
+ <%= render 'shared/error_messages', :object => f.object %>
3
+ <div class="field">
4
+ <%= f.text_area :content %>
5
+ </div>
6
+ <div class="actions">
7
+ <%= f.submit "Submit" %>
8
+ </div>
9
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <div class="user_info">
2
+ <a href="<%= user_path(current_user) %>">
3
+ <%= gravatar_for current_user, :size => 30 %>
4
+ <span class="user_name">
5
+ <%= current_user.name %>
6
+ </span>
7
+ <span class="microposts">
8
+ <%= pluralize(current_user.microposts.count, "micropost") %>
9
+ </span>
10
+ </a>
11
+ </div>
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: tft_rails
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.6.1
5
+ version: 0.6.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Wolfram Arnold
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-07-22 00:00:00 Z
13
+ date: 2011-07-25 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rdiscount
@@ -38,8 +38,24 @@ files:
38
38
  - lib/generators/chapter11_3/begin/instructions.md
39
39
  - lib/generators/chapter11_3/begin/templates/spec/controllers/pages_controller_11_3_spec.rb
40
40
  - lib/generators/chapter11_3/begin/templates/spec/controllers/microposts_controllers_11_3_spec.rb
41
+ - lib/generators/chapter11_3/begin/templates/spec/models/user_11_3_spec.rb
42
+ - lib/generators/chapter11_3/begin/templates/spec/requests/micropost_11_3_spec.rb
43
+ - lib/generators/chapter11_3/begin/templates/app/views/pages/home.html.erb
44
+ - lib/generators/chapter11_3/begin/templates/app/views/shared/_user_info.html.erb
45
+ - lib/generators/chapter11_3/begin/templates/app/views/shared/_micropost_form.html.erb
46
+ - lib/generators/chapter11_3/begin/templates/app/views/shared/_feed.html.erb
47
+ - lib/generators/chapter11_3/begin/templates/app/views/shared/_feed_item.html.erb
41
48
  - lib/generators/chapter11_3/solutions/USAGE
42
49
  - lib/generators/chapter11_3/solutions/solutions_generator.rb
50
+ - lib/generators/chapter11_3/solutions/templates/app/controllers/microposts_controller.rb
51
+ - lib/generators/chapter11_3/solutions/templates/app/controllers/pages_controller.rb
52
+ - lib/generators/chapter11_3/solutions/templates/app/views/pages/home.html.erb
53
+ - lib/generators/chapter11_3/solutions/templates/app/views/microposts/_micropost.html.erb
54
+ - lib/generators/chapter11_3/solutions/templates/app/views/shared/_user_info.html.erb
55
+ - lib/generators/chapter11_3/solutions/templates/app/views/shared/_error_messages.html.erb
56
+ - lib/generators/chapter11_3/solutions/templates/app/views/shared/_micropost_form.html.erb
57
+ - lib/generators/chapter11_3/solutions/templates/app/views/shared/_feed.html.erb
58
+ - lib/generators/chapter11_3/solutions/templates/app/views/shared/_feed_item.html.erb
43
59
  - lib/generators/chapter07/begin/USAGE
44
60
  - lib/generators/chapter07/begin/begin_generator.rb
45
61
  - lib/generators/chapter07/begin/instructions.md
@@ -127,7 +143,7 @@ files:
127
143
  - lib/generators/chapter10/begin/instructions.md
128
144
  - lib/generators/chapter10/begin/snippets/custom.css
129
145
  - lib/generators/chapter10/begin/snippets/factories.rb
130
- - lib/generators/chapter10/begin/templates/lib/tasks/same_data.rake
146
+ - lib/generators/chapter10/begin/templates/lib/tasks/sample_data.rake
131
147
  - lib/generators/chapter10/begin/templates/spec/controllers/users_controller_10_spec.rb
132
148
  - lib/generators/chapter10/begin/templates/spec/models/user_10_spec.rb
133
149
  - lib/generators/chapter10/begin/templates/app/views/layouts/application.html.erb
@@ -159,15 +175,15 @@ files:
159
175
  - lib/generators/chapter11_1/begin/USAGE
160
176
  - lib/generators/chapter11_1/begin/begin_generator.rb
161
177
  - lib/generators/chapter11_1/begin/instructions.md
162
- - lib/generators/chapter11_1/begin/templates/lib/tasks/same_data.rake
178
+ - lib/generators/chapter11_1/begin/templates/lib/tasks/sample_data.rake
163
179
  - lib/generators/chapter11_1/begin/templates/spec/models/user_11_1_spec.rb
164
180
  - lib/generators/chapter11_1/begin/templates/spec/models/microposts_11_1_spec.rb
165
181
  - lib/generators/chapter11_1/solutions/USAGE
166
182
  - lib/generators/chapter11_1/solutions/solutions_generator.rb
167
183
  - lib/generators/chapter11_1/solutions/snippets/migration_create_microposts.rb
168
184
  - lib/generators/chapter11_1/solutions/templates/spec/factories.rb
169
- - lib/generators/chapter11_1/solutions/templates/app/model/user.rb
170
- - lib/generators/chapter11_1/solutions/templates/app/model/micropost.rb
185
+ - lib/generators/chapter11_1/solutions/templates/app/models/user.rb
186
+ - lib/generators/chapter11_1/solutions/templates/app/models/micropost.rb
171
187
  - LICENSE
172
188
  - Rakefile
173
189
  - Gemfile