wbzyl-rails3-tutorial 0.0.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 (48) hide show
  1. data/README.markdown +14 -0
  2. data/Rakefile +34 -0
  3. data/TODO +6 -0
  4. data/VERSION.yml +4 -0
  5. data/config.ru +15 -0
  6. data/lib/config.ru +12 -0
  7. data/lib/public/images/bradypus.jpg +0 -0
  8. data/lib/public/images/leniwce_controller.png +0 -0
  9. data/lib/public/images/leniwce_controller.svg +284 -0
  10. data/lib/public/images/leniwiec.png +0 -0
  11. data/lib/public/images/leniwiec.svg +284 -0
  12. data/lib/public/images/mvc.png +0 -0
  13. data/lib/public/images/mvc.svg +243 -0
  14. data/lib/public/images/pablo_picasso.jpg +0 -0
  15. data/lib/public/images/pastie.png +0 -0
  16. data/lib/public/images/rails3.png +0 -0
  17. data/lib/public/images/rails3.svg +125 -0
  18. data/lib/public/images/the_thinker.jpg +0 -0
  19. data/lib/public/javascripts/ruby3.js +1 -0
  20. data/lib/public/stylesheets/icons/doc.png +0 -0
  21. data/lib/public/stylesheets/icons/email.png +0 -0
  22. data/lib/public/stylesheets/icons/external.png +0 -0
  23. data/lib/public/stylesheets/icons/feed.png +0 -0
  24. data/lib/public/stylesheets/icons/im.png +0 -0
  25. data/lib/public/stylesheets/icons/pdf.png +0 -0
  26. data/lib/public/stylesheets/icons/visited.png +0 -0
  27. data/lib/public/stylesheets/icons/xls.png +0 -0
  28. data/lib/public/stylesheets/ie.css +27 -0
  29. data/lib/public/stylesheets/print.css +30 -0
  30. data/lib/public/stylesheets/rails3.css +139 -0
  31. data/lib/public/stylesheets/screen.css +249 -0
  32. data/lib/public/stylesheets/src/grid.png +0 -0
  33. data/lib/public/stylesheets/uv.css +121 -0
  34. data/lib/rails3-tutorial.rb +72 -0
  35. data/lib/views/answers.rdiscount +0 -0
  36. data/lib/views/authentication.rdiscount +10 -0
  37. data/lib/views/blog.rdiscount +365 -0
  38. data/lib/views/caching.rdiscount +4 -0
  39. data/lib/views/exercises.rdiscount +67 -0
  40. data/lib/views/fortune.rdiscount +592 -0
  41. data/lib/views/intro.rdiscount +68 -0
  42. data/lib/views/layout.rdiscount +38 -0
  43. data/lib/views/main.rdiscount +32 -0
  44. data/lib/views/pastie.rdiscount +371 -0
  45. data/lib/views/store.rdiscount +99 -0
  46. data/lib/views/todo.rdiscount +245 -0
  47. data/rails3-tutorial.gemspec +101 -0
  48. metadata +168 -0
