rails_test 4.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (215) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +83 -0
  3. data/guides/CHANGELOG.md +27 -0
  4. data/guides/Rakefile +77 -0
  5. data/guides/assets/images/akshaysurve.jpg +0 -0
  6. data/guides/assets/images/belongs_to.png +0 -0
  7. data/guides/assets/images/book_icon.gif +0 -0
  8. data/guides/assets/images/bullet.gif +0 -0
  9. data/guides/assets/images/chapters_icon.gif +0 -0
  10. data/guides/assets/images/check_bullet.gif +0 -0
  11. data/guides/assets/images/credits_pic_blank.gif +0 -0
  12. data/guides/assets/images/csrf.png +0 -0
  13. data/guides/assets/images/edge_badge.png +0 -0
  14. data/guides/assets/images/favicon.ico +0 -0
  15. data/guides/assets/images/feature_tile.gif +0 -0
  16. data/guides/assets/images/footer_tile.gif +0 -0
  17. data/guides/assets/images/fxn.png +0 -0
  18. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  19. data/guides/assets/images/getting_started/challenge.png +0 -0
  20. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  21. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  22. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  23. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  24. data/guides/assets/images/getting_started/new_article.png +0 -0
  25. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  26. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  27. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  28. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  29. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  30. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  31. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  32. data/guides/assets/images/grey_bullet.gif +0 -0
  33. data/guides/assets/images/habtm.png +0 -0
  34. data/guides/assets/images/has_many.png +0 -0
  35. data/guides/assets/images/has_many_through.png +0 -0
  36. data/guides/assets/images/has_one.png +0 -0
  37. data/guides/assets/images/has_one_through.png +0 -0
  38. data/guides/assets/images/header_backdrop.png +0 -0
  39. data/guides/assets/images/header_tile.gif +0 -0
  40. data/guides/assets/images/i18n/demo_html_safe.png +0 -0
  41. data/guides/assets/images/i18n/demo_localized_pirate.png +0 -0
  42. data/guides/assets/images/i18n/demo_translated_en.png +0 -0
  43. data/guides/assets/images/i18n/demo_translated_pirate.png +0 -0
  44. data/guides/assets/images/i18n/demo_translation_missing.png +0 -0
  45. data/guides/assets/images/i18n/demo_untranslated.png +0 -0
  46. data/guides/assets/images/icons/README +5 -0
  47. data/guides/assets/images/icons/callouts/1.png +0 -0
  48. data/guides/assets/images/icons/callouts/10.png +0 -0
  49. data/guides/assets/images/icons/callouts/11.png +0 -0
  50. data/guides/assets/images/icons/callouts/12.png +0 -0
  51. data/guides/assets/images/icons/callouts/13.png +0 -0
  52. data/guides/assets/images/icons/callouts/14.png +0 -0
  53. data/guides/assets/images/icons/callouts/15.png +0 -0
  54. data/guides/assets/images/icons/callouts/2.png +0 -0
  55. data/guides/assets/images/icons/callouts/3.png +0 -0
  56. data/guides/assets/images/icons/callouts/4.png +0 -0
  57. data/guides/assets/images/icons/callouts/5.png +0 -0
  58. data/guides/assets/images/icons/callouts/6.png +0 -0
  59. data/guides/assets/images/icons/callouts/7.png +0 -0
  60. data/guides/assets/images/icons/callouts/8.png +0 -0
  61. data/guides/assets/images/icons/callouts/9.png +0 -0
  62. data/guides/assets/images/icons/caution.png +0 -0
  63. data/guides/assets/images/icons/example.png +0 -0
  64. data/guides/assets/images/icons/home.png +0 -0
  65. data/guides/assets/images/icons/important.png +0 -0
  66. data/guides/assets/images/icons/next.png +0 -0
  67. data/guides/assets/images/icons/note.png +0 -0
  68. data/guides/assets/images/icons/prev.png +0 -0
  69. data/guides/assets/images/icons/tip.png +0 -0
  70. data/guides/assets/images/icons/up.png +0 -0
  71. data/guides/assets/images/icons/warning.png +0 -0
  72. data/guides/assets/images/nav_arrow.gif +0 -0
  73. data/guides/assets/images/oscardelben.jpg +0 -0
  74. data/guides/assets/images/polymorphic.png +0 -0
  75. data/guides/assets/images/radar.png +0 -0
  76. data/guides/assets/images/rails4_features.png +0 -0
  77. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  78. data/guides/assets/images/rails_guides_logo.gif +0 -0
  79. data/guides/assets/images/rails_logo_remix.gif +0 -0
  80. data/guides/assets/images/session_fixation.png +0 -0
  81. data/guides/assets/images/tab_grey.gif +0 -0
  82. data/guides/assets/images/tab_info.gif +0 -0
  83. data/guides/assets/images/tab_note.gif +0 -0
  84. data/guides/assets/images/tab_red.gif +0 -0
  85. data/guides/assets/images/tab_yellow.gif +0 -0
  86. data/guides/assets/images/tab_yellow.png +0 -0
  87. data/guides/assets/images/vijaydev.jpg +0 -0
  88. data/guides/assets/javascripts/guides.js +59 -0
  89. data/guides/assets/javascripts/jquery.min.js +4 -0
  90. data/guides/assets/javascripts/responsive-tables.js +43 -0
  91. data/guides/assets/javascripts/syntaxhighlighter/shBrushAS3.js +59 -0
  92. data/guides/assets/javascripts/syntaxhighlighter/shBrushAppleScript.js +75 -0
  93. data/guides/assets/javascripts/syntaxhighlighter/shBrushBash.js +59 -0
  94. data/guides/assets/javascripts/syntaxhighlighter/shBrushCSharp.js +65 -0
  95. data/guides/assets/javascripts/syntaxhighlighter/shBrushColdFusion.js +100 -0
  96. data/guides/assets/javascripts/syntaxhighlighter/shBrushCpp.js +97 -0
  97. data/guides/assets/javascripts/syntaxhighlighter/shBrushCss.js +91 -0
  98. data/guides/assets/javascripts/syntaxhighlighter/shBrushDelphi.js +55 -0
  99. data/guides/assets/javascripts/syntaxhighlighter/shBrushDiff.js +41 -0
  100. data/guides/assets/javascripts/syntaxhighlighter/shBrushErlang.js +52 -0
  101. data/guides/assets/javascripts/syntaxhighlighter/shBrushGroovy.js +67 -0
  102. data/guides/assets/javascripts/syntaxhighlighter/shBrushJScript.js +52 -0
  103. data/guides/assets/javascripts/syntaxhighlighter/shBrushJava.js +57 -0
  104. data/guides/assets/javascripts/syntaxhighlighter/shBrushJavaFX.js +58 -0
  105. data/guides/assets/javascripts/syntaxhighlighter/shBrushPerl.js +72 -0
  106. data/guides/assets/javascripts/syntaxhighlighter/shBrushPhp.js +88 -0
  107. data/guides/assets/javascripts/syntaxhighlighter/shBrushPlain.js +33 -0
  108. data/guides/assets/javascripts/syntaxhighlighter/shBrushPowerShell.js +74 -0
  109. data/guides/assets/javascripts/syntaxhighlighter/shBrushPython.js +64 -0
  110. data/guides/assets/javascripts/syntaxhighlighter/shBrushRuby.js +55 -0
  111. data/guides/assets/javascripts/syntaxhighlighter/shBrushSass.js +94 -0
  112. data/guides/assets/javascripts/syntaxhighlighter/shBrushScala.js +51 -0
  113. data/guides/assets/javascripts/syntaxhighlighter/shBrushSql.js +66 -0
  114. data/guides/assets/javascripts/syntaxhighlighter/shBrushVb.js +56 -0
  115. data/guides/assets/javascripts/syntaxhighlighter/shBrushXml.js +69 -0
  116. data/guides/assets/javascripts/syntaxhighlighter/shCore.js +17 -0
  117. data/guides/assets/stylesheets/fixes.css +16 -0
  118. data/guides/assets/stylesheets/kindle.css +11 -0
  119. data/guides/assets/stylesheets/main.css +713 -0
  120. data/guides/assets/stylesheets/print.css +52 -0
  121. data/guides/assets/stylesheets/reset.css +43 -0
  122. data/guides/assets/stylesheets/responsive-tables.css +50 -0
  123. data/guides/assets/stylesheets/style.css +13 -0
  124. data/guides/assets/stylesheets/syntaxhighlighter/shCore.css +226 -0
  125. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDefault.css +328 -0
  126. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDjango.css +331 -0
  127. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEclipse.css +339 -0
  128. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEmacs.css +324 -0
  129. data/guides/assets/stylesheets/syntaxhighlighter/shCoreFadeToGrey.css +328 -0
  130. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMDUltra.css +324 -0
  131. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMidnight.css +324 -0
  132. data/guides/assets/stylesheets/syntaxhighlighter/shCoreRDark.css +324 -0
  133. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDefault.css +117 -0
  134. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDjango.css +120 -0
  135. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEclipse.css +128 -0
  136. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEmacs.css +113 -0
  137. data/guides/assets/stylesheets/syntaxhighlighter/shThemeFadeToGrey.css +117 -0
  138. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMDUltra.css +113 -0
  139. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMidnight.css +113 -0
  140. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRDark.css +113 -0
  141. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRailsGuides.css +116 -0
  142. data/guides/bug_report_templates/action_controller_gem.rb +47 -0
  143. data/guides/bug_report_templates/action_controller_master.rb +56 -0
  144. data/guides/bug_report_templates/active_record_gem.rb +40 -0
  145. data/guides/bug_report_templates/active_record_master.rb +51 -0
  146. data/guides/rails_guides.rb +63 -0
  147. data/guides/rails_guides/generator.rb +248 -0
  148. data/guides/rails_guides/helpers.rb +53 -0
  149. data/guides/rails_guides/indexer.rb +68 -0
  150. data/guides/rails_guides/kindle.rb +119 -0
  151. data/guides/rails_guides/levenshtein.rb +39 -0
  152. data/guides/rails_guides/markdown.rb +167 -0
  153. data/guides/rails_guides/markdown/renderer.rb +82 -0
  154. data/guides/source/2_2_release_notes.md +435 -0
  155. data/guides/source/2_3_release_notes.md +621 -0
  156. data/guides/source/3_0_release_notes.md +611 -0
  157. data/guides/source/3_1_release_notes.md +559 -0
  158. data/guides/source/3_2_release_notes.md +568 -0
  159. data/guides/source/4_0_release_notes.md +279 -0
  160. data/guides/source/4_1_release_notes.md +730 -0
  161. data/guides/source/4_2_release_notes.md +736 -0
  162. data/guides/source/_license.html.erb +2 -0
  163. data/guides/source/_welcome.html.erb +19 -0
  164. data/guides/source/action_controller_overview.md +1247 -0
  165. data/guides/source/action_mailer_basics.md +738 -0
  166. data/guides/source/action_view_overview.md +1621 -0
  167. data/guides/source/active_job_basics.md +285 -0
  168. data/guides/source/active_model_basics.md +223 -0
  169. data/guides/source/active_record_basics.md +374 -0
  170. data/guides/source/active_record_callbacks.md +413 -0
  171. data/guides/source/active_record_migrations.md +1016 -0
  172. data/guides/source/active_record_postgresql.md +438 -0
  173. data/guides/source/active_record_querying.md +1785 -0
  174. data/guides/source/active_record_validations.md +1169 -0
  175. data/guides/source/active_support_core_extensions.md +3924 -0
  176. data/guides/source/active_support_instrumentation.md +497 -0
  177. data/guides/source/api_documentation_guidelines.md +361 -0
  178. data/guides/source/asset_pipeline.md +1361 -0
  179. data/guides/source/association_basics.md +2238 -0
  180. data/guides/source/caching_with_rails.md +379 -0
  181. data/guides/source/command_line.md +634 -0
  182. data/guides/source/configuring.md +1019 -0
  183. data/guides/source/contributing_to_ruby_on_rails.md +607 -0
  184. data/guides/source/credits.html.erb +80 -0
  185. data/guides/source/debugging_rails_applications.md +861 -0
  186. data/guides/source/development_dependencies_install.md +289 -0
  187. data/guides/source/documents.yaml +197 -0
  188. data/guides/source/engines.md +1401 -0
  189. data/guides/source/form_helpers.md +1010 -0
  190. data/guides/source/generators.md +676 -0
  191. data/guides/source/getting_started.md +2085 -0
  192. data/guides/source/i18n.md +1073 -0
  193. data/guides/source/index.html.erb +28 -0
  194. data/guides/source/initialization.md +704 -0
  195. data/guides/source/kindle/copyright.html.erb +1 -0
  196. data/guides/source/kindle/layout.html.erb +27 -0
  197. data/guides/source/kindle/rails_guides.opf.erb +52 -0
  198. data/guides/source/kindle/toc.html.erb +24 -0
  199. data/guides/source/kindle/toc.ncx.erb +64 -0
  200. data/guides/source/kindle/welcome.html.erb +5 -0
  201. data/guides/source/layout.html.erb +143 -0
  202. data/guides/source/layouts_and_rendering.md +1227 -0
  203. data/guides/source/maintenance_policy.md +75 -0
  204. data/guides/source/nested_model_forms.md +228 -0
  205. data/guides/source/plugins.md +444 -0
  206. data/guides/source/rails_application_templates.md +266 -0
  207. data/guides/source/rails_on_rack.md +332 -0
  208. data/guides/source/routing.md +1141 -0
  209. data/guides/source/ruby_on_rails_guides_guidelines.md +126 -0
  210. data/guides/source/security.md +1024 -0
  211. data/guides/source/testing.md +1055 -0
  212. data/guides/source/upgrading_ruby_on_rails.md +1046 -0
  213. data/guides/source/working_with_javascript_in_rails.md +407 -0
  214. data/guides/w3c_validator.rb +97 -0
  215. metadata +404 -0
