wbzyl-rails3-tutorial 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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.