railties 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/CHANGELOG +4 -0
  2. data/guides/assets/javascripts/syntaxhighlighter/shBrushAS3.js +59 -0
  3. data/guides/assets/javascripts/syntaxhighlighter/shBrushAppleScript.js +75 -0
  4. data/guides/assets/javascripts/syntaxhighlighter/shBrushBash.js +59 -0
  5. data/guides/assets/javascripts/syntaxhighlighter/shBrushCSharp.js +65 -0
  6. data/guides/assets/javascripts/syntaxhighlighter/shBrushColdFusion.js +100 -0
  7. data/guides/assets/javascripts/syntaxhighlighter/shBrushCpp.js +97 -0
  8. data/guides/assets/javascripts/syntaxhighlighter/shBrushCss.js +91 -0
  9. data/guides/assets/javascripts/syntaxhighlighter/shBrushDelphi.js +55 -0
  10. data/guides/assets/javascripts/syntaxhighlighter/shBrushDiff.js +41 -0
  11. data/guides/assets/javascripts/syntaxhighlighter/shBrushErlang.js +52 -0
  12. data/guides/assets/javascripts/syntaxhighlighter/shBrushGroovy.js +67 -0
  13. data/guides/assets/javascripts/syntaxhighlighter/shBrushJScript.js +52 -0
  14. data/guides/assets/javascripts/syntaxhighlighter/shBrushJava.js +57 -0
  15. data/guides/assets/javascripts/syntaxhighlighter/shBrushJavaFX.js +58 -0
  16. data/guides/assets/javascripts/syntaxhighlighter/shBrushPerl.js +72 -0
  17. data/guides/assets/javascripts/syntaxhighlighter/shBrushPhp.js +88 -0
  18. data/guides/assets/javascripts/syntaxhighlighter/shBrushPlain.js +33 -0
  19. data/guides/assets/javascripts/syntaxhighlighter/shBrushPowerShell.js +74 -0
  20. data/guides/assets/javascripts/syntaxhighlighter/shBrushPython.js +64 -0
  21. data/guides/assets/javascripts/syntaxhighlighter/shBrushRuby.js +55 -0
  22. data/guides/assets/javascripts/syntaxhighlighter/shBrushSass.js +94 -0
  23. data/guides/assets/javascripts/syntaxhighlighter/shBrushScala.js +51 -0
  24. data/guides/assets/javascripts/syntaxhighlighter/shBrushSql.js +66 -0
  25. data/guides/assets/javascripts/syntaxhighlighter/shBrushVb.js +56 -0
  26. data/guides/assets/javascripts/syntaxhighlighter/shBrushXml.js +69 -0
  27. data/guides/assets/javascripts/syntaxhighlighter/shCore.js +17 -0
  28. data/guides/assets/stylesheets/main.css +6 -13
  29. data/guides/assets/stylesheets/syntaxhighlighter/shCore.css +226 -0
  30. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDefault.css +328 -0
  31. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDjango.css +331 -0
  32. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEclipse.css +339 -0
  33. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEmacs.css +324 -0
  34. data/guides/assets/stylesheets/syntaxhighlighter/shCoreFadeToGrey.css +328 -0
  35. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMDUltra.css +324 -0
  36. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMidnight.css +324 -0
  37. data/guides/assets/stylesheets/syntaxhighlighter/shCoreRDark.css +324 -0
  38. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDefault.css +117 -0
  39. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDjango.css +120 -0
  40. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEclipse.css +128 -0
  41. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEmacs.css +113 -0
  42. data/guides/assets/stylesheets/syntaxhighlighter/shThemeFadeToGrey.css +117 -0
  43. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMDUltra.css +113 -0
  44. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMidnight.css +113 -0
  45. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRDark.css +113 -0
  46. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRailsGuides.css +116 -0
  47. data/guides/rails_guides/generator.rb +21 -3
  48. data/guides/source/3_0_release_notes.textile +3 -7
  49. data/guides/source/action_controller_overview.textile +8 -1
  50. data/guides/source/action_mailer_basics.textile +1 -1
  51. data/guides/source/action_view_overview.textile +1 -1
  52. data/guides/source/active_record_querying.textile +44 -50
  53. data/guides/source/active_record_validations_callbacks.textile +3 -3
  54. data/guides/source/caching_with_rails.textile +1 -1
  55. data/guides/source/configuring.textile +3 -3
  56. data/guides/source/debugging_rails_applications.textile +6 -4
  57. data/guides/source/form_helpers.textile +21 -15
  58. data/guides/source/getting_started.textile +2 -12
  59. data/guides/source/i18n.textile +6 -0
  60. data/guides/source/index.html.erb +10 -2
  61. data/guides/source/layout.html.erb +13 -5
  62. data/guides/source/layouts_and_rendering.textile +2 -2
  63. data/guides/source/migrations.textile +1 -1
  64. data/guides/source/performance_testing.textile +6 -6
  65. data/guides/source/plugins.textile +9 -9
  66. data/guides/source/routing.textile +45 -25
  67. data/guides/source/ruby_on_rails_guides_guidelines.textile +77 -0
  68. data/lib/rails/application/configuration.rb +2 -0
  69. data/lib/rails/application/finisher.rb +7 -0
  70. data/lib/rails/code_statistics.rb +1 -1
  71. data/lib/rails/commands/console.rb +1 -1
  72. data/lib/rails/commands/runner.rb +2 -2
  73. data/lib/rails/engine/configuration.rb +6 -0
  74. data/lib/rails/generators/generated_attribute.rb +1 -0
  75. data/lib/rails/generators/rails/app/app_generator.rb +7 -4
  76. data/lib/rails/generators/rails/app/templates/Gemfile +2 -3
  77. data/lib/rails/generators/rails/app/templates/README +1 -1
  78. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +1 -1
  79. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +1 -1
  80. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +1 -1
  81. data/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +1 -1
  82. data/lib/rails/generators/resource_helpers.rb +1 -1
  83. data/lib/rails/plugin.rb +1 -1
  84. data/lib/rails/railtie.rb +1 -1
  85. data/lib/rails/railtie/configuration.rb +4 -3
  86. data/lib/rails/ruby_version_check.rb +1 -2
  87. data/lib/rails/tasks/misc.rake +1 -1
  88. data/lib/rails/version.rb +2 -2
  89. metadata +70 -15
  90. data/guides/assets/javascripts/code_highlighter.js +0 -188
  91. data/guides/assets/javascripts/highlighters.js +0 -90
  92. data/guides/assets/stylesheets/syntax.css +0 -31
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Theme by fxn, took shThemeEclipse.css as starting point.
3
+ */
4
+ .syntaxhighlighter {
5
+ background-color: #eee !important;
6
+ font-family: "Anonymous Pro", "Inconsolata", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace !important;
7
+ overflow-y: hidden !important;
8
+ overflow-x: auto !important;
9
+ }
10
+ .syntaxhighlighter .line.alt1 {
11
+ background-color: #eee !important;
12
+ }
13
+ .syntaxhighlighter .line.alt2 {
14
+ background-color: #eee !important;
15
+ }
16
+ .syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
17
+ background-color: #c3defe !important;
18
+ }
19
+ .syntaxhighlighter .line.highlighted.number {
20
+ color: #eee !important;
21
+ }
22
+ .syntaxhighlighter table caption {
23
+ color: #222 !important;
24
+ }
25
+ .syntaxhighlighter .gutter {
26
+ color: #787878 !important;
27
+ }
28
+ .syntaxhighlighter .gutter .line {
29
+ border-right: 3px solid #d4d0c8 !important;
30
+ }
31
+ .syntaxhighlighter .gutter .line.highlighted {
32
+ background-color: #d4d0c8 !important;
33
+ color: #eee !important;
34
+ }
35
+ .syntaxhighlighter.printing .line .content {
36
+ border: none !important;
37
+ }
38
+ .syntaxhighlighter.collapsed {
39
+ overflow: visible !important;
40
+ }
41
+ .syntaxhighlighter.collapsed .toolbar {
42
+ color: #3f5fbf !important;
43
+ background: #eee !important;
44
+ border: 1px solid #d4d0c8 !important;
45
+ }
46
+ .syntaxhighlighter.collapsed .toolbar a {
47
+ color: #3f5fbf !important;
48
+ }
49
+ .syntaxhighlighter.collapsed .toolbar a:hover {
50
+ color: #aa7700 !important;
51
+ }
52
+ .syntaxhighlighter .toolbar {
53
+ color: #a0a0a0 !important;
54
+ background: #d4d0c8 !important;
55
+ border: none !important;
56
+ }
57
+ .syntaxhighlighter .toolbar a {
58
+ color: #a0a0a0 !important;
59
+ }
60
+ .syntaxhighlighter .toolbar a:hover {
61
+ color: red !important;
62
+ }
63
+ .syntaxhighlighter .plain, .syntaxhighlighter .plain a {
64
+ color: #222 !important;
65
+ }
66
+ .syntaxhighlighter .comments, .syntaxhighlighter .comments a {
67
+ color: #708090 !important;
68
+ }
69
+ .syntaxhighlighter .string, .syntaxhighlighter .string a {
70
+ font-style: italic !important;
71
+ color: #6588A8 !important;
72
+ }
73
+ .syntaxhighlighter .keyword {
74
+ color: #64434d !important;
75
+ }
76
+ .syntaxhighlighter .preprocessor {
77
+ color: #646464 !important;
78
+ }
79
+ .syntaxhighlighter .variable {
80
+ color: #222 !important;
81
+ }
82
+ .syntaxhighlighter .value {
83
+ color: #009900 !important;
84
+ }
85
+ .syntaxhighlighter .functions {
86
+ color: #ff1493 !important;
87
+ }
88
+ .syntaxhighlighter .constants {
89
+ color: #0066cc !important;
90
+ }
91
+ .syntaxhighlighter .script {
92
+ color: #222 !important;
93
+ background-color: none !important;
94
+ }
95
+ .syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
96
+ color: gray !important;
97
+ }
98
+ .syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
99
+ color: #222 !important;
100
+ font-weight: bold !important;
101
+ }
102
+ .syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
103
+ color: red !important;
104
+ }
105
+
106
+ .syntaxhighlighter .xml .keyword {
107
+ color: #64434d !important;
108
+ font-weight: normal !important;
109
+ }
110
+ .syntaxhighlighter .xml .color1, .syntaxhighlighter .xml .color1 a {
111
+ color: #7f007f !important;
112
+ }
113
+ .syntaxhighlighter .xml .string {
114
+ font-style: italic !important;
115
+ color: #6588A8 !important;
116
+ }
@@ -207,10 +207,28 @@ module RailsGuides
207
207
  # with code blocks by hand.
