Mudanças no carrierwave

jamesperet 9 years ago
parent
commit
84a5f38c29
8 changed files with 490 additions and 69 deletions
  1. 2 0
      .gitignore
  2. 69 39
      CarrierWave.md
  3. 31 0
      Postgres.md
  4. 5 1
      criando um projeto.md
  5. 18 0
      migration.md
  6. 0 0
      mySQL.md
  7. 335 0
      rails_notes.md
  8. 30 29
      readme.md

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
1
+.DS_Store
2
+Documentation/

+ 69 - 39
CarrierWave.md

@@ -1,63 +1,86 @@
1 1
 # Upload de arquivos com o CarrierWave
2 2
 
3
+O Carrierwave é um *gem* para simplificar a criação de um sistema de upload de arquivos no Ruby on Rails.
4
+
5
+
6
+## Instalação
7
+
3 8
 Adicione no ```Gemfile```:
4 9
 
5
-	gem "carrierwave"
10
+```ruby
11
+gem "carrierwave"
12
+```
6 13
 
7
-Execute o comando ```$ bundle install``` para instalar o **gem** e depois gere um novo objeto:
14
+Instale o **gem** e depois gere um novo objeto:
8 15
 
9
-```$ rails g uploader image```
16
+```bash
17
+bundle install
18
+rails g uploader image
19
+```
10 20
 
11 21
 Depois crie uma migração para associar as imagens a outra classe:
12 22
 
13
-```$ rails g migration add_image_to_posts image:string```
23
+```bash
24
+rails g migration add_image_to_posts image:string
25
+```
14 26
 
15 27
 Execute o  comando ```$ rake db:migrate``` para criar o campo na tabela no banco de dados. Depois entre no arquivo ```models/post.rb``` e adicione o uploder:
16 28
 
17
-	class post < ActiveRecord::Base
18
-	  attr_accessible :name, :content, :image
19
-	  mount_uploader :image, ImageUploader
20
-	end
29
+```ruby
30
+class post < ActiveRecord::Base
31
+  attr_accessible :name, :content, :image
32
+  mount_uploader :image, ImageUploader
33
+end
34
+```
21 35
 
22 36
 Depois modifique o formulario que vai conter o campo de upload:
23 37
 
24
-	<%= form_for @post, html => {:multipart => true} do |f| %>
25
-	
26
-		<%= f.file_field :image %>
27
-		<%= f.submit %>
28
-		
29
-	<% end %>
38
+```erb
39
+<%= form_for @post, html => {:multipart => true} do |f| %>
40
+	<%= f.file_field :image %>
41
+	<%= f.submit %>
42
+<% end %>
43
+```
30 44
 
31 45
 Para utilizar a imagem no **view**:
32 46
 
33
-	<%= image_tag @post.image.to_s %>
47
+```erb
48
+<%= image_tag @post.image.to_s %>
49
+```
50
+
34 51
 
35
-#### Modificar a pasta onde os arquivos são salvos
52
+## Modificar a pasta onde os arquivos são salvos
36 53
 
37 54
 No **uploader** que foi gerado, modifique o arquivo ```app/uploaders/image_uploader.rb``` e defina onde os arquivos vão ser salvos:
38 55
 
39
-	class ImageUploader < CarrierWave::Uploader::Base
40
-	  storage :file
41
-	
42
-	  def store_dir
43
-	    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
44
-	  end
56
+```ruby
57
+class ImageUploader < CarrierWave::Uploader::Base
58
+  storage :file
45 59
 
46
-	end
60
+  def store_dir
61
+    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
62
+  end
47 63
 
48
-#### Upload de arquivo via URL
64
+end
65
+```
66
+
67
+
68
+## Upload de arquivo via URL
49 69
 
50 70
 Para carregar um arquivo externo vindo de uma URL, modifique o formulario de upload:
51 71
 
52
-	<%= form_for @painting, :html => {:multipart => true} do |f| %>
53
-		<%= f.file_field :image %>
54
-	    <%= f.text_field :remote_image_url %>
55
-	  	<%= f.submit %>
56
-	<% end %>
72
+```erb
73
+<%= form_for @painting, :html => {:multipart => true} do |f| %>
74
+	<%= f.file_field :image %>
75
+    <%= f.text_field :remote_image_url %>
76
+  	<%= f.submit %>
77
+<% end %>
78
+```
57 79
 