@@ -0,0 +1,68 @@
1
+ #### {% title "Rozkład jazdy" %}
2
+
3
+
4
+ # Wykłady
5
+
6
+ 1. Fortunka
7
+ 2. Wprowadzenie do języka Ruby
8
+ 3. Pastie
9
+ 4. Może Sinatra?
10
+ 5. …
11
+ 6. Aplikacje z dwoma modelami.
12
+
13
+
14
+ ## Uwagi o przykładach
15
+
16
+ Zaczynamy od przerobienia *Fortunki* na aplikację Rails.
17
+ Fortunka to aplikacja z jednym modelem.
18
+ REST.
19
+
20
+ Następnie piszemy klon *Pastie*.
21
+ Też tylko jeden model.
22
+ Bez REST.
23
+
24
+ *Blog*, *Todo*, *Hurtownia* to aplikacje z dwoma modelami. Autorem
25
+ tych aplikacji jest Ryan Bates. Są one wykorzystywane w jego
26
+ [screencastach](http://railscasts.com/). Kod przykładów oraz
27
+ kod screencastów znajdują się na serwerze
28
+ [Github](http://github.com/ryanb).
29
+
30
+
31
+ ## Najważniejsze gemy i wtyczki
32
+
33
+ 1. Mislav Marohnić, gem
34
+ [will_paginate](http://github.com/mislav/will_paginate/).
35
+ Most awesome pagination solution for Ruby.
36
+ 2. Ben Johnsos, gem
37
+ [Authlogic](http://github.com/binarylogic/authlogic/).
38
+ A clean, simple, and unobtrusive ruby authentication solution.
39
+ 3. Jon Yurek, gem
40
+ [paperclip](http://github.com/thoughtbot/paperclip/),
41
+ [strona domowa](http://www.thoughtbot.com/projects/paperclip).
42
+ Easy file attachment management for ActiveRecord.
43
+ 4. Mike Perham, plugin
44
+ [Exception Notifier](http://github.com/rails/exception_notification/).
45
+ Exception Notifier for Rails.
46
+ 5. Jeremy Kemper, plugin
47
+ [Acts As List](http://github.com/rails/acts_as_list/).
48
+ Provides the capabilities for sorting and reordering a number of
49
+ objects in a list.
50
+
51
+
52
+ ## Różne
53
+
54
+ 1. [JavaScript and CSS Asset Compression
55
+ for Production Rails Apps](http://github.com/sbecker/asset_packager/)
56
+ 2. [Real HTTP Caching for Ruby Web Apps](http://github.com/rtomayko/rack-cache/)
57
+ 3. Generatory.
58
+ [*A collection of useful Rails generator scripts*](http://github.com/ryanb/nifty-generators/)
59
+
60
+
61
+ ## TODO
62
+
63
+ Więcej przykładów:
64
+
65
+ 1. Z jednym modelem, np. *Tatry + Google maps*.
66
+ 2. Z więcej niż dwoma modelami, np. *Ale Kino*.
67
+ 3. Wyszukiwanie w bazie:
68
+ Xapian + gem [Xapit](http://github.com/ryanb/xapit).
@@ -0,0 +1,38 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
5
+
6
+ <%= stylesheet_link_tag "/stylesheets/screen.css", "/stylesheets/uv.css", "/stylesheets/rails3.css" %>
7
+ <%= stylesheet_link_tag "/stylesheets/print.css", :media => "print" %>
8
+ <!--[if IE]>
9
+ <%= stylesheet_link_tag "css/blueprint/ie.css" %>
10
+ <![endif]-->
11
+
12
+ <title><%= @title %></title>
13
+ </head>
14
+ <body>
15
+ <div class="span-21" id="header">
16
+ <div class="push-1 span-7">
17
+ <a href="/"><%= image_tag "/images/rails3.png", :alt => "[WB/Ruby logo]" %></a>
18
+ </div>
19
+ <div class="span-13 last">
20
+ <div class="append-1" id="links">
21
+ <a href="http://wbzyl.ug.edu.pl/">home</a>
22
+ <a href="http://wbzyl.ug.edu.pl/galeria">galeria</a>
23
+ </div>
24
+ </div>
25
+ </div>
26
+
27
+ <div class="span-21 container"><!-- showgrid -->
28
+ <div class="push-1 span-12" id="content">
29
+
30
+ <%= yield %>
31
+
32
+ </div>
33
+ <div class="span-8 last">
34
+ </div>
35
+ </div>
36
+
37
+ </body>
38
+ </html>
@@ -0,0 +1,32 @@
1
+ #### {% title %} – set the default title
2
+
3
+ # Samouczek
4
+
5
+ <blockquote>
6
+ {%= image_tag "/images/the_thinker.jpg", :alt => "[The Thinker]" %}
7
+ <p>There's no sense in being precise when you don't even know what
8
+ you're talking about.</p>
9
+ <p class="author">— John von Neumann</p>
10
+ </blockquote>
11
+
12
+ 1. {%= link_to "Rozkład jazdy", "/intro" %}
13
+ 1. {%= link_to "Hello Fortune", "/fortune" %}
14
+ 1. {%= link_to "Klon Pastie w Rails3 + ActiveRecord", "/pastie" %}
15
+ 1. {%= link_to "Aplikacja: Todo", "/todo" %}
16
+ 1. {%= link_to "Aplikacja: Blog", "/blog" %}
17
+ 1. {%= link_to "Aplikacja: Store", "/store" %}
18
+ 1. {%= link_to "Autentykacja i autoryzacja", "/authentication" %}
19
+ 1. {%= link_to "Caching", "/caching" %}
20
+ 1. {%= link_to "Ćwiczenia", "/exercises" %}
21
+ 1. {%= link_to "Odpowiedzi", "/answers" %}
22
+
23
+ ## Dokumentacja
24
+
25
+ Na początek zaczynamy od przestudiownaia
26
+ [Rails Guides](http://guides.rubyonrails.org/):
27
+
28
+ 1. [Getting Started with Rails](http://guides.rubyonrails.org/getting_started.html)
29
+ 2. [Active Record Query Interface](http://guides.rubyonrails.org/active_record_querying.html)
30
+ 3. [Rails Form helpers](http://guides.rubyonrails.org/form_helpers.html)
31
+ 4. Dalej już według własnego uznania,
32
+ wybieramy kolejny *Przewodnik* do przestudiowania
@@ -0,0 +1,371 @@
1
+ #### {% title "Leniwiec z o.o." %}
2
+
3
+ # Pastie „Leniwiec z o.o.”
4
+
5
+ <blockquote>
6
+ {%= image_tag "/images/bradypus.jpg",
7
+ :alt => "[Bradypus tridactylus]", :title => "Bradypus tridactylus" %}
8
+ </blockquote>
9
+
10
+ To klon Pastie napisany w Rails 3 + ActiveRecord.
11
+
12
+ Czym jest „pastie”? Oto przykłady:
13
+
14
+ * [pastie](http://pastie.org/)
15
+ * [pastebin](http://pastebin.com/)
16
+
17
+ Jak stworzyć klona pastie w Sinatrze + Datamapper
18
+ opisał Nick Plante, [Clone Pastie with Sinatra & DataMapper
19
+ 0.9](http://blog.zerosum.org/2008/7/2/clone-pastie-with-sinatra-datamapper-redux).
20
+
21
+ Nasz „Leniwiec” ma umożliwiać wklejanie
22
+ fragmentów kodu. Kod będziemy wklejać do formularza
23
+ z przyciskiem „Wklej”.
24
+ Po kliknięciu tego przycisku, wklejony kod
25
+ zapisujemy w tabelce i przekierowujemy się na stronę
26
+ z wklejonym kodem, na przykład:
27
+
28
+ http://leniwiec.local:3000/128
29
+
30
+ Od tej chwili, po wsze czasy (no, dopóty, dopóki nie padnie dysk na
31
+ *mancie*), wklejony kod będzie dostępny pod tym URL.
32
+
33
+ W następnej wersji dodamy do każdej strony formularz umożliwiający
34
+ wyszukiwanie wklejonych fragmentów kodu zawierających podaną frazę.
35
+
36
+ A tak wygląda strona główna *pastie.org*:
37
+
38
+ {%= image_tag "/images/pastie.png", :alt => "[http://pastie.org]" %}
39
+
40
+
41
+ **Zaczynamy** od wygenerowania rusztowanie aplikacji:
42
+
43
+ rails leniwiec.local
44
+
45
+ Oraz nauczenia Railsów odmiany słowa *leniwiec*.
46
+ W pliku *inflections.rb* wpisujemy:
47
+
48
+ :::ruby
49
+ ActiveSupport::Inflector.inflections do |inflect|
50
+ inflect.irregular 'leniwiec', 'leniwce'
51
+ end
52
+
53
+ ## Projektujemy routing
54
+
55
+ <blockquote>
56
+ {%= image_tag "/images/mvc.png", :alt => "[MVC]" %}
57
+ </blockquote>
58
+
59
+ Cytat: „The routing *ActionController::Routing* module provides URL rewriting
60
+ in native Ruby. It’s a way to redirect incoming requests to
61
+ controllers and actions. This replaces *mod_rewrite* rules. Best of all,
62
+ Rails' Routing works with any web server. Routes are defined in
63
+ *config/routes.rb*.”
64
+ \[[więcej](http://apidock.com/rails/ActionController/Routing)\]
65
+
66
+ Strona główna:
67
+
68
+ http://leniwiec.local:3000/
69
+
70
+ Wklejone fragmenty kodu:
71
+
72
+ http://leniwiec.local:3000/:number
73
+
74
+ Wyszukiwanie:
75
+
76
+ http://leniwiec.local:3000/search?query=def
77
+
78
+ Wyniki:
79
+
80
+ http://leniwiec.local:3000/search
81
+
82
+ Routing:
83
+
84
+ :::ruby
85
+ # root_path, root_url
86
+ map.root :conditions => { :method => :get },
87
+ :controller => 'leniwce',
88
+ :action => 'index'
89
+
90
+ # leniwce_url(:number)
91
+ map.leniwce ':number',
92
+ :conditions => { :method => :get },
93
+ :controller => 'leniwce',
94
+ :action => 'show',
95
+ :number => /\d+/
96
+
97
+ # create_path
98
+ map.create '',
99
+ :conditions => { :method => :post },
100
+ :controller => 'leniwce',
101
+ :action => 'create'
102
+
103
+ # search_path
104
+ map.search 'search',
105
+ :conditions => { :method => :get },
106
+ :controller => 'leniwce',
107
+ :action => 'search'
108
+
109
+ Generujemy model i migrujemy:
110
+
111
+ <blockquote>
112
+ {%= image_tag "/images/leniwiec.png", :alt => "[leniwiec.rb]" %}
113
+ </blockquote>
114
+
115
+ script/generate model Leniwiec lang:string body:text
116
+ rake db:migrate
117
+
118
+ Generujemy kontroller:
119
+
120
+ script/generate controller Leniwce index show search
121
+
122
+ Dopiero teraz możemy obejrzeć routing:
123
+
124
+ rake routes
125
+
126
+ I próbnie uruchomić aplikację.
127
+
128
+ Co działa? A co nie działa? Wpisujemy kilka URL.
129
+ Przyglądamy się temu co jest wypisywane na konsoli.
130
+
131
+
132
+ ## Jazda obowiązkowa: ćwiczenia na konsoli
133
+
134
+ <blockquote>
135
+ {%= image_tag "/images/mvc.png", :alt => "[MVC]" %}
136
+ </blockquote>
137
+
138
+ Przykłady do wpisania na konsoli SQlite, `script/dbconsole`:
139
+
140
+ :::sql
141
+ insert into leniwce (lang, body)
142
+ values("ruby", "puts 1");
143
+ insert into leniwce (lang, body)
144
+ values("html", "<html></html>");
145
+
146
+ I – na konsoli Rails, `script/console`:
147
+
148
+ :::sql_rails
149
+ Leniwiec.all
150
+ Leniwiec.all(:conditions => ["lang = ?", "ruby"])
151
+ Leniwiec.all(:conditions =>
152
+ ["lang = ? and body like ?", "ruby", "%puts%"])
153
+
154
+ Więcej przykładowych poleceń jest do wklejenia
155
+ [stąd](http://apidock.com/rails/ActiveRecord/Base)
156
+
157
+ :::sql_rails
158
+ w = Leniwiec.new :lang => "css",
159
+ :body => "h1 { color: red; }"
160
+ w.save
161
+
162
+ Leniwiec.create :lang => "css",
163
+ :body => "h1 { background-color: blue; }"
164
+
165
+
166
+ ## Widoki
167
+
168
+ <blockquote>
169
+ {%= image_tag "/images/mvc.png", :alt => "[MVC]" %}
170
+ </blockquote>
171
+
172
+ Zaczynamy od widoku *index.html.erb* z formularzem do wklejania kodu:
173
+
174
+ :::html_rails
175
+ <% form_for :leniwiec, :url => {
176
+ :controller => "leniwce",
177
+ :action => "create" } do |f| %>
178
+ <%= f.error_messages %>
179
+ <p>
180
+ <%= f.label :lang, "Wybierz język" %><br />
181
+ <%= f.select :lang, @languages %>
182
+ </p>
183
+ <p>
184
+ <%= f.label :body, "Wklej kod:" %><br />
185
+ <%= f.text_area :body, :cols => 80, :rows => 20 %>
186
+ </p>
187
+ <p>
188
+ <%= f.submit 'Wklej' %>
189
+ </p>
190
+ <% end %>
191
+
192
+ Od razu też wrzucimy do katalogu *layouts* layout *application.html.erb*:
193
+
194
+ :::html_rails
195
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
196
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
197
+
198
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
199
+ <head>
200
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
201
+ <title>Leniwce z o.o.</title>
202
+ <%= stylesheet_link_tag 'application', 'uv' %>
203
+ </head>
204
+ <body>
205
+ <h1>Leniwce z o.o.</h1>
206
+
207
+ <p style="color: green"><%= flash[:notice] %></p>
208
+
209
+ <%= yield %>
210
+
211
+ </body>
212
+ </html>
213
+
214
+ Plik *uv.css* będzie używany przy kolorowaniu składni.
215
+ Skopiowałem go z katalogu *stylesheets* tego samouczka.
216
+
217
+ Wejście na stronę *http://localhost:3000/* daje błąd:
218
+
219
+ NoMethodError in Leniwce#index
220
+
221
+ You have a nil object when you didn't expect it!
222
+ You might have expected an instance of Array.
223
+
224
+ <%= f.select :lang, @languages %>
225
+
226
+ Zmienna `@languages` nie istnieje. Aby błąd się nie pojawiał
227
+ musimy ją zdefiniować.
228
+
229
+ <blockquote>
230
+ {%= image_tag "/images/leniwce_controller.png", :alt => "[leniwce_controller.rb]" %}
231
+ </blockquote>
232
+
233
+ Dopisujemy w pliku *leniwce_controller.rb* w metodzie *index*:
234
+
235
+ :::ruby
236
+ class LeniwceController < ApplicationController
237
+ def index
238
+ @languages = ["ruby", "html", "css"]
239
+ end
240
+
241
+ Jeszcze raz wchodzimy na stronę *http://localhost:3000/*,
242
+ teraz już działa, wpisujemy kawałek kodu, klikamy przycisk
243
+ „Wklej” i dostajemy stronę z:
244
+
245
+ Unknown action
246
+ No action responded to create. Actions: index, search, and show
247
+
248
+ No to definiujemy akcję *create*. Ponownie zaglądamy do pliku
249
+ *leniwce_controller.rb*, gdzie definiujemy metodę *create*:
250
+
251
+ :::ruby
252
+ def create
253
+ @leniwiec = Leniwiec.new(params[:leniwiec])
254
+ if @leniwiec.save
255
+ flash[:notice] = 'Umieszczono leniwca w bazie.'
256
+ redirect_to leniwce_path(@leniwiec.id)
257
+ else
258
+ render :action => "index"
259
+ end
260
+ end
261
+
262
+ Teraz wyświetla się wygenerowana stronka *show.html.erb*
263
+ na której ma się pojawić przed chwilą wklejony i zapisany
264
+ w bazie kod. Zmieniamy ją na:
265
+
266
+ :::html_rails
267
+ <h3>Leniwiec: <%= @leniwiec.lang %></h3>
268
+ <%= @leniwiec.body %>
269
+ <%= link_to 'Nowy leniwiec', root_path %>
270
+
271
+ Teraz po przekierowaniu dostajemy błąd:
272
+
273
+ NoMethodError in Leniwce#show
274
+ Showing app/views/leniwce/show.html.erb where line #1 raised:
275
+ You have a nil object when you didn't expect it!
276
+
277
+ Oznacza to, że w metodzie *show* musimy wyciągnąć leniwca z bazy.
278
+ Robimy to tak:
279
+
280
+ :::ruby
281
+ def show
282
+ @leniwiec = Leniwiec.find(params[:number])
283
+ end
284
+
285
+
286
+ ## Dodajemy kolorowanie składni
287
+
288
+ Zmieniamy kod metody *show*:
289
+
290
+ :::ruby
291
+ class LeniwceController < ApplicationController
292
+ def show
293
+ @leniwiec = Leniwiec.find(params[:number])
294
+ @leniwiec.body = ::Uv.parse(@leniwiec.body, 'xhtml', @leniwiec.lang, false, "dawn")
295
+ end
296
+
297
+ oraz dopisujemy w pliku *environment.rb*:
298
+
299
+ :::ruby
300
+ require 'uv'
301
+ Rails::Initializer.run do |config|
302
+ config.gem 'ultraviolet'
303
+
304
+
305
+ ## Następna wersja „Leniwca z o.o.”
306
+
307
+ Zaimplementujemy wyszukiwanie fragmentów kodu zawierających podaną
308
+ frazę. Jak takie rzeczy się robi można podejrzeć na screencaście
309
+ [Simple Search Form](http://railscasts.com/episodes/37-simple-search-form).
310
+
311
+ W pliku *application.html.erb* dodamy formularz.
312
+ Tym razem użyjemy `form_tag` a nie `form_for`, dlaczego?
313
+
314
+ :::html_rails
315
+ <% form_tag search_path, :method => 'get' do %>
316
+ <p>
317
+ <%= text_field_tag :search, params[:search] %>
318
+ <%= submit_tag "Wyszukaj", :name => nil %>
319
+ </p>
320
+ <% end %>
321
+
322
+ Jaką funkcję spełnia `:name => nil`? Technicznie żadną.
323
+ To jaki sens ma ten kawałek kodu?
324
+
325
+ W pliku *leniwce_controller.rb* piszemy metodę *search*:
326
+
327
+ :::ruby
328
+ def search
329
+ @search = params[:search]
330
+ @leniwce = Leniwiec.search(@search)
331
+
332
+ # kolorowanie składni
333
+ @leniwce.each do |leniwiec|
334
+ leniwiec.body = ::Uv.parse(leniwiec.body, 'xhtml', leniwiec.lang, false, "dawn")
335
+ end
336
+ end
337
+
338
+ Implementujemy `Leniwiec.search`:
339
+
340
+ :::ruby
341
+ def self.search(search)
342
+ if search
343
+ all(:conditions => ['body LIKE ?', "%#{search}%"])
344
+ else
345
+ all
346
+ end
347
+ end
348
+
349
+ I tworzymy widok na wyszukane fragmenty kodu:
350
+
351
+ :::html_rails
352
+ <h3>Wyniki wyszukiwania: <%= @search %></h3>
353
+ <% @leniwce.each do |leniwiec| %>
354
+ <p><b><%= leniwiec.lang %></b></p>
355
+ <%= leniwiec.body %>
356
+ <% end %>
357
+
358
+
359
+ ## Filter parameter logging
360
+
361
+ Pamiętamy też o skróceniu logów \(dlaczego?\):
362
+
363
+ :::ruby
364
+ class ApplicationController < ActionController::Base
365
+ # Scrub sensitive parameters from your log
366
+ filter_parameter_logging :body
367
+ end
368
+
369
+ ## Final touches
370
+
371
+ Pozostaje jeszcze osuszyć kod (jaki?) oraz odrobić zadania.