rails 4.1.16 → 4.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/guides/CHANGELOG.md +13 -102
  4. data/guides/Rakefile +2 -2
  5. data/guides/assets/javascripts/guides.js +6 -0
  6. data/guides/assets/stylesheets/main.css +4 -1
  7. data/guides/bug_report_templates/action_controller_gem.rb +2 -2
  8. data/guides/bug_report_templates/action_controller_master.rb +5 -2
  9. data/guides/bug_report_templates/active_record_master.rb +2 -0
  10. data/guides/rails_guides.rb +2 -2
  11. data/guides/rails_guides/helpers.rb +1 -1
  12. data/guides/rails_guides/levenshtein.rb +29 -21
  13. data/guides/rails_guides/markdown.rb +6 -7
  14. data/guides/rails_guides/markdown/renderer.rb +1 -1
  15. data/guides/source/2_3_release_notes.md +3 -3
  16. data/guides/source/3_0_release_notes.md +4 -4
  17. data/guides/source/3_1_release_notes.md +2 -2
  18. data/guides/source/3_2_release_notes.md +2 -2
  19. data/guides/source/4_1_release_notes.md +8 -9
  20. data/guides/source/4_2_release_notes.md +572 -0
  21. data/guides/source/_license.html.erb +1 -1
  22. data/guides/source/_welcome.html.erb +2 -8
  23. data/guides/source/action_controller_overview.md +79 -7
  24. data/guides/source/action_mailer_basics.md +36 -11
  25. data/guides/source/action_view_overview.md +138 -119
  26. data/guides/source/active_job_basics.md +253 -0
  27. data/guides/source/active_model_basics.md +23 -0
  28. data/guides/source/active_record_basics.md +16 -15
  29. data/guides/source/active_record_callbacks.md +12 -9
  30. data/guides/source/{migrations.md → active_record_migrations.md} +90 -217
  31. data/guides/source/active_record_postgresql.md +437 -0
  32. data/guides/source/active_record_querying.md +261 -261
  33. data/guides/source/active_record_validations.md +7 -7
  34. data/guides/source/active_support_core_extensions.md +105 -44
  35. data/guides/source/active_support_instrumentation.md +3 -2
  36. data/guides/source/api_documentation_guidelines.md +62 -16
  37. data/guides/source/asset_pipeline.md +58 -46
  38. data/guides/source/association_basics.md +47 -38
  39. data/guides/source/caching_with_rails.md +31 -6
  40. data/guides/source/command_line.md +56 -25
  41. data/guides/source/configuring.md +98 -19
  42. data/guides/source/contributing_to_ruby_on_rails.md +174 -111
  43. data/guides/source/credits.html.erb +1 -1
  44. data/guides/source/debugging_rails_applications.md +438 -284
  45. data/guides/source/development_dependencies_install.md +17 -4
  46. data/guides/source/documents.yaml +11 -7
  47. data/guides/source/engines.md +192 -203
  48. data/guides/source/form_helpers.md +54 -45
  49. data/guides/source/generators.md +20 -11
  50. data/guides/source/getting_started.md +330 -191
  51. data/guides/source/i18n.md +92 -62
  52. data/guides/source/index.html.erb +1 -0
  53. data/guides/source/initialization.md +108 -59
  54. data/guides/source/layout.html.erb +1 -4
  55. data/guides/source/layouts_and_rendering.md +24 -23
  56. data/guides/source/nested_model_forms.md +3 -3
  57. data/guides/source/plugins.md +26 -26
  58. data/guides/source/rails_application_templates.md +21 -3
  59. data/guides/source/rails_on_rack.md +1 -1
  60. data/guides/source/routing.md +97 -71
  61. data/guides/source/ruby_on_rails_guides_guidelines.md +10 -12
  62. data/guides/source/security.md +39 -33
  63. data/guides/source/testing.md +111 -108
  64. data/guides/source/upgrading_ruby_on_rails.md +131 -14
  65. data/guides/source/working_with_javascript_in_rails.md +18 -16
  66. data/guides/w3c_validator.rb +2 -0
  67. metadata +37 -94
  68. data/guides/bug_report_templates/generic_gem.rb +0 -15
  69. data/guides/bug_report_templates/generic_master.rb +0 -26
  70. data/guides/code/getting_started/Gemfile +0 -40
  71. data/guides/code/getting_started/Gemfile.lock +0 -125
  72. data/guides/code/getting_started/README.rdoc +0 -28
  73. data/guides/code/getting_started/Rakefile +0 -6
  74. data/guides/code/getting_started/app/assets/javascripts/application.js +0 -15
  75. data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
  76. data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
  77. data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
  78. data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
  79. data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
  80. data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
  81. data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
  82. data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
  83. data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -23
  84. data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -53
  85. data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
  86. data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
  87. data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
  88. data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
  89. data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
  90. data/guides/code/getting_started/app/models/comment.rb +0 -3
  91. data/guides/code/getting_started/app/models/post.rb +0 -7
  92. data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
  93. data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
  94. data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
  95. data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
  96. data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
  97. data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
  98. data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
  99. data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
  100. data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -4
  101. data/guides/code/getting_started/bin/bundle +0 -4
  102. data/guides/code/getting_started/bin/rails +0 -4
  103. data/guides/code/getting_started/bin/rake +0 -4
  104. data/guides/code/getting_started/config.ru +0 -4
  105. data/guides/code/getting_started/config/application.rb +0 -18
  106. data/guides/code/getting_started/config/boot.rb +0 -4
  107. data/guides/code/getting_started/config/database.yml +0 -25
  108. data/guides/code/getting_started/config/environment.rb +0 -5
  109. data/guides/code/getting_started/config/environments/development.rb +0 -30
  110. data/guides/code/getting_started/config/environments/production.rb +0 -80
  111. data/guides/code/getting_started/config/environments/test.rb +0 -36
  112. data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
  113. data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
  114. data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
  115. data/guides/code/getting_started/config/initializers/locale.rb +0 -9
  116. data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
  117. data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
  118. data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
  119. data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
  120. data/guides/code/getting_started/config/locales/en.yml +0 -23
  121. data/guides/code/getting_started/config/routes.rb +0 -7
  122. data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
  123. data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
  124. data/guides/code/getting_started/db/schema.rb +0 -33
  125. data/guides/code/getting_started/db/seeds.rb +0 -7
  126. data/guides/code/getting_started/public/404.html +0 -60
  127. data/guides/code/getting_started/public/422.html +0 -60
  128. data/guides/code/getting_started/public/500.html +0 -59
  129. data/guides/code/getting_started/public/favicon.ico +0 -0
  130. data/guides/code/getting_started/public/robots.txt +0 -5
  131. data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
  132. data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
  133. data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
  134. data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
  135. data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
  136. data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
  137. data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
  138. data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
  139. data/guides/code/getting_started/test/models/comment_test.rb +0 -7
  140. data/guides/code/getting_started/test/models/post_test.rb +0 -7
  141. data/guides/code/getting_started/test/test_helper.rb +0 -12