208
208
  def with_workaround_for_notextile(body)
209
209
  code_blocks = []
210
+
210
211
  body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)</\1>}m) do |m|
211
- es = ERB::Util.h($2)
212
- css_class = ['erb', 'shell'].include?($1) ? 'html' : $1
213
- code_blocks << %{<div class="code_container"><code class="#{css_class}">#{es}</code></div>}
212
+ brush = case $1
213
+ when 'ruby', 'sql', 'plain'
214
+ $1
215
+ when 'erb'
216
+ 'ruby; html-script: true'
217
+ when 'html'
218
+ 'xml' # html is understood, but there are .xml rules in the CSS
219
+ else
220
+ 'plain'
221
+ end
222
+
223
+ code_blocks.push(<<HTML)
224
+ <notextile>
225
+ <div class="code_container">
226
+ <pre class="brush: #{brush}; gutter: false; toolbar: false">
227
+ #{ERB::Util.h($2).strip}
228
+ </pre>
229
+ </div>
230
+ </notextile>
231
+ HTML
214
232
  "\ndirty_workaround_for_notextile_#{code_blocks.size - 1}\n"
215
233
  end
216
234
 
@@ -18,13 +18,11 @@ These release notes cover the major upgrades, but don't include every little bug
18
18
 
19
19
  endprologue.
20
20
 
21
- WARNING: Rails 3.0 is currently in beta. This means that there are probably bugs and that you should "report them":http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/overview if you see them. You also may not want to run the NORAD nuclear launch application off a beta version. But if you're starting development on a new application and you don't mind getting wind in your hair, please do jump on board!
22
-
23
- To install the last Rails 3 beta:
21
+ To install Rails 3:
24
22
 
25
23
  <shell>
26
24
  # Use sudo if your setup requires it
27
- gem install rails --pre
25
+ gem install rails
28
26
  </shell>
29
27
 
30
28
 
@@ -77,10 +75,8 @@ More information - "The Path to Rails 3: Approaching the upgrade":http://omgblog
77
75
 
78
76
  h3. Creating a Rails 3.0 application
79
77
 
80
- The new installing rails sequence (for the beta) is:
81
-
82
78
  <shell>
83
- $ gem install rails --prerelease
79
+ # You should have the 'rails' rubygem installed
84
80
  $ rails new myapp
85
81
  $ cd myapp
86
82
  </shell>
@@ -242,7 +242,7 @@ class LoginsController < ApplicationController
242
242
  # "Delete" a login, aka "log the user out"
243
243
  def destroy
244
244
  # Remove the user id from the session
245
- session[:current_user_id] = nil
245
+ @_current_user = session[:current_user_id] = nil
246
246
  redirect_to root_url
247
247
  end
248
248
  end
@@ -264,6 +264,13 @@ class LoginsController < ApplicationController
264
264
  end
265
265
  </ruby>
266
266
 
267
+ Note it is also possible to assign a flash message as part of the redirection.
268
+
269
+ <ruby>
270
+ redirect_to root_url, :notice => "You have successfully logged out"
271
+ </ruby>
272
+
273
+
267
274
  The +destroy+ action redirects to the application's +root_url+, where the message will be displayed. Note that it's entirely up to the next action to decide what, if anything, it will do with what the previous action put in the flash. It's conventional to display eventual errors or notices from the flash in the application's layout:
268
275
 
269
276
  <ruby>
@@ -462,7 +462,7 @@ class UserMailerTest < ActionMailer::TestCase
462
462
  user = users(:some_user_in_your_fixtures)
463
463
 
464
464
  # Send the email, then test that it got queued
465
- email = UserMailer.deliver_welcome_email(user)
465
+ email = UserMailer.welcome_email(user).deliver
466
466
  assert !ActionMailer::Base.deliveries.empty?
467
467
 
468
468
  # Test the body of the sent email contains what we expect it to
@@ -233,7 +233,7 @@ h4. AssetTagHelper
233
233
 
234
234
  This module provides methods for generating HTML that links views to assets such as images, javascripts, stylesheets, and feeds.
235
235
 
236
- By default, Rails links to these assets on the current host in the public folder, but you can direct Rails to link to assets from a dedicated assets server by setting +ActionController::Base.asset_host+ in your +config/environment.rb+. For example, let's say your asset host is +assets.example.com+:
236
+ By default, Rails links to these assets on the current host in the public folder, but you can direct Rails to link to assets from a dedicated assets server by setting +ActionController::Base.asset_host+ in the application configuration, typically in +config/environments/production.rb+. For example, let's say your asset host is +assets.example.com+:
237
237
 
238
238
  <ruby>
239
239
  ActionController::Base.asset_host = "assets.example.com"
@@ -159,14 +159,14 @@ The following may seem very straight forward at first:
159
159
 
160
160
  <ruby>
161
161
  # Very inefficient when users table has thousands of rows.
162
- User.each do |user|
162
+ User.all.each do |user|
163
163
  NewsLetter.weekly_deliver(user)
164
164
  end
165
165
  </ruby>
166
166
 
167
167
  But if the total number of rows in the table is very large, the above approach may vary from being under performant to just plain impossible.
168
168
 
169
- This is because +User.each+ makes Active Record fetch _the entire table_, build a model object per row, and keep the entire array in the memory. Sometimes that is just too many objects and demands too much memory.
169
+ This is because +User.all.each+ makes Active Record fetch _the entire table_, build a model object per row, and keep the entire array in the memory. Sometimes that is just too many objects and demands too much memory.
170
170
 
171
171
  h5. +find_each+
172
172
 
@@ -234,7 +234,7 @@ h4. Array Conditions
234
234
  Now what if that number could vary, say as an argument from somewhere, or perhaps from the user's level status somewhere? The find then becomes something like:
235
235
 
236
236
  <ruby>
237
- Client.where(["orders_count = ?", params[:orders]])
237
+ Client.where("orders_count = ?", params[:orders])
238
238
  </ruby>
239
239
 
240
240
  Active Record will go through the first element in the conditions value and any additional elements will replace the question marks +(?)+ in the first element.
@@ -242,7 +242,7 @@ Active Record will go through the first element in the conditions value and any
242
242
  Or if you want to specify two conditions, you can do it like:
243
243
 
244
244
  <ruby>
245
- Client.where(["orders_count = ? AND locked = ?", params[:orders], false])
245
+ Client.where("orders_count = ? AND locked = ?", params[:orders], false)
246
246
  </ruby>
247
247
 
248
248
  In this example, the first question mark will be replaced with the value in +params[:orders]+ and the second will be replaced with the SQL representation of +false+, which depends on the adapter.
@@ -250,7 +250,7 @@ In this example, the first question mark will be replaced with the value in +par
250
250
  The reason for doing code like:
251
251
 
252
252
  <ruby>
253
- Client.where(["orders_count = ?", params[:orders]])
253
+ Client.where("orders_count = ?", params[:orders])
254
254
  </ruby>
255
255
 
256
256
  instead of:
@@ -268,8 +268,8 @@ h5. Placeholder Conditions
268
268
  Similar to the +(?)+ replacement style of params, you can also specify keys/values hash in your array conditions:
269
269
 
270
270
  <ruby>
271
- Client.where(
272
- ["created_at >= :start_date AND created_at <= :end_date", { :start_date => params[:start_date], :end_date => params[:end_date] }])
271
+ Client.where("created_at >= :start_date AND created_at <= :end_date",
272
+ {:start_date => params[:start_date], :end_date => params[:end_date]})
273
273
  </ruby>
274
274
 
275
275
  This makes for clearer readability if you have a large number of variable conditions.
@@ -279,8 +279,8 @@ h5(#array-range_conditions). Range Conditions
279
279
  If you're looking for a range inside of a table (for example, users created in a certain timeframe) you can use the conditions option coupled with the +IN+ SQL statement for this. If you had two dates coming in from a controller you could do something like this to look for a range:
280
280
 
281
281
  <ruby>
282
- Client.where(["created_at IN (?)",
283
- (params[:start_date].to_date)..(params[:end_date].to_date)])
282
+ Client.where("created_at IN (?)",
283
+ (params[:start_date].to_date)..(params[:end_date].to_date))
284
284
  </ruby>
285
285
 
286
286
  This would generate the proper query which is great for small ranges but not so good for larger ranges. For example if you pass in a range of date objects spanning a year that's 365 (or possibly 366, depending on the year) strings it will attempt to match your field against.
@@ -301,8 +301,8 @@ h5. Time and Date Conditions
301
301
  Things can get *really* messy if you pass in Time objects as it will attempt to compare your field to *every second* in that range:
302
302
 
303
303
  <ruby>
304
- Client.where(["created_at IN (?)",
305
- (params[:start_date].to_date.to_time)..(params[:end_date].to_date.to_time)])
304
+ Client.where("created_at IN (?)",
305
+ (params[:start_date].to_date.to_time)..(params[:end_date].to_date.to_time))
306
306
  </ruby>
307
307
 
308
308
  <sql>
@@ -323,14 +323,14 @@ In this example it would be better to use greater-than and less-than operators i
323
323
 
324
324
  <ruby>
325
325
  Client.where(
326
- ["created_at > ? AND created_at < ?", params[:start_date], params[:end_date]])
326
+ "created_at > ? AND created_at < ?", params[:start_date], params[:end_date])
327
327
  </ruby>
328
328
 
329
329
  You can also use the greater-than-or-equal-to and less-than-or-equal-to like this:
330
330
 
331
331
  <ruby>
332
332
  Client.where(
333
- ["created_at >= ? AND created_at <= ?", params[:start_date], params[:end_date]])
333
+ "created_at >= ? AND created_at <= ?", params[:start_date], params[:end_date])
334
334
  </ruby>