@@ -0,0 +1,285 @@
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
+
17
+ Introduction
18
+ ------------
19
+
20
+ Active Job is a framework for declaring jobs and making them run on a variety
21
+ of queueing backends. These jobs can be everything from regularly scheduled
22
+ clean-ups, to billing charges, to mailings. Anything that can be chopped up
23
+ into small units of work and run in parallel, really.
24
+
25
+
26
+ The Purpose of the Active Job
27
+ -----------------------------
28
+ The main point is to ensure that all Rails apps will have a job infrastructure
29
+ in place, even if it's in the form of an "immediate runner". We can then have
30
+ framework features and other gems build on top of that, without having to
31
+ worry about API differences between various job runners such as Delayed Job
32
+ and Resque. Picking your queuing backend becomes more of an operational concern,
33
+ then. And you'll be able to switch between them without having to rewrite your jobs.
34
+
35
+
36
+ Creating a Job
37
+ --------------
38
+
39
+ This section will provide a step-by-step guide to creating a job and enqueuing it.
40
+
41
+ ### Create the Job
42
+
43
+ Active Job provides a Rails generator to create jobs. The following will create a
44
+ job in `app/jobs`:
45
+
46
+ ```bash
47
+ $ bin/rails generate job guests_cleanup
48
+ create app/jobs/guests_cleanup_job.rb
49
+ ```
50
+
51
+ You can also create a job that will run on a specific queue:
52
+
53
+ ```bash
54
+ $ bin/rails generate job guests_cleanup --queue urgent
55
+ create app/jobs/guests_cleanup_job.rb
56
+ ```
57
+
58
+ As you can see, you can generate jobs just like you use other generators with
59
+ Rails.
60
+
61
+ If you don't want to use a generator, you could create your own file inside of
62
+ `app/jobs`, just make sure that it inherits from `ActiveJob::Base`.
63
+
64
+ Here's what a job looks like:
65
+
66
+ ```ruby
67
+ class GuestsCleanupJob < ActiveJob::Base
68
+ queue_as :default
69
+
70
+ def perform(*args)
71
+ # Do something later
72
+ end
73
+ end
74
+ ```
75
+
76
+ ### Enqueue the Job
77
+
78
+ Enqueue a job like so:
79
+
80
+ ```ruby
81
+ MyJob.enqueue record # Enqueue a job to be performed as soon the queueing system is free.
82
+ ```
83
+
84
+ ```ruby
85
+ MyJob.enqueue_at Date.tomorrow.noon, record # Enqueue a job to be performed tomorrow at noon.
86
+ ```
87
+
88
+ ```ruby
89
+ MyJob.enqueue_in 1.week, record # Enqueue a job to be performed 1 week from now.
90
+ ```
91
+
92
+ That's it!
93
+
94
+
95
+ Job Execution
96
+ -------------
97
+
98
+ If no adapter is set, the job is immediately executed.
99
+
100
+ ### Backends
101
+
102
+ Active Job has adapters for the following queueing backends:
103
+
104
+ * [Backburner](https://github.com/nesquena/backburner)
105
+ * [Delayed Job](https://github.com/collectiveidea/delayed_job)
106
+ * [Qu](https://github.com/bkeepers/qu)
107
+ * [Que](https://github.com/chanks/que)
108
+ * [QueueClassic 2.x](https://github.com/ryandotsmith/queue_classic/tree/v2.2.3)
109
+ * [Resque 1.x](https://github.com/resque/resque/tree/1-x-stable)
110
+ * [Sidekiq](https://github.com/mperham/sidekiq)
111
+ * [Sneakers](https://github.com/jondot/sneakers)
112
+ * [Sucker Punch](https://github.com/brandonhilkert/sucker_punch)
113
+
114
+ #### Backends Features
115
+
116
+ | | Async | Queues | Delayed | Priorities | Timeout | Retries |
117
+ |-----------------------|-------|--------|-----------|------------|---------|---------|
118
+ | **Backburner** | Yes | Yes | Yes | Yes | Job | Global |
119
+ | **Delayed Job** | Yes | Yes | Yes | Job | Global | Global |
120
+ | **Que** | Yes | Yes | Yes | Job | No | Job |
121
+ | **Queue Classic** | Yes | Yes | No* | No | No | No |
122
+ | **Resque** | Yes | Yes | Yes (Gem) | Queue | Global | Yes |
123
+ | **Sidekiq** | Yes | Yes | Yes | Queue | No | Job |
124
+ | **Sneakers** | Yes | Yes | No | Queue | Queue | No |
125
+ | **Sucker Punch** | Yes | Yes | No | No | No | No |
126
+ | **Active Job Inline** | No | Yes | N/A | N/A | N/A | N/A |
127
+ | **Active Job** | Yes | Yes | Yes | No | No | No |
128
+
129
+ NOTE:
130
+ * Queue Classic does not support Job scheduling. However you can implement this
131
+ yourself or you can use the queue_classic-later gem. See the documentation for
132
+ ActiveJob::QueueAdapters::QueueClassicAdapter.
133
+
134
+ ### Change Backends
135
+
136
+ You can easily change your adapter:
137
+
138
+ ```ruby
139
+ # be sure to have the adapter gem in your Gemfile and follow the adapter specific
140
+ # installation and deployment instructions
141
+ YourApp::Application.config.active_job.queue_adapter = :sidekiq
142
+ ```
143
+
144
+
145
+ Queues
146
+ ------
147
+
148
+ Most of the adapters support multiple queues. With Active Job you can schedule
149
+ the job to run on a specific queue:
150
+
151
+ ```ruby
152
+ class GuestsCleanupJob < ActiveJob::Base
153
+ queue_as :low_priority
154
+ #....
155
+ end
156
+ ```
157
+
158
+ Also you can prefix the queue name for all your jobs using
159
+ `config.active_job.queue_name_prefix` in `application.rb`:
160
+
161
+ ```ruby
162
+ # config/application.rb
163
+ module YourApp
164
+ class Application < Rails::Application
165
+ config.active_job.queue_name_prefix = Rails.env
166
+ end
167
+ end
168
+
169
+ # app/jobs/guests_cleanup.rb
170
+ class GuestsCleanupJob < ActiveJob::Base
171
+ queue_as :low_priority
172
+ #....
173
+ end
174
+
175
+ # Now your job will run on queue production_low_priority on your production
176
+ # environment and on beta_low_priority on your beta environment
177
+ ```
178
+
179
+ NOTE: Make sure your queueing backend "listens" on your queue name. For some
180
+ backends you need to specify the queues to listen to.
181
+
182
+
183
+ Callbacks
184
+ ---------
185
+
186
+ Active Job provides hooks during the lifecycle of a job. Callbacks allow you to
187
+ trigger logic during the lifecycle of a job.
188
+
189
+ ### Available callbacks
190
+
191
+ * `before_enqueue`
192
+ * `around_enqueue`
193
+ * `after_enqueue`
194
+ * `before_perform`
195
+ * `around_perform`
196
+ * `after_perform`
197
+
198
+ ### Usage
199
+
200
+ ```ruby
201
+ class GuestsCleanupJob < ActiveJob::Base
202
+ queue_as :default
203
+
204
+ before_enqueue do |job|
205
+ # do something with the job instance
206
+ end
207
+
208
+ around_perform do |job, block|
209
+ # do something before perform
210
+ block.call
211
+ # do something after perform
212
+ end
213
+
214
+ def perform
215
+ # Do something later
216
+ end
217
+ end
218
+ ```
219
+
220
+
221
+ ActionMailer
222
+ ------------
223
+
224
+ One of the most common jobs in a modern web application is sending emails outside
225
+ of the request-response cycle, so the user doesn't have to wait on it. Active Job
226
+ is integrated with Action Mailer so you can easily send emails asynchronously:
227
+
228
+ ```ruby
229
+ # If you want to send the email now use #deliver_now
230
+ UserMailer.welcome(@user).deliver_now
231
+
232
+ # If you want to send the email through Active Job use #deliver_later
233
+ UserMailer.welcome(@user).deliver_later
234
+ ```
235
+
236
+
237
+ GlobalID
238
+ --------
239
+ Active Job supports GlobalID for parameters. This makes it possible to pass live
240
+ Active Record objects to your job instead of class/id pairs, which you then have
241
+ to manually deserialize. Before, jobs would look like this:
242
+
243
+ ```ruby
244
+ class TrashableCleanupJob
245
+ def perform(trashable_class, trashable_id, depth)
246
+ trashable = trashable_class.constantize.find(trashable_id)
247
+ trashable.cleanup(depth)
248
+ end
249
+ end
250
+ ```
251
+
252
+ Now you can simply do:
253
+
254
+ ```ruby
255
+ class TrashableCleanupJob
256
+ def perform(trashable, depth)
257
+ trashable.cleanup(depth)
258
+ end
259
+ end
260
+ ```
261
+
262
+ This works with any class that mixes in `ActiveModel::GlobalIdentification`, which
263
+ by default has been mixed into Active Model classes.
264
+
265
+
266
+ Exceptions
267
+ ----------
268
+
269
+ Active Job provides a way to catch exceptions raised during the execution of the
270
+ job:
271
+
272
+ ```ruby
273
+
274
+ class GuestsCleanupJob < ActiveJob::Base
275
+ queue_as :default
276
+
277
+ rescue_from(ActiveRecord::RecordNotFound) do |exception|
278
+ # do something with the exception
279
+ end
280
+
281
+ def perform
282
+ # Do something later
283
+ end
284
+ end
285
+ ```
@@ -0,0 +1,223 @@
1
+ Active Model Basics
2
+ ===================
3
+
4
+ This guide should provide you with all you need to get started using model classes. Active Model allows for Action Pack helpers to interact with non-Active Record models. Active Model also helps building custom ORMs for use outside of the Rails framework.
5
+
6
+ After reading this guide, you will know:
7
+
8
+ --------------------------------------------------------------------------------
9
+
10
+ Introduction
11
+ ------------
12
+
13
+ Active Model is a library containing various modules used in developing frameworks that need to interact with the Rails Action Pack library. Active Model provides a known set of interfaces for usage in classes. Some of modules are explained below.
14
+
15
+ ### AttributeMethods
16
+
17
+ The AttributeMethods module can add custom prefixes and suffixes on methods of a class. It is used by defining the prefixes and suffixes and which methods on the object will use them.
18
+
19
+ ```ruby
20
+ class Person
21
+ include ActiveModel::AttributeMethods
22
+
23
+ attribute_method_prefix 'reset_'
24
+ attribute_method_suffix '_highest?'
25
+ define_attribute_methods 'age'
26
+
27
+ attr_accessor :age
28
+
29
+ private
30
+ def reset_attribute(attribute)
31
+ send("#{attribute}=", 0)
32
+ end
33
+
34
+ def attribute_highest?(attribute)
35
+ send(attribute) > 100
36
+ end
37
+ end
38
+
39
+ person = Person.new
40
+ person.age = 110
41
+ person.age_highest? # true
42
+ person.reset_age # 0
43
+ person.age_highest? # false
44
+ ```
45
+
46
+ ### Callbacks
47
+
48
+ Callbacks gives Active Record style callbacks. This provides an ability to define callbacks which run at appropriate times. After defining callbacks, you can wrap them with before, after and around custom methods.
49
+
50
+ ```ruby
51
+ class Person
52
+ extend ActiveModel::Callbacks
53
+
54
+ define_model_callbacks :update
55
+
56
+ before_update :reset_me
57
+
58
+ def update
59
+ run_callbacks(:update) do
60
+ # This method is called when update is called on an object.
61
+ end
62
+ end
63
+
64
+ def reset_me
65
+ # This method is called when update is called on an object as a before_update callback is defined.
66
+ end
67
+ end
68
+ ```
69
+
70
+ ### Conversion
71
+
72
+ If a class defines `persisted?` and `id` methods, then you can include the `Conversion` module in that class and call the Rails conversion methods on objects of that class.
73
+
74
+ ```ruby
75
+ class Person
76
+ include ActiveModel::Conversion
77
+
78
+ def persisted?
79
+ false
80
+ end
81
+
82
+ def id
83
+ nil
84
+ end
85
+ end
86
+
87
+ person = Person.new
88
+ person.to_model == person # => true
89
+ person.to_key # => nil
90
+ person.to_param # => nil
91
+ ```
92
+
93
+ ### Dirty
94
+
95
+ An object becomes dirty when it has gone through one or more changes to its attributes and has not been saved. This gives the ability to check whether an object has been changed or not. It also has attribute based accessor methods. Let's consider a Person class with attributes `first_name` and `last_name`:
96
+
97
+ ```ruby
98
+ require 'active_model'
99
+
100
+ class Person
101
+ include ActiveModel::Dirty
102
+ define_attribute_methods :first_name, :last_name
103
+
104
+ def first_name
105
+ @first_name
106
+ end
107
+
108
+ def first_name=(value)
109
+ first_name_will_change!
110
+ @first_name = value
111
+ end
112
+
113
+ def last_name
114
+ @last_name
115
+ end
116
+
117
+ def last_name=(value)
118
+ last_name_will_change!
119
+ @last_name = value
120
+ end
121
+
122
+ def save
123
+ # do save work...
124
+ changes_applied
125
+ end
126
+ end
127
+ ```
128
+
129
+ #### Querying object directly for its list of all changed attributes.
130
+
131
+ ```ruby
132
+ person = Person.new
133
+ person.changed? # => false
134
+
135
+ person.first_name = "First Name"
136
+ person.first_name # => "First Name"
137
+
138
+ # returns if any attribute has changed.
139
+ person.changed? # => true
140
+
141
+ # returns a list of attributes that have changed before saving.
142
+ person.changed # => ["first_name"]
143
+
144
+ # returns a hash of the attributes that have changed with their original values.
145
+ person.changed_attributes # => {"first_name"=>nil}
146
+
147
+ # returns a hash of changes, with the attribute names as the keys, and the values will be an array of the old and new value for that field.
148
+ person.changes # => {"first_name"=>[nil, "First Name"]}
149
+ ```
150
+
151
+ #### Attribute based accessor methods
152
+
153
+ Track whether the particular attribute has been changed or not.
154
+
155
+ ```ruby
156
+ # attr_name_changed?
157
+ person.first_name # => "First Name"
158
+ person.first_name_changed? # => true
159
+ ```
160
+
161
+ Track what was the previous value of the attribute.
162
+
163
+ ```ruby
164
+ # attr_name_was accessor
165
+ person.first_name_was # => "First Name"
166
+ ```
167
+
168
+ Track both previous and current value of the changed attribute. Returns an array if changed, else returns nil.
169
+
170
+ ```ruby
171
+ # attr_name_change
172
+ person.first_name_change # => [nil, "First Name"]
173
+ person.last_name_change # => nil
174
+ ```
175
+
176
+ ### Validations
177
+
178
+ Validations module adds the ability to class objects to validate them in Active Record style.
179
+
180
+ ```ruby
181
+ class Person
182
+ include ActiveModel::Validations
183
+
184
+ attr_accessor :name, :email, :token
185
+
186
+ validates :name, presence: true
187
+ validates_format_of :email, with: /\A([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})\z/i
188
+ validates! :token, presence: true
189
+ end
190
+
191
+ person = Person.new(token: "2b1f325")
192
+ person.valid? # => false
193
+ person.name = 'vishnu'
194
+ person.email = 'me'
195
+ person.valid? # => false
196
+ person.email = 'me@vishnuatrai.com'
197
+ person.valid? # => true
198
+ person.token = nil
199
+ person.valid? # => raises ActiveModel::StrictValidationFailed
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
+ ```