@@ -0,0 +1,253 @@
1
+ Active Job Basics
2
+ =================
3
+
4
+ This guide provides you with all you need to get started in creating,
5
+ enqueueing and executing background jobs.
6
+
7
+ After reading this guide, you will know:
8
+
9
+ * How to create jobs.
10
+ * How to enqueue jobs.
11
+ * How to run jobs in the background.
12
+ * How to send emails from your application async.
13
+
14
+ --------------------------------------------------------------------------------
15
+
16
+ Introduction
17
+ ------------
18
+
19
+ Active Job is a framework for declaring jobs and making them run on a variety
20
+ of queueing backends. These jobs can be everything from regularly scheduled
21
+ clean-ups, billing charges, or mailings. Anything that can be chopped up
22
+ into small units of work and run in parallel, really.
23
+
24
+
25
+ The Purpose of the Active Job
26
+ -----------------------------
27
+ The main point is to ensure that all Rails apps will have a job infrastructure
28
+ in place, even if it's in the form of an "immediate runner". We can then have
29
+ framework features and other gems build on top of that, without having to
30
+ worry about API differences between various job runners such as Delayed Job
31
+ and Resque. Picking your queuing backend becomes more of an operational concern,
32
+ then. And you'll be able to switch between them without having to rewrite your jobs.
33
+
34
+
35
+ Creating a Job
36
+ --------------
37
+
38
+ This section will provide a step-by-step guide to creating a job and enqueue it.
39
+
40
+ ### Create the Job
41
+
42
+ Active Job provides a Rails generator to create jobs. The following will create a
43
+ job in app/jobs:
44
+
45
+ ```bash
46
+ $ bin/rails generate job guests_cleanup
47
+ create app/jobs/guests_cleanup_job.rb
48
+ ```
49
+
50
+ You can also create a job that will run on a specific queue:
51
+
52
+ ```bash
53
+ $ bin/rails generate job guests_cleanup --queue urgent
54
+ create app/jobs/guests_cleanup_job.rb
55
+ ```
56
+
57
+ As you can see, you can generate jobs just like you use other generators with
58
+ Rails.
59
+
60
+ If you don't want to use a generator, you could create your own file inside of
61
+ app/jobs, just make sure that it inherits from `ActiveJob::Base`.
62
+
63
+ Here's how a job looks like:
64
+
65
+ ```ruby
66
+ class GuestsCleanupJob < ActiveJob::Base
67
+ queue_as :default
68
+
69
+ def perform
70
+ # Do something later
71
+ end
72
+ end
73
+ ```
74
+
75
+ ### Enqueue the Job
76
+
77
+ Enqueue a job like so:
78
+
79
+ ```ruby
80
+ MyJob.enqueue record # Enqueue a job to be performed as soon the queueing system is free.
81
+ ```
82
+
83
+ ```ruby
84
+ MyJob.enqueue_at Date.tomorrow.noon, record # Enqueue a job to be performed tomorrow at noon.
85
+ ```
86
+
87
+ ```ruby
88
+ MyJob.enqueue_in 1.week, record # Enqueue a job to be performed 1 week from now.
89
+ ```
90
+
91
+ That's it!
92
+
93
+
94
+ Job Execution
95
+ -------------
96
+
97
+ If not adapter is set, the job is immediately executed.
98
+
99
+ ### Backends
100
+
101
+ Active Job has adapters for the following queueing backends:
102
+
103
+ * [Backburner](https://github.com/nesquena/backburner)
104
+ * [Delayed Job](https://github.com/collectiveidea/delayed_job)
105
+ * [Qu](https://github.com/bkeepers/qu)
106
+ * [Que](https://github.com/chanks/que)
107
+ * [QueueClassic](https://github.com/ryandotsmith/queue_classic)
108
+ * [Resque 1.x](https://github.com/resque/resque)
109
+ * [Sidekiq](https://github.com/mperham/sidekiq)
110
+ * [Sneakers](https://github.com/jondot/sneakers)
111
+ * [Sucker Punch](https://github.com/brandonhilkert/sucker_punch)
112
+
113
+ #### Backends Features
114
+
115
+ | | Async | Queues | Delayed | Priorities | Timeout | Retries |
116
+ |-----------------------|-------|---------|---------|-------------|---------|---------|
117
+ | **Backburner** | Yes | Yes | Yes | Yes | Job | Global |
118
+ | **Delayed Job** | Yes | Yes | Yes | Job | Global | Global |
119
+ | **Que** | Yes | Yes | Yes | Job | No | Job |
120
+ | **Queue Classic** | Yes | Yes | Gem | No | No | No |
121
+ | **Resque** | Yes | Yes | Gem | Queue | Global | ? |
122
+ | **Sidekiq** | Yes | Yes | Yes | Queue | No | Job |
123
+ | **Sneakers** | Yes | Yes | No | Queue | Queue | No |
124
+ | **Sucker Punch** | Yes | Yes | Yes | No | No | No |
125
+ | **Active Job** | Yes | Yes | WIP | No | No | No |
126
+ | **Active Job Inline** | No | Yes | N/A | N/A | N/A | N/A |
127
+
128
+ ### Change Backends
129
+
130
+ You can easy change your adapter:
131
+
132
+ ```ruby
133
+ # be sure to have the adapter gem in your Gemfile and follow the adapter specific
134
+ # installation and deployment instructions
135
+ YourApp::Application.config.active_job.queue_adapter = :sidekiq
136
+ ```
137
+
138
+ Queues
139
+ ------
140
+
141
+ Most of the adapters supports multiple queues. With Active Job you can schedule the job
142
+ to run on a specific queue:
143
+
144
+ ```ruby
145
+ class GuestsCleanupJob < ActiveJob::Base
146
+ queue_as :low_priority
147
+ #....
148
+ end
149
+ ```
150
+
151
+ NOTE: Make sure your queueing backend "listens" on your queue name. For some backends
152
+ you need to specify the queues to listen to.
153
+
154
+
155
+ Callbacks
156
+ ---------
157
+
158
+ Active Job provides hooks during the lifecycle of a job. Callbacks allows you to trigger
159
+ logic during the lifecycle of a job.
160
+
161
+ ### Available callbacks
162
+
163
+ * before_enqueue
164
+ * around_enqueue
165
+ * after_enqueue
166
+ * before_perform
167
+ * around_perform
168
+ * after_perform
169
+
170
+ ### Usage
171
+
172
+ ```ruby
173
+ class GuestsCleanupJob < ActiveJob::Base
174
+ queue_as :default
175
+
176
+ before_enqueue do |job|
177
+ # do somthing with the job instance
178
+ end
179
+
180
+ around_perform do |job, block|
181
+ # do something before perform
182
+ block.call
183
+ # do something after perform
184
+ end
185
+
186
+ def perform
187
+ # Do something later
188
+ end
189
+ end
190
+ ```
191
+
192
+ ActionMailer
193
+ ------------
194
+ One of the most common jobs in a modern web application is sending emails outside
195
+ of the request-response cycle, so the user doesn't have to wait on it. Active Job
196
+ is integrated with Action Mailer so you can easily send emails async:
197
+
198
+ ```ruby
199
+ # Instead of the classic
200
+ UserMailer.welcome(@user).deliver
201
+
202
+ # use #deliver later to send the email async
203
+ UserMailer.welcome(@user).deliver_later
204
+ ```
205
+
206
+ GlobalID
207
+ --------
208
+ Active Job supports GlobalID for parameters. This makes it possible
209
+ to pass live Active Record objects to your job instead of class/id pairs, which
210
+ you then have to manually deserialize. Before, jobs would look like this:
211
+
212
+ ```ruby
213
+ class TrashableCleanupJob
214
+ def perform(trashable_class, trashable_id, depth)
215
+ trashable = trashable_class.constantize.find(trashable_id)
216
+ trashable.cleanup(depth)
217
+ end
218
+ end
219
+ ```
220
+
221
+ Now you can simply do:
222
+
223
+ ```ruby
224
+ class TrashableCleanupJob
225
+ def perform(trashable, depth)
226
+ trashable.cleanup(depth)
227
+ end
228
+ end
229
+ ```
230
+
231
+ This works with any class that mixes in ActiveModel::GlobalIdentification, which
232
+ by default has been mixed into Active Model classes.
233
+
234
+
235
+ Exceptions
236
+ ----------
237
+ Active Job provides a way to catch exceptions raised during the execution of the
238
+ job:
239
+
240
+ ```ruby
241
+
242
+ class GuestsCleanupJob < ActiveJob::Base
243
+ queue_as :default
244
+
245
+ rescue_from(ActiveRecord:NotFound) do |exception|
246
+ # do something with the exception
247
+ end
248
+
249
+ def perform
250
+ # Do something later
251
+ end
252
+ end
253
+ ```
@@ -198,3 +198,26 @@ person.valid? # => true
198
198
  person.token = nil
199
199
  person.valid? # => raises ActiveModel::StrictValidationFailed
200
200
  ```
201
+
202
+ ### ActiveModel::Naming
203
+
204
+ Naming adds a number of class methods which make the naming and routing
205
+ easier to manage. The module defines the `model_name` class method which
206
+ will define a number of accessors using some `ActiveSupport::Inflector` methods.
207
+
208
+ ```ruby
209
+ class Person
210
+ extend ActiveModel::Naming
211
+ end
212
+
213
+ Person.model_name.name # => "Person"
214
+ Person.model_name.singular # => "person"
215
+ Person.model_name.plural # => "people"
216
+ Person.model_name.element # => "person"
217
+ Person.model_name.human # => "Person"
218
+ Person.model_name.collection # => "people"
219
+ Person.model_name.param_key # => "person"
220
+ Person.model_name.i18n_key # => :person
221
+ Person.model_name.route_key # => "people"
222
+ Person.model_name.singular_route_key # => "person"
223
+ ```
@@ -82,13 +82,13 @@ by underscores. Examples:
82
82
  * Model Class - Singular with the first letter of each word capitalized (e.g.,
83
83
  `BookClub`).
84
84
 
85
- | Model / Class | Table / Schema |
86
- | ------------- | -------------- |
87
- | `Post` | `posts` |
88
- | `LineItem` | `line_items` |
89
- | `Deer` | `deers` |
90
- | `Mouse` | `mice` |
91
- | `Person` | `people` |
85
+ | Model / Class | Table / Schema |
86
+ | ---------------- | -------------- |
87
+ | `Article` | `articles` |
88
+ | `LineItem` | `line_items` |
89
+ | `Deer` | `deers` |
90
+ | `Mouse` | `mice` |
91
+ | `Person` | `people` |
92
92
 
93
93
 
94
94
  ### Schema Conventions
@@ -120,9 +120,9 @@ to Active Record instances:
120
120
  * `(association_name)_type` - Stores the type for
121
121
  [polymorphic associations](association_basics.html#polymorphic-associations).
122
122
  * `(table_name)_count` - Used to cache the number of belonging objects on
123
- associations. For example, a `comments_count` column in a `Post` class that
123
+ associations. For example, a `comments_count` column in a `Articles` class that
124
124
  has many instances of `Comment` will cache the number of existent comments
125
- for each post.
125
+ for each article.
126
126
 
127
127
  NOTE: While these column names are optional, they are in fact reserved by Active Record. Steer clear of reserved keywords unless you want the extra functionality. For example, `type` is a reserved keyword used to designate a table using Single Table Inheritance (STI). If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.
128
128
 
@@ -309,11 +309,11 @@ into the database. There are several methods that you can use to check your
309
309
  models and validate that an attribute value is not empty, is unique and not
310
310
  already in the database, follows a specific format and many more.
311
311
 
312
- Validation is a very important issue to consider when persisting to database, so
313
- the methods `create`, `save` and `update` take it into account when
312
+ Validation is a very important issue to consider when persisting to the database, so
313
+ the methods `save` and `update` take it into account when
314
314
  running: they return `false` when validation fails and they didn't actually
315
- perform any operation on database. All of these have a bang counterpart (that
316
- is, `create!`, `save!` and `update!`), which are stricter in that
315
+ perform any operation on the database. All of these have a bang counterpart (that
316
+ is, `save!` and `update!`), which are stricter in that
317
317
  they raise the exception `ActiveRecord::RecordInvalid` if validation fails.
318
318
  A quick example to illustrate:
319
319
 
@@ -322,8 +322,9 @@ class User < ActiveRecord::Base
322
322
  validates :name, presence: true
323
323
  end
324
324
 
325
- User.create # => false
326
- User.create! # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
325
+ user = User.new
326
+ user.save # => false
327
+ user.save! # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
327
328
  ```
328
329
 
329
330
  You can learn more about validations in the [Active Record Validations
@@ -15,7 +15,7 @@ After reading this guide, you will know:
15
15
  The Object Life Cycle
16
16
  ---------------------
17
17
 
18
- During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this <em>object life cycle</em> so that you can control your application and its data.
18
+ During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this *object life cycle* so that you can control your application and its data.
19
19
 
20
20
  Callbacks allow you to trigger logic before or after an alteration of an object's state.
21
21
 
@@ -92,6 +92,7 @@ Here is a list with all the available Active Record callbacks, listed in the sam
92
92
  * `around_create`
93
93
  * `after_create`
94
94
  * `after_save`
95
+ * `after_commit/after_rollback`
95
96
 
96
97
  ### Updating an Object
97
98
 
@@ -103,12 +104,14 @@ Here is a list with all the available Active Record callbacks, listed in the sam
103
104
  * `around_update`
104
105
  * `after_update`
105
106
  * `after_save`
107
+ * `after_commit/after_rollback`
106
108
 
107
109
  ### Destroying an Object
108
110
 
109
111
  * `before_destroy`
110
112
  * `around_destroy`
111
113
  * `after_destroy`
114
+ * `after_commit/after_rollback`
112
115
 
113
116
  WARNING. `after_save` runs both on create and update, but always _after_ the more specific callbacks `after_create` and `after_update`, no matter the order in which the macro calls were executed.
114
117
 
@@ -258,27 +261,27 @@ WARNING. Any exception that is not `ActiveRecord::Rollback` will be re-raised by
258
261
  Relational Callbacks
259
262
  --------------------
260
263
 
261
- Callbacks work through model relationships, and can even be defined by them. Suppose an example where a user has many posts. A user's posts should be destroyed if the user is destroyed. Let's add an `after_destroy` callback to the `User` model by way of its relationship to the `Post` model:
264
+ Callbacks work through model relationships, and can even be defined by them. Suppose an example where a user has many articles. A user's articles should be destroyed if the user is destroyed. Let's add an `after_destroy` callback to the `User` model by way of its relationship to the `Article` model:
262
265
 
263
266
  ```ruby
264
267
  class User < ActiveRecord::Base
265
- has_many :posts, dependent: :destroy
268
+ has_many :articles, dependent: :destroy
266
269
  end
267
270
 
268
- class Post < ActiveRecord::Base
271
+ class Article < ActiveRecord::Base
269
272
  after_destroy :log_destroy_action
270
273
 
271
274
  def log_destroy_action
272
- puts 'Post destroyed'
275
+ puts 'Article destroyed'
273
276
  end
274
277
  end
275
278
 
276
279
  >> user = User.first
277
280
  => #<User id: 1>
278
- >> user.posts.create!
279
- => #<Post id: 1, user_id: 1>
281
+ >> user.articles.create!
282
+ => #<Article id: 1, user_id: 1>
280
283
  >> user.destroy
281
- Post destroyed
284
+ Article destroyed
282
285
  => #<User id: 1>
283
286
  ```
284
287
 
@@ -325,7 +328,7 @@ When writing conditional callbacks, it is possible to mix both `:if` and `:unles
325
328
  ```ruby
326
329
  class Comment < ActiveRecord::Base
327
330
  after_create :send_email_to_author, if: :author_wants_emails?,
328
- unless: Proc.new { |comment| comment.post.ignore_comments? }
331
+ unless: Proc.new { |comment| comment.article.ignore_comments? }
329
332
  end
330
333
  ```
331
334
 
@@ -18,9 +18,10 @@ After reading this guide, you will know:
18
18
  Migration Overview
19
19
  ------------------
20
20
 
21
- Migrations are a convenient way to alter your database schema over time in a
22
- consistent and easy way. They use a Ruby DSL so that you don't have to write
23
- SQL by hand, allowing your schema and changes to be database independent.
21
+ Migrations are a convenient way to
22
+ [alter your database schema over time](http://en.wikipedia.org/wiki/Schema_migration)
23
+ in a consistent and easy way. They use a Ruby DSL so that you don't have to
24
+ write SQL by hand, allowing your schema and changes to be database independent.
24
25
 
25
26
  You can think of each migration as being a new 'version' of the database. A
26
27
  schema starts off with nothing in it, and each migration modifies it to add or
@@ -433,21 +434,62 @@ change_column_default :products, :approved, false
433
434
  This sets `:name` field on products to a `NOT NULL` column and the default
434
435
  value of the `:approved` field to false.
435
436
 
437
+ TIP: Unlike `change_column` (and `change_column_default`), `change_column_null`
438
+ is reversible.
439
+
436
440
  ### Column Modifiers
437
441
 
438
442
  Column modifiers can be applied when creating or changing a column:
439
443
 
440
444
  * `limit` Sets the maximum size of the `string/text/binary/integer` fields.
441
- * `precision` Defines the precision for the `decimal` fields, representing the total number of digits in the number.
442
- * `scale` Defines the scale for the `decimal` fields, representing the number of digits after the decimal point.
445
+ * `precision` Defines the precision for the `decimal` fields, representing the
446
+ total number of digits in the number.
447
+ * `scale` Defines the scale for the `decimal` fields, representing the
448
+ number of digits after the decimal point.
443
449
  * `polymorphic` Adds a `type` column for `belongs_to` associations.
444
450
  * `null` Allows or disallows `NULL` values in the column.
445
- * `default` Allows to set a default value on the column. NOTE: If using a dynamic value (such as date), the default will only be calculated the first time (e.g. on the date the migration is applied.)
451
+ * `default` Allows to set a default value on the column. Note that if you
452
+ are using a dynamic value (such as a date), the default will only be calculated
453
+ the first time (i.e. on the date the migration is applied).
446
454
  * `index` Adds an index for the column.
447
455
 
448
456
  Some adapters may support additional options; see the adapter specific API docs
449
457
  for further information.
450
458
 
459
+ ### Foreign Keys
460
+
461
+ While it's not required you might want to add foreign key constraints to
462
+ [guarantee referential integrity](#active-record-and-referential-integrity).
463
+
464
+ ```ruby
465
+ add_foreign_key :articles, :authors
466
+ ```
467
+
468
+ This adds a new foreign key to the `author_id` column of the `articles`
469
+ table. The key references the `id` column of the `articles` table. If the
470
+ column names can not be derived from the table names, you can use the
471
+ `:column` and `:primary_key` options.
472
+
473
+ Rails will generate a name for every foreign key starting with
474
+ `fk_rails_` followed by 10 random characters.
475
+ There is a `:name` option to specify a different name if needed.
476
+
477
+ NOTE: Active Record only supports single column foreign keys. `execute` and
478
+ `structure.sql` are required to use composite foreign keys.
479
+
480
+ Removing a foreign key is easy as well:
481
+
482
+ ```ruby
483
+ # let Active Record figure out the column name
484
+ remove_foreign_key :accounts, :branches
485
+
486
+ # remove foreign key for a specific column
487
+ remove_foreign_key :accounts, column: :owner_id
488
+
489
+ # remove foreign key by name
490
+ remove_foreign_key :accounts, name: :special_fk_name
491
+ ```
492
+
451
493
  ### When Helpers aren't Enough
452
494
 
453
495
  If the helpers provided by Active Record aren't enough you can use the `execute`
@@ -478,6 +520,7 @@ definitions:
478
520
  * `add_index`
479
521
  * `add_reference`
480
522
  * `add_timestamps`
523
+ * `add_foreign_key`
481
524
  * `create_table`
482
525
  * `create_join_table`
483
526
  * `drop_table` (must supply a block)
@@ -503,24 +546,23 @@ migration what else to do when reverting it. For example:
503
546
  ```ruby
504
547
  class ExampleMigration < ActiveRecord::Migration
505
548
  def change
506
- create_table :products do |t|
507
- t.references :category
549
+ create_table :distributors do |t|
550
+ t.string :zipcode
508
551
  end
509
552
 
510
553
  reversible do |dir|
511
554
  dir.up do
512
- #add a foreign key
555
+ # add a CHECK constraint
513
556
  execute <<-SQL
514
- ALTER TABLE products
515
- ADD CONSTRAINT fk_products_categories
516
- FOREIGN KEY (category_id)
517
- REFERENCES categories(id)
557
+ ALTER TABLE distributors
558
+ ADD CONSTRAINT zipchk
559
+ CHECK (char_length(zipcode) = 5) NO INHERIT;
518
560
  SQL
519
561
  end
520
562
  dir.down do
521
563
  execute <<-SQL
522
- ALTER TABLE products
523
- DROP FOREIGN KEY fk_products_categories
564
+ ALTER TABLE distributors
565
+ DROP CONSTRAINT zipchk
524
566
  SQL
525
567
  end
526
568
  end
@@ -534,7 +576,7 @@ end
534
576
  Using `reversible` will ensure that the instructions are executed in the
535
577
  right order too. If the previous example migration is reverted,
536
578
  the `down` block will be run after the `home_page_url` column is removed and
537
- right before the table `products` is dropped.
579
+ right before the table `distributors` is dropped.
538
580
 
539
581
  Sometimes your migration will do something which is just plain irreversible; for
540
582
  example, it might destroy some data. In such cases, you can raise
@@ -557,16 +599,15 @@ made in the `up` method. The example in the `reversible` section is equivalent t
557
599
  ```ruby
558
600
  class ExampleMigration < ActiveRecord::Migration
559
601
  def up
560
- create_table :products do |t|
561
- t.references :category
602
+ create_table :distributors do |t|
603
+ t.string :zipcode
562
604
  end
563
605
 
564
- # add a foreign key
606
+ # add a CHECK constraint
565
607
  execute <<-SQL
566
- ALTER TABLE products
567
- ADD CONSTRAINT fk_products_categories
568
- FOREIGN KEY (category_id)
569
- REFERENCES categories(id)
608
+ ALTER TABLE distributors
609
+ ADD CONSTRAINT zipchk
610
+ CHECK (char_length(zipcode) = 5);
570
611
  SQL
571
612
 
572
613
  add_column :users, :home_page_url, :string
@@ -578,11 +619,11 @@ class ExampleMigration < ActiveRecord::Migration
578
619
  remove_column :users, :home_page_url
579
620
 
580
621
  execute <<-SQL
581
- ALTER TABLE products
582
- DROP FOREIGN KEY fk_products_categories
622
+ ALTER TABLE distributors
623
+ DROP CONSTRAINT zipchk
583
624
  SQL
584
625
 
585
- drop_table :products
626
+ drop_table :distributors
586
627
  end
587
628
  end
588
629
  ```
@@ -613,43 +654,27 @@ end
613
654
  The `revert` method also accepts a block of instructions to reverse.
614
655
  This could be useful to revert selected parts of previous migrations.
615
656
  For example, let's imagine that `ExampleMigration` is committed and it
616
- is later decided it would be best to serialize the product list instead.
617
- One could write:
657
+ is later decided it would be best to use Active Record validations,
658
+ in place of the `CHECK` constraint, to verify the zipcode.
618
659
 
619
660
  ```ruby
620
- class SerializeProductListMigration < ActiveRecord::Migration
661
+ class DontUseConstraintForZipcodeValidationMigration < ActiveRecord::Migration
621
662
  def change
622
- add_column :categories, :product_list
623
-
624
- reversible do |dir|
625
- dir.up do
626
- # transfer data from Products to Category#product_list
627
- end
628
- dir.down do
629
- # create Products from Category#product_list
630
- end
631
- end
632
-
633
663
  revert do
634
664
  # copy-pasted code from ExampleMigration
635
- create_table :products do |t|
636
- t.references :category
637
- end
638
-
639
665
  reversible do |dir|
640
666
  dir.up do
641
- #add a foreign key
667
+ # add a CHECK constraint
642
668
  execute <<-SQL
643
- ALTER TABLE products
644
- ADD CONSTRAINT fk_products_categories
645
- FOREIGN KEY (category_id)
646
- REFERENCES categories(id)
669
+ ALTER TABLE distributors
670
+ ADD CONSTRAINT zipchk
671
+ CHECK (char_length(zipcode) = 5);
647
672
  SQL
648
673
  end
649
674
  dir.down do
650
675
  execute <<-SQL
651
- ALTER TABLE products
652
- DROP FOREIGN KEY fk_products_categories
676
+ ALTER TABLE distributors
677
+ DROP CONSTRAINT zipchk
653
678
  SQL
654
679
  end
655
680
  end
@@ -853,159 +878,6 @@ The `revert` method can be helpful when writing a new migration to undo
853
878
  previous migrations in whole or in part
854
879
  (see [Reverting Previous Migrations](#reverting-previous-migrations) above).
855
880
 
856
- Using Models in Your Migrations
857
- -------------------------------
858
-
859
- When creating or updating data in a migration it is often tempting to use one
860
- of your models. After all, they exist to provide easy access to the underlying
861
- data. This can be done, but some caution should be observed.
862
-
863
- For example, problems occur when the model uses database columns which are (1)
864
- not currently in the database and (2) will be created by this or a subsequent
865
- migration.
866
-
867
- Consider this example, where Alice and Bob are working on the same code base
868
- which contains a `Product` model:
869
-
870
- Bob goes on vacation.
871
-
872
- Alice creates a migration for the `products` table which adds a new column and
873
- initializes it:
874
-
875
- ```ruby
876
- # db/migrate/20100513121110_add_flag_to_product.rb
877
-
878
- class AddFlagToProduct < ActiveRecord::Migration
879
- def change
880
- add_column :products, :flag, :boolean
881
- reversible do |dir|
882
- dir.up { Product.update_all flag: false }
883
- end
884
- end
885
- end
886
- ```
887
-
888
- She also adds a validation to the `Product` model for the new column:
889
-
890
- ```ruby
891
- # app/models/product.rb
892
-
893
- class Product < ActiveRecord::Base
894
- validates :flag, inclusion: { in: [true, false] }
895
- end
896
- ```
897
-
898
- Alice adds a second migration which adds another column to the `products`
899
- table and initializes it:
900
-
901
- ```ruby
902
- # db/migrate/20100515121110_add_fuzz_to_product.rb
903
-
904
- class AddFuzzToProduct < ActiveRecord::Migration
905
- def change
906
- add_column :products, :fuzz, :string
907
- reversible do |dir|
908
- dir.up { Product.update_all fuzz: 'fuzzy' }
909
- end
910
- end
911
- end
912
- ```
913
-
914
- She also adds a validation to the `Product` model for the new column:
915
-
916
- ```ruby
917
- # app/models/product.rb
918
-
919
- class Product < ActiveRecord::Base
920
- validates :flag, inclusion: { in: [true, false] }
921
- validates :fuzz, presence: true
922
- end
923
- ```
924
-
925
- Both migrations work for Alice.
926
-
927
- Bob comes back from vacation and:
928
-
929
- * Updates the source - which contains both migrations and the latest version
930
- of the Product model.
931
- * Runs outstanding migrations with `rake db:migrate`, which
932
- includes the one that updates the `Product` model.
933
-
934
- The migration crashes because when the model attempts to save, it tries to
935
- validate the second added column, which is not in the database when the _first_
936
- migration runs:
937
-
938
- ```
939
- rake aborted!
940
- An error has occurred, this and all later migrations canceled:
941
-
942
- undefined method `fuzz' for #<Product:0x000001049b14a0>
943
- ```
944
-
945
- A fix for this is to create a local model within the migration. This keeps
946
- Rails from running the validations, so that the migrations run to completion.
947
-
948
- When using a local model, it's a good idea to call
949
- `Product.reset_column_information` to refresh the Active Record cache for the
950
- `Product` model prior to updating data in the database.
951
-
952
- If Alice had done this instead, there would have been no problem:
953
-
954
- ```ruby
955
- # db/migrate/20100513121110_add_flag_to_product.rb
956
-
957
- class AddFlagToProduct < ActiveRecord::Migration
958
- class Product < ActiveRecord::Base
959
- end
960
-
961
- def change
962
- add_column :products, :flag, :boolean
963
- Product.reset_column_information
964
- reversible do |dir|
965
- dir.up { Product.update_all flag: false }
966
- end
967
- end
968
- end
969
- ```
970
-
971
- ```ruby
972
- # db/migrate/20100515121110_add_fuzz_to_product.rb
973
-
974
- class AddFuzzToProduct < ActiveRecord::Migration
975
- class Product < ActiveRecord::Base
976
- end
977
-
978
- def change
979
- add_column :products, :fuzz, :string
980
- Product.reset_column_information
981
- reversible do |dir|
982
- dir.up { Product.update_all fuzz: 'fuzzy' }
983
- end
984
- end
985
- end
986
- ```
987
-
988
- There are other ways in which the above example could have gone badly.
989
-
990
- For example, imagine that Alice creates a migration that selectively
991
- updates the `description` field on certain products. She runs the
992
- migration, commits the code, and then begins working on the next feature,
993
- which is to add a new column `fuzz` to the products table.
994
-
995
- She creates two migrations for this new feature, one which adds the new
996
- column, and a second which selectively updates the `fuzz` column based on
997
- other product attributes.
998
-
999
- These migrations run just fine, but when Bob comes back from his vacation
1000
- and calls `rake db:migrate` to run all the outstanding migrations, he gets a
1001
- subtle bug: The descriptions have defaults, and the `fuzz` column is present,
1002
- but `fuzz` is `nil` on all products.
1003
-
1004
- The solution is again to use `Product.reset_column_information` before
1005
- referencing the Product model in a migration, ensuring the Active Record's
1006
- knowledge of the table structure is current before manipulating data in those
1007
- records.
1008
-
1009
881
  Schema Dumping and You
1010
882
  ----------------------
1011
883
 
@@ -1067,10 +939,10 @@ that Active Record supports. This could be very useful if you were to
1067
939
  distribute an application that is able to run against multiple databases.
1068
940
 
1069
941
  There is however a trade-off: `db/schema.rb` cannot express database specific
1070
- items such as foreign key constraints, triggers, or stored procedures. While in
1071
- a migration you can execute custom SQL statements, the schema dumper cannot
1072
- reconstitute those statements from the database. If you are using features like
1073
- this, then you should set the schema format to `:sql`.
942
+ items such as triggers, or stored procedures. While in a migration you can
943
+ execute custom SQL statements, the schema dumper cannot reconstitute those
944
+ statements from the database. If you are using features like this, then you
945
+ should set the schema format to `:sql`.
1074
946
 
1075
947
  Instead of using Active Record's schema dumper, the database's structure will
1076
948
  be dumped using a tool specific to the database (via the `db:structure:dump`
@@ -1088,11 +960,16 @@ schema into a RDBMS other than the one used to create it.
1088
960
  Because schema dumps are the authoritative source for your database schema, it
1089
961
  is strongly recommended that you check them into source control.
1090
962
 
963
+ `db/schema.rb` contains the current version number of the database. This
964
+ ensures conflicts are going to happen in the case of a merge where both
965
+ branches touched the schema. When that happens, solve conflicts manually,
966
+ keeping the highest version number of the two.
967
+
1091
968
  Active Record and Referential Integrity
1092
969
  ---------------------------------------
1093
970
 
1094
971
  The Active Record way claims that intelligence belongs in your models, not in
1095
- the database. As such, features such as triggers or foreign key constraints,
972
+ the database. As such, features such as triggers or constraints,
1096
973
  which push some of that intelligence back into the database, are not heavily
1097
974
  used.
1098
975
 
@@ -1101,14 +978,10 @@ which models can enforce data integrity. The `:dependent` option on
1101
978
  associations allows models to automatically destroy child objects when the
1102
979
  parent is destroyed. Like anything which operates at the application level,
1103
980
  these cannot guarantee referential integrity and so some people augment them
1104
- with foreign key constraints in the database.
1105
-
1106
- Although Active Record does not provide any tools for working directly with
1107
- such features, the `execute` method can be used to execute arbitrary SQL. You
1108
- can also use a gem like
1109
- [foreigner](https://github.com/matthuhiggins/foreigner) which adds foreign key
1110
- support to Active Record (including support for dumping foreign keys in
1111
- `db/schema.rb`).
981
+ with [foreign key constraints](#foreign-keys) in the database.
982
+
983
+ Although Active Record does not provide all the tools for working directly with
984
+ such features, the `execute` method can be used to execute arbitrary SQL.
1112
985
 
1113
986
  Migrations and Seed Data
1114
987
  ------------------------