kitabu 1.0.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -3
  3. data/.travis.yml +18 -0
  4. data/CHANGELOG.md +9 -0
  5. data/Gemfile.lock +67 -50
  6. data/README.md +235 -0
  7. data/attachments/browser-version.png +0 -0
  8. data/attachments/cover.png +0 -0
  9. data/attachments/kitabu.epub +0 -0
  10. data/attachments/kitabu.mobi +0 -0
  11. data/attachments/kitabu.pdf +0 -0
  12. data/{spec/support/mybook/output → examples/kitabu/output/epub/images}/.gitkeep +0 -0
  13. data/examples/kitabu/output/epub/images/kitabu-icon.png +0 -0
  14. data/examples/kitabu/output/epub/images/kitabu-icon.svg +19 -0
  15. data/examples/kitabu/output/epub/images/kitabu-word.png +0 -0
  16. data/examples/kitabu/output/epub/images/kitabu-word.svg +14 -0
  17. data/examples/kitabu/output/epub/images/kitabu.png +0 -0
  18. data/examples/kitabu/output/epub/images/kitabu.svg +20 -0
  19. data/examples/kitabu/output/epub/section_0.html +266 -0
  20. data/examples/kitabu/output/epub/section_1.html +246 -0
  21. data/examples/kitabu/output/epub/section_2.html +520 -0
  22. data/examples/kitabu/output/epub/section_3.html +282 -0
  23. data/examples/kitabu/output/epub/section_4.html +276 -0
  24. data/examples/kitabu/output/epub/styles/epub.css +437 -0
  25. data/examples/kitabu/output/epub/styles/html.css +712 -0
  26. data/examples/kitabu/output/epub/styles/pdf.css +840 -0
  27. data/examples/kitabu/output/epub/styles/print.css +1278 -0
  28. data/examples/kitabu/output/epub/toc.html +37 -0
  29. data/{spec/support/mybook/templates/epub/style.css → examples/kitabu/output/images/.gitkeep} +0 -0
  30. data/examples/kitabu/output/images/kitabu-icon.png +0 -0
  31. data/examples/kitabu/output/images/kitabu-icon.svg +19 -0
  32. data/examples/kitabu/output/images/kitabu-word.png +0 -0
  33. data/examples/kitabu/output/images/kitabu-word.svg +14 -0
  34. data/examples/kitabu/output/images/kitabu.png +0 -0
  35. data/examples/kitabu/output/images/kitabu.svg +20 -0
  36. data/examples/kitabu/output/kitabu.epub +0 -0
  37. data/examples/kitabu/output/kitabu.html +513 -0
  38. data/examples/kitabu/output/kitabu.mobi +0 -0
  39. data/examples/kitabu/output/kitabu.pdf +0 -0
  40. data/examples/kitabu/output/kitabu.pdf.html +729 -0
  41. data/examples/kitabu/output/kitabu.print.html +729 -0
  42. data/examples/kitabu/output/kitabu.print.pdf +0 -0
  43. data/examples/kitabu/output/kitabu.txt +440 -0
  44. data/examples/kitabu/output/styles/epub.css +437 -0
  45. data/examples/kitabu/output/styles/html.css +712 -0
  46. data/examples/kitabu/output/styles/pdf.css +840 -0
  47. data/examples/kitabu/output/styles/print.css +1278 -0
  48. data/kitabu.gemspec +7 -5
  49. data/lib/kitabu.rb +10 -20
  50. data/lib/kitabu/cli.rb +0 -5
  51. data/lib/kitabu/dependency.rb +0 -4
  52. data/lib/kitabu/exporter.rb +2 -0
  53. data/lib/kitabu/extensions/rouge.rb +9 -0
  54. data/lib/kitabu/generator.rb +9 -21
  55. data/lib/kitabu/helpers.rb +47 -0
  56. data/lib/kitabu/markdown.rb +31 -0
  57. data/lib/kitabu/parser.rb +21 -3
  58. data/lib/kitabu/parser/epub.rb +31 -18
  59. data/lib/kitabu/parser/html.rb +48 -29
  60. data/lib/kitabu/parser/mobi.rb +1 -1
  61. data/lib/kitabu/parser/pdf.rb +52 -8
  62. data/lib/kitabu/version.rb +2 -2
  63. data/spec/kitabu/cli/export_spec.rb +4 -4
  64. data/spec/kitabu/cli/new_spec.rb +2 -2
  65. data/spec/kitabu/markdown_spec.rb +24 -0
  66. data/spec/kitabu/parser/html_spec.rb +20 -25
  67. data/spec/kitabu/parser/mobi_spec.rb +14 -0
  68. data/spec/kitabu/parser/pdf_spec.rb +18 -1
  69. data/spec/kitabu/parser/txt_spec.rb +14 -0
  70. data/spec/spec_helper.rb +10 -6
  71. data/spec/support/mybook/config/helper.rb +4 -29
  72. data/spec/support/mybook/config/kitabu.yml +0 -10
  73. data/spec/support/mybook/templates/epub/cover.erb +4 -3
  74. data/{templates → spec/support/mybook/templates/epub}/cover.png +0 -0
  75. data/spec/support/mybook/templates/epub/page.erb +3 -2
  76. data/spec/support/mybook/templates/html/layout.erb +10 -13
  77. data/spec/support/mybook/templates/styles/epub.scss +3 -0
  78. data/spec/support/mybook/templates/styles/html.scss +3 -0
  79. data/spec/support/mybook/templates/styles/pdf.scss +3 -0
  80. data/spec/support/mybook/templates/styles/print.scss +3 -0
  81. data/spec/support/mybook/text/{01_Markdown_Chapter.markdown → 01_Markdown_Chapter.md} +2 -3
  82. data/spec/support/mybook/text/02_ERB_Chapter.md.erb +7 -0
  83. data/spec/support/mybook/text/{04_With_Directory/Some_Chapter.mkdn → 03_With_Directory/Some_Chapter.md} +0 -0
  84. data/spec/support/mybook/text/{CHANGELOG.textile → CHANGELOG.md} +2 -2
  85. data/spec/support/mybook/text/{TOC.textile → TOC.md} +0 -0
  86. data/spec/support/mybook/text/{_00_Introduction.markdown → _00_Introduction.md} +0 -0
  87. data/spec/support/shared.rb +14 -10
  88. data/templates/Gemfile +3 -3
  89. data/templates/Guardfile +1 -5
  90. data/templates/config.erb +5 -5
  91. data/templates/cover.erb +4 -3
  92. data/templates/epub.erb +3 -2
  93. data/templates/helper.rb +28 -29
  94. data/templates/images/.gitkeep +0 -0
  95. data/templates/images/kitabu-icon.png +0 -0
  96. data/templates/images/kitabu-icon.svg +19 -0
  97. data/templates/images/kitabu-word.png +0 -0
  98. data/templates/images/kitabu-word.svg +14 -0
  99. data/templates/images/kitabu.png +0 -0
  100. data/templates/images/kitabu.svg +20 -0
  101. data/{examples/RailsGuides/templates → templates/templates/epub}/cover.erb +4 -3
  102. data/templates/templates/epub/cover.png +0 -0
  103. data/templates/templates/epub/page.erb +16 -0
  104. data/templates/{layout.erb → templates/html/layout.erb} +22 -11
  105. data/templates/templates/styles/epub.scss +1 -0
  106. data/templates/templates/styles/files/_normalize.scss +427 -0
  107. data/templates/templates/styles/html.scss +252 -0
  108. data/templates/templates/styles/pdf.scss +371 -0
  109. data/templates/templates/styles/print.scss +2 -0
  110. data/templates/text/01_Getting_Started.md +26 -0
  111. data/templates/text/02_Creating_Chapters.md +22 -0
  112. data/templates/text/03_Syntax_Highlighting.erb +69 -0
  113. data/templates/text/04_Dynamic_Content.erb +64 -0
  114. data/templates/text/05_Exporting_Files.md +49 -0
  115. metadata +143 -83
  116. data/README.rdoc +0 -218
  117. data/examples/RailsGuides/config/helper.rb +0 -29
  118. data/examples/RailsGuides/config/kitabu.yml +0 -44
  119. data/examples/RailsGuides/images/challenge.png +0 -0
  120. data/examples/RailsGuides/images/posts_index.png +0 -0
  121. data/examples/RailsGuides/images/rails_welcome.png +0 -0
  122. data/examples/RailsGuides/output/RailsGuides.epub +0 -0
  123. data/examples/RailsGuides/output/RailsGuides.html +0 -1556
  124. data/examples/RailsGuides/output/RailsGuides.pdf +3 -4934
  125. data/examples/RailsGuides/templates/layout.css +0 -352
  126. data/examples/RailsGuides/templates/layout.erb +0 -43
  127. data/examples/RailsGuides/templates/syntax.css +0 -62
  128. data/examples/RailsGuides/templates/user.css +0 -19
  129. data/examples/RailsGuides/text/01_Guide_Assumptions.mkdn +0 -13
  130. data/examples/RailsGuides/text/02_What_is_Rails.mkdn +0 -106
  131. data/examples/RailsGuides/text/03_Creating_a_new_Rails_project.mkdn +0 -200
  132. data/examples/RailsGuides/text/04_Hello_Rails.mkdn +0 -62
  133. data/examples/RailsGuides/text/05_Getting_Up_and_Running_Quickly_with_Scaffolding.mkdn +0 -4
  134. data/examples/RailsGuides/text/06_Creating_a_resource.mkdn +0 -503
  135. data/examples/RailsGuides/text/07_Adding_a_second_model.mkdn +0 -232
  136. data/examples/RailsGuides/text/08_Refactoring.mkdn +0 -123
  137. data/examples/RailsGuides/text/09_Deleting_comments.mkdn +0 -57
  138. data/examples/RailsGuides/text/09_Security.mkdn +0 -56
  139. data/examples/RailsGuides/text/10_Building_a_multi_model_form.mkdn +0 -130
  140. data/examples/RailsGuides/text/11_View_helpers.mkdn +0 -50
  141. data/examples/RailsGuides/text/12_Whats_next.mkdn +0 -14
  142. data/examples/RailsGuides/text/13_Configuration_gotchas.mkdn +0 -10
  143. data/lib/kitabu/adapters/markdown.rb +0 -34
  144. data/lib/kitabu/extensions/redcloth.rb +0 -69
  145. data/lib/kitabu/syntax.rb +0 -130
  146. data/spec/kitabu/extensions/redcloth_spec.rb +0 -57
  147. data/spec/kitabu/syntax_spec.rb +0 -106
  148. data/spec/support/mybook/templates/html/layout.css +0 -353
  149. data/spec/support/mybook/templates/html/syntax.css +0 -58
  150. data/spec/support/mybook/templates/html/user.css +0 -1
  151. data/spec/support/mybook/text/02_Textile_Chapter.textile +0 -3
  152. data/spec/support/mybook/text/03_HTML_Chapter.html +0 -3
  153. data/templates/epub.css +0 -500
  154. data/templates/layout.css +0 -353
  155. data/templates/sample.md +0 -6
  156. data/templates/syntax.css +0 -58
  157. data/templates/user.css +0 -1