58 80
 No modelo onde que carrega as imagens ```models/post.rb```, adicione o ```attr_accessible :remote_image_url```. É importante usar essa variavel por que o **CarrierWave** vai automaticamente procurar o arquivo pela URL e fazer o upload e processamento.
59 81
 
60
-#### Processamento de imagens com o rmagik
82
+
83
+## Processamento de imagens com o rmagik
61 84
 
62 85
 Para fazer modificações na imagem como criar versões *thumbnail*, é possivel utilizar o **rmagick** junto com o **ImageMagick**.
63 86
 
@@ -65,24 +88,31 @@ Primeiro é necessario instalar o **ImageMagick**.
65 88
 
66 89
 Adicione no ```Gemfile``` o **rmagick** e execute o ```$ bundle install```:
67 90
 
68
-	gem "rmagick"
91
+```ruby
92
+gem "rmagick"
93
+```
69 94
 
70 95
 No arquivo ```app/uploaders/image_uploader.rb```, inclua o ```CarrierWave::RMagik```, defina a pasta onde as imagens serão guardadas e defina o processamento da nova versão da imagem:
71 96
 
72
-	class ImageUploader < CarrierWave::Uploader::Base
97
+```ruby
98
+class ImageUploader < CarrierWave::Uploader::Base
73 99
 
74
-	  include CarrierWave::RMagick
100
+  include CarrierWave::RMagick
75 101
 
76
-	  version :thumb do
77
-	    process :resize_to_limit => [200, 200]
78
-	  end
102
+  version :thumb do
103
+    process :resize_to_limit => [200, 200]
104
+  end
79 105
 
80
-	end
106
+end
107
+```
81 108
 
82 109
 Para fazer o display da imagem **thumb**:
83 110
 
84
-	<%= image_tag @post.image.thumb if painting.image? %>
111
+```erb
112
+<%= image_tag @post.image.thumb if painting.image? %>
113
+```
114
+
85 115
 
86 116
 ------
87 117
 
88
-<a href="readme.md" class=""btn btn-mini>voltar</a>
118
+[voltar](../)

+ 31 - 0
Postgres.md

@@ -0,0 +1,31 @@
1
+# Postgres
2
+
3
+Para criar um banco de dados postgres primeiro faça o login no banco de dados:
4
+
5
+``$ psql --username=admin``
6
+
7
+Use o comando ``\list`` para listar as bases de dado.
8
+
9
+Depois crie dois novos bancos de dados com os seguintes comandos:
10
+
11
+``CREATE DATABASE demo_app_development``
12
+
13
+``CREATE DATABASE demo_app_test``
14
+
15
+Por ultimo configure o arquivo ``database.yml `` com as informações de login e database que foram criadas:
16
+
17
+	development:
18
+	  adapter: postgresql
19
+	  encoding: unicode
20
+	  database: demo_app_development
21
+	  pool: 5
22
+	  username: admin
23
+	  password: password1
24
+
25
+	test:
26
+	  adapter: postgresql
27
+	  encoding: unicode
28
+	  database: demo_app_test
29
+	  pool: 5
30
+	  username: admin
31
+	  password: password1

+ 5 - 1
criando um projeto.md

@@ -1,7 +1,11 @@
1 1
 # Criando um projeto
2 2
 Para criar um aplicativo em rails, digite o seguinte comando no terminal:
3 3
 
4
-```$ rails new demo_project -d mysql```
4
+``$ rails new demo_project -d mysql``
5
+
6
+ou
7
+
8
+``$ rails new demo_project --database=postgresql``
5 9
 
6 10
 O parametro *demo_project* indica o nome do projeto que está sendo criado. O parametro *-d mysql* serve para que o rails já configure o projeto utilizando um banco de dados mySQL. 
7 11
 

+ 18 - 0
migration.md

@@ -95,6 +95,24 @@ Também é possivel reverter para uma versão intermediaria utilizando o número
95 95
 - ```remove_index(table,column)```
96 96
 - ```execute("any SQL string")```
97 97
 
98
+## Resetar banco de dados
99
+
100
+Para resetar o banco de dados e recriar as migrações:
101
+
102
+``` bash
103
+rake db:reset
104
+rake db:migrate
105
+```
106
+
107
+Para deletar o banco de dados, criar um novo e rodar as migrações:
108
+
109
+``` bash
110
+rake db:drop
111
+rake db:create
112
+rake db:migrate
113
+```
114
+
115
+
98 116
 #### Links