335
335
 
336
336
  Just like in Ruby. If you want a shorter syntax be sure to check out the "Hash Conditions":#hash-conditions section later on in the guide.
@@ -344,13 +344,13 @@ NOTE: Only equality, range and subset checking are possible with Hash conditions
344
344
  h5. Equality Conditions
345
345
 
346
346
  <ruby>
347
- Client.where({ :locked => true })
347
+ Client.where(:locked => true)
348
348
  </ruby>
349
349
 
350
350
  The field name can also be a string:
351
351
 
352
352
  <ruby>
353
- Client.where({ 'locked' => true })
353
+ Client.where('locked' => true)
354
354
  </ruby>
355
355
 
356
356
  h5(#hash-range_conditions). Range Conditions
@@ -358,7 +358,7 @@ h5(#hash-range_conditions). Range Conditions
358
358
  The good thing about this is that we can pass in a range for our fields without it generating a large query as shown in the preamble of this section.
359
359
 
360
360
  <ruby>
361
- Client.where({ :created_at => (Time.now.midnight - 1.day)..Time.now.midnight})
361
+ Client.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight)
362
362
  </ruby>
363
363
 
364
364
  This will find all clients created yesterday by using a +BETWEEN+ SQL statement:
@@ -374,7 +374,7 @@ h5. Subset Conditions
374
374
  If you want to find records using the +IN+ expression you can pass an array to the conditions hash:
375
375
 
376
376
  <ruby>
377
- Client.where({ :orders_count => [1,3,5] })
377
+ Client.where(:orders_count => [1,3,5])
378
378
  </ruby>
379
379
 
380
380
  This code will generate SQL like this:
@@ -496,7 +496,7 @@ SQL uses the +HAVING+ clause to specify conditions on the +GROUP BY+ fields. You
496
496
  For example:
497
497
 
498
498
  <ruby>
499
- Order.group("date(created_at)".having(["created_at > ?", 1.month.ago])
499
+ Order.group("date(created_at)".having("created_at > ?", 1.month.ago)
500
500
  </ruby>
501
501
 
502
502
  The SQL that would be executed would be something like this:
@@ -509,22 +509,16 @@ This will return single order objects for each day, but only for the last month.
509
509
 
510
510
  h4. Readonly Objects
511
511
 
512
- To explicitly disallow modification/destruction of the matching records returned in a Relation object, you could chain the +readonly+ method as +true+ to the find call.
513
-
514
- Any attempt to alter or destroy the readonly records will not succeed, raising an +ActiveRecord::ReadOnlyRecord+ exception. To set this option, specify it like this:
512
+ Active Record provides +readonly+ method on a relation to explicitly disallow modification or deletion of any of the returned object. Any attempt to alter or destroy a readonly record will not succeed, raising an +ActiveRecord::ReadOnlyRecord+ exception.
515
513
 
516
514
  <ruby>
517
- Client.first.readonly(true)
518
- </ruby>
519
-
520
- For example, calling the following code will raise an +ActiveRecord::ReadOnlyRecord+ exception:
521
-
522
- <ruby>
523
- client = Client.first.readonly(true)
524
- client.locked = false
515
+ client = Client.readonly.first
516
+ client.visits += 1
525
517
  client.save
526
518
  </ruby>
527
519
 
520
+ 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 _visists_.
521
+
528
522
  h4. Locking Records for Update
529
523
 
530
524
  Locking is helpful for preventing race conditions when updating records in the database and ensuring atomic updates.
@@ -571,13 +565,13 @@ end
571
565
 
572
566
  h5. Pessimistic Locking
573
567
 
574
- Pessimistic locking uses a locking mechanism provided by the underlying database. Passing +:lock => true+ to +Model.find+ obtains an exclusive lock on the selected rows. +Model.find+ using +:lock+ are usually wrapped inside a transaction for preventing deadlock conditions.
568
+ Pessimistic locking uses a locking mechanism provided by the underlying database. Using +lock+ when building a relation obtains an exclusive lock on the selected rows. Relations using +lock+ are usually wrapped inside a transaction for preventing deadlock conditions.
575
569
 
576
570
  For example:
577
571
 
578
572
  <ruby>
579
573
  Item.transaction do
580
- i = Item.first(:lock => true)
574
+ i = Item.lock.first
581
575
  i.name = 'Jones'
582
576
  i.save
583
577
  end
@@ -592,25 +586,25 @@ Item Update (0.4ms) UPDATE `items` SET `updated_at` = '2009-02-07 18:05:56', `
592
586
  SQL (0.8ms) COMMIT
593
587
  </sql>
594
588
 
595
- You can also pass raw SQL to the +:lock+ option to allow different types of locks. For example, MySQL has an expression called +LOCK IN SHARE MODE+ where you can lock a record but still allow other queries to read it. To specify this expression just pass it in as the lock option:
589
+ You can also pass raw SQL to the +lock+ method for allowing different types of locks. For example, MySQL has an expression called +LOCK IN SHARE MODE+ where you can lock a record but still allow other queries to read it. To specify this expression just pass it in as the lock option:
596
590
 
597
591
  <ruby>
598
592
  Item.transaction do
599
- i = Item.find(1, :lock => "LOCK IN SHARE MODE")
593
+ i = Item.lock("LOCK IN SHARE MODE").find(1)
600
594
  i.increment!(:views)
601
595
  end
602
596
  </ruby>
603
597
 
604
598
  h3. Joining Tables
605
599
 
606
- <tt>Model.find</tt> provides a +:joins+ option for specifying +JOIN+ clauses on the resulting SQL. There are multiple ways to specify the +:joins+ option:
600
+ Active Record provides a finder method called +joins+ for specifying +JOIN+ clauses on the resulting SQL. There are multiple ways to use the +joins+ method.
607
601
 
608
602
  h4. Using a String SQL Fragment
609
603
 
610
- You can just supply the raw SQL specifying the +JOIN+ clause to the +:joins+ option. For example:
604
+ You can just supply the raw SQL specifying the +JOIN+ clause to +joins+:
611
605
 
612
606
  <ruby>
613
- Client.all(:joins => 'LEFT OUTER JOIN addresses ON addresses.client_id = clients.id')
607
+ Client.joins('LEFT OUTER JOIN addresses ON addresses.client_id = clients.id')
614
608
  </ruby>
615
609
 
616
610
  This will result in the following SQL:
@@ -625,7 +619,7 @@ WARNING: This method only works with +INNER JOIN+,
625
619
 
626
620
  <br />
627
621
 
628
- Active Record lets you use the names of the "associations":association_basics.html defined on the model as a shortcut for specifying the +:joins+ option.
622
+ Active Record lets you use the names of the "associations":association_basics.html defined on the model as a shortcut for specifying +JOIN+ clause for those associations when using the +joins+ method.
629
623
 
630
624
  For example, consider the following +Category+, +Post+, +Comments+ and +Guest+ models:
631
625
 
@@ -838,13 +832,13 @@ Client.exists?(1,2,3)
838
832
  Client.exists?([1,2,3])
839
833
  </ruby>
840
834
 
841
- The +exists+ method may also take a +conditions+ option much like find:
835
+ It's even possible to use +exists?+ without any arguments on a model or a relation.
842
836
 
843
837
  <ruby>
844
- Client.exists?(:conditions => "first_name = 'Ryan'")
838
+ Client.where(:first_name => 'Ryan').exists?
845
839
  </ruby>
846
840
 
847
- It's even possible to use +exists?+ without any arguments:
841
+ The above returns +true+ if there is at least one client with the +first_name+ 'Ryan' and +false+ otherwise.
848
842
 
849
843
  <ruby>
850
844
  Client.exists?
@@ -856,22 +850,24 @@ h3. Calculations
856
850
 
857
851
  This section uses count as an example method in this preamble, but the options described apply to all sub-sections.
858
852
 
859
- <tt>count</tt> takes conditions much in the same way +exists?+ does:
853
+ All calculation methods work directly on a model:
860
854
 
861
855
  <ruby>
862
- Client.count(:conditions => "first_name = 'Ryan'")
856
+ Client.count
857
+ # SELECT count(*) AS count_all FROM clients
863
858
  </ruby>
864
859
 
865
- Which will execute:
860
+ Or on a relation :
866
861
 
867
- <sql>
868
- SELECT count(*) AS count_all FROM clients WHERE (first_name = 'Ryan')
869
- </sql>
862
+ <ruby>
863
+ Client.where(:first_name => 'Ryan').count
864
+ # SELECT count(*) AS count_all FROM clients WHERE (first_name = 'Ryan')
865
+ </ruby>
870
866
 
871
- You can also use the +includes+ or +joins+ methods for this to do something a little more complex:
867
+ You can also use various finder methods on a relation for performing complex calculations:
872
868
 
873
869
  <ruby>
874
- Client.where("clients.first_name = 'Ryan' AND orders.status = 'received'").includes("orders").count
870
+ Client.includes("orders").where(:first_name => 'Ryan', :orders => {:status => 'received'}).count
875
871
  </ruby>
876
872
 
877
873
  Which will execute:
@@ -882,8 +878,6 @@ SELECT count(DISTINCT clients.id) AS count_all FROM clients
882
878
  (clients.first_name = 'Ryan' AND orders.status = 'received')
883
879
  </sql>
884
880
 
885
- This code specifies +clients.first_name+ just in case one of the join tables has a field also called +first_name+ and it uses +orders.status+ because that's the name of our join table.
886
-
887
881
  h4. Count
888
882
 
889
883
  If you want to see how many records are in your model's table you could call +Client.count+ and that will return the number. If you want to be more specific and find all the clients with their age present in the database you can use +Client.count(:age)+.