@@ -1,232 +0,0 @@
1
- ## Adding a Second Model
2
-
3
- Now that you’ve seen how a model built with scaffolding looks like, it’s time to add a second model to the application. The second model will handle comments on blog posts.
4
-
5
- ### Generating a Model
6
-
7
- Models in Rails use a singular name, and their corresponding database tables use a plural name. For the model to hold comments, the convention is to use the name Comment. Even if you don’t want to use the entire apparatus set up by scaffolding, most Rails developers still use generators to make things like models and controllers. To create the new model, run this command in your terminal:
8
-
9
- $ rails generate model Comment commenter:string body:text post:references
10
-
11
- This command will generate four files:
12
-
13
- * `app/models/comment.rb` – The model
14
- * `db/migrate/20100207235629_create_comments.rb` – The migration
15
- * `test/unit/comment_test.rb and test/fixtures/comments.yml` – The test harness.
16
-
17
- First, take a look at `comment.rb`:
18
-
19
- @@@ ruby
20
- class Comment < ActiveRecord::Base
21
-   belongs_to :post
22
- end
23
- @@@
24
-
25
- This is very similar to the `post.rb` model that you saw earlier. The difference is the line `belongs_to :post`, which sets up an Active Record *association*. You’ll learn a little about associations in the next section of this guide.
26
-
27
- In addition to the model, Rails has also made a migration to create the corresponding database table:
28
-
29
- @@@ ruby
30
- class CreateComments < ActiveRecord::Migration
31
-   def self.up
32
-     create_table :comments do |t|
33
-       t.string :commenter
34
-       t.text :body
35
-       t.references :post
36
-
37
-       t.timestamps
38
-     end
39
-   end
40
-
41
-   def self.down
42
-     drop_table :comments
43
-   end
44
- end
45
- @@@
46
-
47
- The `t.references` line sets up a foreign key column for the association between the two models. Go ahead and run the migration:
48
-
49
- $ rake db:migrate
50
-
51
- Rails is smart enough to only execute the migrations that have not already been run against the current database, so in this case you will just see:
52
-
53
- ==  CreateComments: migrating ============
54
- -- create_table(:comments)
55
-    -> 0.0017s
56
- ==  CreateComments: migrated (0.0018s) ===
57
-
58
- ### Associating Models
59
-
60
- Active Record associations let you easily declare the relationship between two models. In the case of comments and posts, you could write out the relationships this way:
61
-
62
- * Each comment belongs to one post
63
- * One post can have many comments
64
-
65
- In fact, this is very close to the syntax that Rails uses to declare this association. You’ve already seen the line of code inside the Comment model that makes each comment belong to a Post:
66
-
67
- @@@ ruby
68
- class Comment < ActiveRecord::Base
69
-   belongs_to :post
70
- end
71
- @@@
72
-
73
- You’ll need to edit the `post.rb` file to add the other side of the association:
74
-
75
- @@@ ruby
76
- class Post < ActiveRecord::Base
77
-   validates :name,  :presence => true
78
-   validates :title, :presence => true,
79
-                     :length => { :minimum => 5 }
80
-
81
-   has_many :comments
82
- end
83
- @@@
84
-
85
- These two declarations enable a good bit of automatic behavior. For example, if you have an instance variable `@post` containing a post, you can retrieve all the comments belonging to that post as the array `@post.comments`.
86
-
87
- <p class="notice">
88
- For more information on Active Record associations, see the <a href="http://guides.rubyonrails.org/association_basics.html" title="Ruby on Rails Guides: A Guide to Active Record Associations">Active Record Associations</a> guide.
89
- </p>
90
-
91
- ### Adding a Route for Comments
92
-
93
- As with the `home` controller, we will need to add a route so that Rails knows where we would like to navigate to see `comments`. Open up the `config/routes.rb` file again, you will see an entry that was added automatically for posts near the top by the scaffold generator, `resources :posts`, edit it as follows:
94
-
95
- @@@ ruby
96
- resources :posts do
97
-   resources :comments
98
- end
99
- @@@
100
-
101
- This creates `comments` as a *nested resource* within `posts`. This is another part of capturing the hierarchical relationship that exists between posts and comments.
102
-
103
- <p class="notice">
104
- For more information on routing, see the <a href="http://guides.rubyonrails.org/routing.html" title="Ruby on Rails Guides: Rails Routing from the Outside In">Rails Routing from the Outside In</a> guide.
105
- </p>
106
-
107
- ### Generating a Controller
108
-
109
- With the model in hand, you can turn your attention to creating a matching controller. Again, there’s a generator for this:
110
-
111
- $ rails generate controller Comments
112
-
113
- This creates four files and one empty directory:
114
-
115
- * `app/controllers/comments_controller.rb` – The controller
116
- * `app/helpers/comments_helper.rb` – A view helper file
117
- * `test/functional/comments_controller_test.rb` – The functional tests for the controller
118
- * `test/unit/helpers/comments_helper_test.rb` – The unit tests for the helper
119
- * `app/views/comments/` – Views of the controller are stored here
120
-
121
- Like with any blog, our readers will create their comments directly after reading the post, and once they have added their comment, will be sent back to the post show page to see their comment now listed. Due to this, our `CommentsController` is there to provide a method to create comments and delete SPAM comments when they arrive.
122
-
123
- So first, we’ll wire up the Post show template (`/app/views/posts/show.html.erb`) to let us make a new comment:
124
-
125
- @@@ html
126
- <p class="notice"><%= notice %></p>
127
-
128
- <p>
129
-   <b>Name:</b>
130
-   <%= @post.name %>
131
- </p>
132
-
133
- <p>
134
-   <b>Title:</b>
135
-   <%= @post.title %>
136
- </p>
137
-
138
- <p>
139
-   <b>Content:</b>
140
-   <%= @post.content %>
141
- </p>
142
-
143
- <h2>Add a comment:</h2>
144
- <%= form_for([@post, @post.comments.build]) do |f| %>
145
-   <div class="field">
146
-     <%= f.label :commenter %><br />
147
-     <%= f.text_field :commenter %>
148
-   </div>
149
-   <div class="field">
150
-     <%= f.label :body %><br />
151
-     <%= f.text_area :body %>
152
-   </div>
153
-   <div class="actions">
154
-     <%= f.submit %>
155
-   </div>
156
- <% end %>
157
-
158
- <%= link_to 'Edit Post', edit_post_path(@post) %> |
159
- <%= link_to 'Back to Posts', posts_path %> |
160
- @@@
161
-
162
- This adds a form on the Post show page that creates a new comment, which will call the `CommentsController` create action, so let’s wire that up:
163
-
164
- @@@ ruby
165
- class CommentsController < ApplicationController
166
-   def create
167
-     @post = Post.find(params[:post_id])
168
-     @comment = @post.comments.create(params[:comment])
169
-     redirect_to post_path(@post)
170
-   end
171
- end
172
- @@@
173
-
174
- You’ll see a bit more complexity here than you did in the controller for posts. That’s a side-effect of the nesting that you’ve set up; each request for a comment has to keep track of the post to which the comment is attached, thus the initial find action to the Post model to get the post in question.
175
-
176
- In addition, the code takes advantage of some of the methods available for an association. We use the `create` method on `@post.comments` to create and save the comment. This will automatically link the comment so that it belongs to that particular post.
177
-
178
- Once we have made the new comment, we send the user back to the original post using the `post_path(@post)` helper. As we have already seen, this calls the `show` action of the `PostsController` which in turn renders the `show.html.erb` template. This is where we want the comment to show, so let’s add that to the `app/views/posts/show.html.erb`.
179
-
180
- @@@ html
181
- <p class="notice"><%= notice %></p>
182
-
183
- <p>
184
-   <b>Name:</b>
185
-   <%= @post.name %>
186
- </p>
187
-
188
- <p>
189
-   <b>Title:</b>
190
-   <%= @post.title %>
191
- </p>
192
-
193
- <p>
194
-   <b>Content:</b>
195
-   <%= @post.content %>
196
- </p>
197
-
198
- <h2>Comments</h2>
199
- <% @post.comments.each do |comment| %>
200
-   <p>
201
-     <b>Commenter:</b>
202
-     <%= comment.commenter %>
203
-   </p>
204
-
205
-   <p>
206
-     <b>Comment:</b>
207
-     <%= comment.body %>
208
-   </p>
209
- <% end %>
210
-
211
- <h2>Add a comment:</h2>
212
- <%= form_for([@post, @post.comments.build]) do |f| %>
213
-   <div class="field">
214
-     <%= f.label :commenter %><br />
215
-     <%= f.text_field :commenter %>
216
-   </div>
217
-   <div class="field">
218
-     <%= f.label :body %><br />
219
-     <%= f.text_area :body %>
220
-   </div>
221
-   <div class="actions">
222
-     <%= f.submit %>
223
-   </div>
224
- <% end %>
225
-
226
- <br />
227
-
228
- <%= link_to 'Edit Post', edit_post_path(@post) %> |
229
- <%= link_to 'Back to Posts', posts_path %> |
230
- @@@
231
-
232
- Now you can add posts and comments to your blog and have them show up in the right places.
@@ -1,123 +0,0 @@
1
- ## Refactoring
2
-
3
- Now that we have Posts and Comments working, if we take a look at the `app/views/posts/show.html.erb` template, it’s getting long and awkward. We can use partials to clean this up.
4
-
5
- ### Rendering Partial Collections
6
-
7
- First we will make a comment partial to extract showing all the comments for the post. Create the file `app/views/comments/_comment.html.erb` and put the following into it:
8
-
9
- @@@ html
10
- <p>
11
-   <b>Commenter:</b>
12
-   <%= comment.commenter %>
13
- </p>
14
-
15
- <p>
16
-   <b>Comment:</b>
17
-   <%= comment.body %>
18
- </p>
19
- @@@
20
-
21
- Then in the `app/views/posts/show.html.erb` you can change it to look like the following:
22
-
23
- @@@ html
24
- <p class="notice"><%= notice %></p>
25
-
26
- <p>
27
-   <b>Name:</b>
28
-   <%= @post.name %>
29
- </p>
30
-
31
- <p>
32
-   <b>Title:</b>
33
-   <%= @post.title %>
34
- </p>
35
-
36
- <p>
37
-   <b>Content:</b>
38
-   <%= @post.content %>
39
- </p>
40
-
41
- <h2>Comments</h2>
42
- <%= render :partial => "comments/comment",
43
-            :collection => @post.comments %>
44
-
45
- <h2>Add a comment:</h2>
46
- <%= form_for([@post, @post.comments.build]) do |f| %>
47
-   <div class="field">
48
-     <%= f.label :commenter %><br />
49
-     <%= f.text_field :commenter %>
50
-   </div>
51
-   <div class="field">
52
-     <%= f.label :body %><br />
53
-     <%= f.text_area :body %>
54
-   </div>
55
-   <div class="actions">
56
-     <%= f.submit %>
57
-   </div>
58
- <% end %>
59
-
60
- <br />
61
-
62
- <%= link_to 'Edit Post', edit_post_path(@post) %> |
63
- <%= link_to 'Back to Posts', posts_path %> |
64
- @@@
65
-
66
- This will now render the partial in `app/views/comments/_comment.html.erb` once for each comment that is in the `@post.comments collection`. As the render method iterates over the `@post.comments` collection, it assigns each comment to a local variable named the same as the partial, in this case comment which is then available in the partial for us to show.
67
-
68
- ### Rendering a Partial Form
69
-
70
- Lets also move that new comment section out to it’s own partial, again, you create a file `app/views/comments/_form.html.erb` and in it you put:
71
-
72
- @@@ html
73
- <%= form_for([@post, @post.comments.build]) do |f| %>
74
-   <div class="field">
75
-     <%= f.label :commenter %><br />
76
-     <%= f.text_field :commenter %>
77
-   </div>
78
-   <div class="field">
79
-     <%= f.label :body %><br />
80
-     <%= f.text_area :body %>
81
-   </div>
82
-   <div class="actions">
83
-     <%= f.submit %>
84
-   </div>
85
- <% end %>
86
- @@@
87
-
88
- Then you make the `app/views/posts/show.html.erb` look like the following:
89
-
90
- @@@ html
91
- <p class="notice"><%= notice %></p>
92
-
93
- <p>
94
-   <b>Name:</b>
95
-   <%= @post.name %>
96
- </p>
97
-
98
- <p>
99
-   <b>Title:</b>
100
-   <%= @post.title %>
101
- </p>
102
-
103
- <p>
104
-   <b>Content:</b>
105
-   <%= @post.content %>
106
- </p>
107
-
108
- <h2>Comments</h2>
109
- <%= render :partial => "comments/comment",
110
-            :collection => @post.comments %>
111
-
112
- <h2>Add a comment:</h2>
113
- <%= render "comments/form" %>
114
-
115
- <br />
116
-
117
- <%= link_to 'Edit Post', edit_post_path(@post) %> |
118
- <%= link_to 'Back to Posts', posts_path %> |
119
- @@@
120
-
121
- The second render just defines the partial template we want to render, `comments/form`, Rails is smart enough to spot the forward slash in that string and realize that you want to render the `_form.html.erb` file in the `app/views/comments` directory.
122
-
123
- The `@post` object is available to any partials rendered in the view because we defined it as an instance variable.
@@ -1,57 +0,0 @@
1
- ## Deleting Comments
2
-
3
- Another important feature on a blog is being able to delete SPAM comments. To do this, we need to implement a link of some sort in the view and a `DELETE` action in the `CommentsController`.
4
-
5
- So first, let’s add the delete link in the `app/views/comments/_comment.html.erb` partial:
6
-
7
- @@@ html
8
- <p>
9
-   <b>Commenter:</b>
10
-   <%= comment.commenter %>
11
- </p>
12
-
13
- <p>
14
-   <b>Comment:</b>
15
-   <%= comment.body %>
16
- </p>
17
-
18
- <p>
19
-   <%= link_to 'Destroy Comment', [comment.post, comment],
20
-                :confirm => 'Are you sure?',
21
-                :method => :delete %>
22
- </p>
23
- @@@
24
-
25
- Clicking this new “Destroy Comment” link will fire off a `DELETE /posts/:id/comments/:id` to our `CommentsController`, which can then use this to find the comment we want to delete, so let’s add a `destroy` action to our controller:
26
-
27
- @@@ ruby
28
- class CommentsController < ApplicationController
29
-   def create
30
-     @post = Post.find(params[:post_id])
31
-     @comment = @post.comments.create(params[:comment])
32
-     redirect_to post_path(@post)
33
-   end
34
-
35
-   def destroy
36
-     @post = Post.find(params[:post_id])
37
-     @comment = @post.comments.find(params[:id])
38
-     @comment.destroy
39
-     redirect_to post_path(@post)
40
-   end
41
- end
42
- @@@
43
-
44
- The `destroy` action will find the post we are looking at, locate the comment within the `@post.comments` collection, and then remove it from the database and send us back to the `show` action for the post.
45
-
46
- ### Deleting Associated Objects
47
-
48
- If you delete a post then its associated comments will also need to be deleted. Otherwise they would simply occupy space in the database. Rails allows you to use the `dependent` option of an association to achieve this. Modify the `Post` model, `app/models/post.rb`, as follows:
49
-
50
- @@@ ruby
51
- class Post < ActiveRecord::Base
52
-   validates :name,  :presence => true
53
-   validates :title, :presence => true,
54
-                     :length => { :minimum => 5 }
55
-   has_many :comments, :dependent => :destroy
56
- end
57
- @@@
@@ -1,56 +0,0 @@
1
- ## Security
2
-
3
- If you were to publish your blog online, anybody would be able to add, edit and delete posts or delete comments.
4
-
5
- Rails provides a very simple HTTP authentication system that will work nicely in this situation. First, we enable simple HTTP based authentication in our `app/controllers/application_controller.rb`:
6
-
7
- @@@ ruby
8
- class ApplicationController < ActionController::Base
9
-   protect_from_forgery
10
-
11
-   private
12
-
13
-   def authenticate
14
-     authenticate_or_request_with_http_basic do |user_name, password|
15
-       user_name == 'admin' && password == 'password'
16
-     end
17
-   end
18
- end
19
- @@@
20
-
21
- You can obviously change the username and password to whatever you want. We put this method inside of `ApplicationController` so that it is available to all of our controllers.
22
-
23
- Then in the `PostsController` we need to have a way to block access to the various actions if the person is not authenticated, here we can use the Rails `before_filter` method, which allows us to specify that Rails must run a method and only then allow access to the requested action if that method allows it.
24
-
25
- To use the before filter, we specify it at the top of our `PostsController`, in this case, we want the user to be authenticated on every action, except for `index` and `show`, so we write that:
26
-
27
- @@@ ruby
28
- class PostsController < ApplicationController
29
-
30
-   before_filter :authenticate, :except => [:index, :show]
31
-
32
-   # GET /posts
33
-   # GET /posts.xml
34
-   def index
35
-     @posts = Post.all
36
-     respond_to do |format|
37
- # snipped for brevity
38
- @@@
39
-
40
- <p class="figure">
41
- <img src="../images/challenge.png" alt="Basic Auth challenge window" />
42
- </p>
43
-
44
- We also only want to allow authenticated users to delete comments, so in the `CommentsController` we write:
45
-
46
- @@@ ruby
47
- class CommentsController < ApplicationController
48
-
49
-   before_filter :authenticate, :only => :destroy
50
-
51
-   def create
52
-     @post = Post.find(params[:post_id])
53
- # snipped for brevity
54
- @@@
55
-
56
- Now if you try to create a new post, you will be greeted with a basic HTTP Authentication challenge.