99 117
 
100 118
 - [Rails Guides - Migrations](http://guides.rubyonrails.org/migrations.html)

Criando um banco de dados mySQL.md → mySQL.md


+ 335 - 0
rails_notes.md

@@ -0,0 +1,335 @@
1
+# Rails Nested Fields Params
2
+
3
+To access the nested fields from params do the following:
4
+
5
+``` ruby
6
+params[:order][:items_attributes].values.each do |item|
7
+  item[:type_id]
8
+end if params[:order] and params[:order][:items_attributes]
9
+```
10
+
11
+Above solution will work ONLY if you have declared the correct associations and accepts_nested_attributes_for.
12
+
13
+```ruby
14
+class Order < ActiveRecord::Base
15
+  has_many :items
16
+  accepts_nested_attributes_for :items, :allow_destroy => true
17
+end
18
+
19
+class Item < ActiveRecord::Base
20
+  belongs_to :order
21
+end
22
+
23
+```
24
+
25
+# Ruby each Iterator
26
+
27
+The each iterator returns all the elements of an array or a hash.
28
+
29
+Syntax:
30
+
31
+``` ruby
32
+collection.each do |variable|
33
+   code
34
+end
35
+```
36
+
37
+Executes code for each element in collection. Here, collection could be an array or a ruby hash.
38
+
39
+Example:
40
+
41
+``` ruby
42
+#!/usr/bin/ruby
43
+
44
+ary = [1,2,3,4,5]
45
+ary.each do |i|
46
+   puts i
47
+end
48
+
49
+```
50
+
51
+This will produce the following result:
52
+
53
+``` bash
54
+1
55
+2
56
+3
57
+4
58
+5
59
+```
60
+
61
+You always associate the each iterator with a block. It returns each value of the array, one by one, to the block. The value is stored in the variable i and then displayed on the screen.
62
+
63
+# Ruby collect Iterator
64
+
65
+The collect iterator returns all the elements of a collection.
66
+
67
+Syntax:
68
+
69
+``` ruby
70
+collection = collection.collect
71
+```
72
+
73
+The collect method need not always be associated with a block. The collect method returns the entire collection, regardless of whether it is an array or a hash.
74
+
75
+Example:
76
+
77
+``` ruby
78
+#!/usr/bin/ruby
79
+
80
+a = [1,2,3,4,5]
81
+b = Array.new
82
+b = a.collect
83
+puts b
84
+```
85
+
86
+This will produce the following result:
87
+
88
+``` bash
89
+1
90
+2
91
+3
92
+4
93
+5
94
+```
95
+
96
+NOTE: The collect method is not the right way to do copying between arrays. There is another method called a clone, which should be used to copy one array into another array.
97
+
98
+You normally use the collect method when you want to do something with each of the values to get the new array. For example, this code produces an array b containing 10 times each value in a.
99
+
100
+``` ruby
101
+#!/usr/bin/ruby
102
+
103
+a = [1,2,3,4,5]
104
+b = a.collect{|x| 10*x}
105
+puts b
106
+```
107
+
108
+This will produce the following result:
109
+
110
+``` bash
111
+	10
112
+	20
113
+	30
114
+	40
115
+	50
116
+```
117
+
118
+# find\_or\_create_by(attributes, &block)
119
+
120
+Finds the first record with the given attributes, or creates a record with the attributes if one is not found:
121
+
122
+``` ruby
123
+# Find the first user named "Penélope" or create a new one.
124
+User.find_or_create_by(first_name: 'Penélope')
125
+# => #<User id: 1, first_name: "Penélope", last_name: nil>
126
+
127
+# Find the first user named "Penélope" or create a new one.
128
+# We already have one so the existing record will be returned.
129
+User.find_or_create_by(first_name: 'Penélope')
130
+# => #<User id: 1, first_name: "Penélope", last_name: nil>
131
+
132
+# Find the first user named "Scarlett" or create a new one with
133
+# a particular last name.
134
+User.create_with(last_name: 'Johansson').find_or_create_by(first_name: 'Scarlett')
135
+# => #<User id: 2, first_name: "Scarlett", last_name: "Johansson">
136
+```
137
+
138
+This method accepts a block, which is passed down to create. The last example above can be alternatively written this way:
139
+
140
+``` ruby
141
+# Find the first user named "Scarlett" or create a new one with a
142
+# different last name.
143
+User.find_or_create_by(first_name: 'Scarlett') do |user|
144
+  user.last_name = 'Johansson'
145
+end
146
+# => #<User id: 2, first_name: "Scarlett", last_name: "Johansson">
147
+```
148
+
149
+This method always returns a record, but if creation was attempted and failed due to validation errors it won’t be persisted, you get what create returns in such situation.
150
+
151
+Please note *this method is not atomic*, it runs first a SELECT, and if there are no results an INSERT is attempted. If there are other threads or processes there is a race condition between both calls and it could be the case that you end up with two similar records.
152
+
153
+Whether that is a problem or not depends on the logic of the application, but in the particular case in which rows have a UNIQUE constraint an exception may be raised, just retry:
154
+
155
+``` ruby
156
+begin
157
+  CreditAccount.find_or_create_by(user_id: user.id)
158
+rescue ActiveRecord::RecordNotUnique
159
+  retry
160
+end
161
+```
162
+
163
+
164
+# Trucate
165
+
166
+``` ruby
167
+truncate("Once upon a time in a world far far away")
168
+# => "Once upon a time in a world..."
169
+truncate("Once upon a time in a world far far away", :length => 17)
170
+# => "Once upon a ti..."
171
+truncate("Once upon a time in a world far far away", :length => 17, :separator => ' ')
172
+# => "Once upon a..."
173
+truncate("And they found that many people were sleeping better.", :length => 25, :omission => '... (continued)')
174
+# => "And they f... (continued)"
175
+```
176
+
177
+# Active Record Order
178
+
179
+Allows to specify an order attribute:
180
+
181
+``` ruby
182
+User.order('name')
183
+=> SELECT "users".* FROM "users" ORDER BY name
184
+
185
+User.order('name DESC')
186
+=> SELECT "users".* FROM "users" ORDER BY name DESC
187
+
188
+User.order('name DESC, email')
189
+=> SELECT "users".* FROM "users" ORDER BY name DESC, email
190
+
191
+User.order(:name)
192
+=> SELECT "users".* FROM "users" ORDER BY "users"."name" ASC
193
+
194
+User.order(email: :desc)
195
+=> SELECT "users".* FROM "users" ORDER BY "users"."email" DESC
196
+
197
+User.order(:name, email: :desc)
198
+=> SELECT "users".* FROM "users" ORDER BY "users"."name" ASC, "users"."email" DESC
199
+```
200
+
201
+
202
+# Active Record assign_attributes
203
+
204
+```assign_attributes(new_attributes, options = {}) public```
205
+
206
+Allows you to set all the attributes for a particular mass-assignment security role by passing in a hash of attributes with keys matching the attribute names (which again matches the column names) and the role name using the :as option.
207
+
208
+To bypass mass-assignment security you can use the :without_protection => true option.
209
+
210
+``` ruby
211
+class User < ActiveRecord::Base
212
+  attr_accessible :name
213
+  attr_accessible :name, :is_admin, :as => :admin
214
+end
215
+
216
+user = User.new
217
+user.assign_attributes({ :name => 'Josh', :is_admin => true })
218
+user.name       # => "Josh"
219
+user.is_admin?  # => false
220
+
221
+user = User.new
222
+user.assign_attributes({ :name => 'Josh', :is_admin => true }, :as => :admin)
223
+user.name       # => "Josh"
224
+user.is_admin?  # => true
225
+
226
+user = User.new
227
+user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true)
228
+user.name       # => "Josh"
229
+user.is_admin?  # => true
230
+```
231
+
232
+# Fully Customizing Devise Routes
233
+
234
+Devise is a full-featured authentication and account management framework for Ruby on Rails. It has many options, but the default configuration is definitely encouraged.
235
+
236
+There are some basic URL (path) options that allow you to modify the basics of the routes that Devise supplies for all of its features, but they are very minimal.
237
+
238
+``` ruby
239
+devise_for :users, path_names: {
240
+  sign_in: 'login',
241
+  sign_out: 'logout',
242
+  password: 'reset'
243
+}
244
+```
245
+
246
+This means that Devise will use /login and /logout, but when it comes to doing password resets, confirmations, registrations, etc., it’s going to tack on the default Rails CRUD actions ```/reset/new```, ```/reset/edit```, ```/confirmations/new``` etc.
247
+
248
+I can’t abide by those ugly URLs and want full customization ability for every single route. A brief aside: I’m using the model Person in my latest app instead of the ubiquitous User. I find the former to be more humanizing.
249
+
250
+Given that, in order to customize every single route across the sessions, passwords, confirmations and registrations controllers for Devise, I used the following:
251
+
252
+``` ruby
253
+# Authentication
254
+  devise_for :people, skip: [:sessions, :passwords, :confirmations, :registrations]
255
+  as :person do
256
+    # session handling
257
+    get     '/login'  => 'devise/sessions#new',     as: 'new_person_session'
258
+    post    '/login'  => 'devise/sessions#create',  as: 'person_session'
259
+    delete  '/logout' => 'devise/sessions#destroy', as: 'destroy_person_session'
260
+
261
+    # joining
262
+    get   '/join' => 'devise/registrations#new',    as: 'new_person_registration'
263
+    post  '/join' => 'devise/registrations#create', as: 'person_registration'
264
+
265
+    scope '/account' do
266
+      # password reset
267
+      get   '/reset-password'        => 'devise/passwords#new',    as: 'new_person_password'
268
+      put   '/reset-password'        => 'devise/passwords#update', as: 'person_password'
269
+      post  '/reset-password'        => 'devise/passwords#create'
270
+      get   '/reset-password/change' => 'devise/passwords#edit',   as: 'edit_person_password'
271
+
272
+      # confirmation
273
+      get   '/confirm'        => 'devise/confirmations#show',   as: 'person_confirmation'
274
+      post  '/confirm'        => 'devise/confirmations#create'
275
+      get   '/confirm/resend' => 'devise/confirmations#new',    as: 'new_person_confirmation'
276
+
277
+      # settings & cancellation
278
+      get '/cancel'   => 'devise/registrations#cancel', as: 'cancel_person_registration'
279
+      get '/settings' => 'devise/registrations#edit',   as: 'edit_person_registration'
280
+      put '/settings' => 'devise/registrations#update'
281
+
282
+      # account deletion
283
+      delete '' => 'devise/registrations#destroy'
284
+    end
285
+  end
286
+```
287
+
288
+The trick is to make sure your as named route aliases line up correctly with what Devise expects, and to ensure that you call devise_for before devise_scope (or its alias, as, like I did). You need to tell devise_for to skip the auto-creation of all of the routes for all of the controllers you’re using, then go ahead and define all of them yourself.
289
+
290
+# Rails 4 Turbolinks Override
291
+
292
+### First solution: disable Turbolinks
293
+
294
+Disable turbolinks in a given page by passing a data-attribute:
295
+
296
+``` ruby
297
+= link_to "My rating feature", rating_feature_path,
298
+  "data-no-turbolink" => true
299
+```
300
+
301
+### Second solution: create a trigger handler 
302
+
303
+``` javascript
304
+attachRatingHandler = ->
305
+  $("span.star").on "click", ->
306
+    ... code dealing with ratings ...
307
+
308
+$(document).ready attachRatingHandler
309
+$(document).on "page:load", attachRatingHandler
310
+
311
+Article from [I am Pedantic](http://iampedantic.com/post/41170460234/fully-customizing-devise-routes).
312
+```
313
+
314
+or even better:
315
+
316
+``` javascript
317
+attachRatingHandler = ->
318
+  ... code dealing with ratings ...
319
+$ ->
320
+  $(document).on 'click', 'span.star', attachRatingHandler
321
+```
322
+
323
+from [Rails 4: My First Run-in with Turbolinks](http://srbiv.github.io/2013/04/06/rails-4-my-first-run-in-with-turbolinks.html)
324
+
325
+# Nested Model Links
326
+
327
+* [Nested Model Form in Rails 4](http://iroller.ru/blog/2013/10/14/nested-model-form-in-rails-4/)
328
+* [Rails Nested Forms using jQuery and SimpleForm](http://davidlesches.com/blog/rails-nested-forms-using-jquery-and-simpleform)
329
+* [Active Record Nested Attributes](http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html)
330
+* [Complex Rails Forms with Nested Attributes](http://www.sitepoint.com/complex-rails-forms-with-nested-attributes/)
331
+* [Rails awesome_nested_fields gem](https://github.com/lailsonbm/awesome_nested_fields)
332
+* [Working with JavaScript in Rails](http://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html)
333
+* [accepts_nested_attributes_for](http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for)
334
+* [Working with nested forms and a many-to-many association in Rails 4](http://www.createdbypete.com/articles/working-with-nested-forms-and-a-many-to-many-association-in-rails-4/)
335
+* [fields_for](http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for)

+ 30 - 29
readme.md

@@ -6,34 +6,35 @@ Anota&ccedil;&otilde;es dos estudos de Ruby on Rails de James Peret, baseado no
6 6
 ## Index
7 7
 1. [Instalação](instalacao.md)
8 8
 2. [Criando um projeto](criando%20um%20projeto.md)
9
-3. [Criando um banco de dados mySQL](Criando%20um%20banco%20de%20dados%20mySQL.md)
10
-4. [Gerando um "Controller" e um "View"](Gerando%20um%20Controller%20e%20um%20View.md)
11
-5. [Routes](routes.md)
12
-6. [Render e redirecionamento](Render%20e%20Redirecionamento.md)
13
-7. [ERB View Templates](View%20Templates.md)
14
-8. [Instance Variables](Instance%20Variables.md)
15
-9. [Links](Links.md)
16
-10. [Parametros na URL](Parametros%20na%20URL.md) (GET e POST)
17
-11. [Rake](rake.md)
18
-12. [Migrations](migration.md)
19
-13. [ActiveRecord e ActiveRelations](ActiveRecord_ActiveRelation.md)
20
-14. [Gerando modelos](gerando_modelos.md)
21
-15. [Rails Console](rails_console.md)
22
-16. [Records](records.md)
23
-17. [Scopes](scopes.md)
24
-18. [Associações](associacoes.md)
25
-19. [CRUD](CRUD.md)
26
-20. [Scaffolding](scaffolding.md)
27
-21. [Helpers](helpers.md)
28
-22. [SimpleForm](SimpleForm.md)
29
-23. [Nested Model Forms](nested_model.md)
30
-24. [Autenticação de usuários com o Devise](devise.md)
31
-25. [Upload de arquivos com o CarrierWave](CarrierWave.md)
32
-26. [jQuery File Upload](jQuery_file_upload.md)
33
-27. [Testes](testes.md)
34
-28. [Twitter Bootstrap](twitter_bootstrap.md)
35
-29. [Cucumber](cucumber.md)
36
-30. [Controle de versão com Git](git.md)
37
-31. [Funções de tempo](time_ago.md)
9
+3. [Criando um banco de dados mySQL](mySQL.md)
10
+4. [Criando um banco de dados Postgres](Postgres.md)
11
+5. [Gerando um "Controller" e um "View"](Gerando%20um%20Controller%20e%20um%20View.md)
12
+6. [Routes](routes.md)
13
+7. [Render e redirecionamento](Render%20e%20Redirecionamento.md)
14
+8. [ERB View Templates](View%20Templates.md)
15
+9. [Instance Variables](Instance%20Variables.md)
16
+10. [Links](Links.md)
17
+11. [Parametros na URL](Parametros%20na%20URL.md) (GET e POST)
18
+12. [Rake](rake.md)
19
+13. [Migrations](migration.md)
20
+14. [ActiveRecord e ActiveRelations](ActiveRecord_ActiveRelation.md)
21
+15. [Gerando modelos](gerando_modelos.md)
22
+16. [Rails Console](rails_console.md)
23
+17. [Records](records.md)
24
+18. [Scopes](scopes.md)
25
+19. [Associações](associacoes.md)
26
+20. [CRUD](CRUD.md)
27
+21. [Scaffolding](scaffolding.md)
28
+22. [Helpers](helpers.md)
29
+23. [SimpleForm](SimpleForm.md)
30
+24. [Nested Model Forms](nested_model.md)
31
+25. [Autenticação de usuários com o Devise](devise.md)
32
+26. [Upload de arquivos com o CarrierWave](CarrierWave.md)
33
+27. [jQuery File Upload](jQuery_file_upload.md)
34
+28. [Testes](testes.md)
35
+29. [Twitter Bootstrap](twitter_bootstrap.md)
36
+30. [Cucumber](cucumber.md)
37
+31. [Controle de versão com Git](git.md)
38
+32. [Funções de tempo](time_ago.md)
38 39
 
39 40
 *[Links de referencia](links_referencias.md)*