railties 3.0.0.beta3 → 3.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -0
- data/README +118 -123
- data/guides/source/3_0_release_notes.textile +13 -11
- data/guides/source/action_controller_overview.textile +2 -2
- data/guides/source/action_mailer_basics.textile +70 -26
- data/guides/source/action_view_overview.textile +1 -1
- data/guides/source/active_record_basics.textile +9 -1
- data/guides/source/active_record_querying.textile +2 -2
- data/guides/source/active_support_core_extensions.textile +377 -9
- data/guides/source/activerecord_validations_callbacks.textile +98 -55
- data/guides/source/association_basics.textile +1 -1
- data/guides/source/caching_with_rails.textile +1 -1
- data/guides/source/command_line.textile +23 -23
- data/guides/source/configuring.textile +1 -3
- data/guides/source/contribute.textile +27 -28
- data/guides/source/credits.html.erb +4 -4
- data/guides/source/debugging_rails_applications.textile +2 -2
- data/guides/source/form_helpers.textile +7 -6
- data/guides/source/generators.textile +19 -29
- data/guides/source/getting_started.textile +106 -49
- data/guides/source/i18n.textile +27 -27
- data/guides/source/index.html.erb +18 -8
- data/guides/source/initialization.textile +140 -514
- data/guides/source/layout.html.erb +6 -4
- data/guides/source/layouts_and_rendering.textile +5 -5
- data/guides/source/migrations.textile +7 -3
- data/guides/source/nested_model_forms.textile +2 -2
- data/guides/source/performance_testing.textile +11 -12
- data/guides/source/plugins.textile +30 -30
- data/guides/source/rails_application_templates.textile +3 -3
- data/guides/source/rails_on_rack.textile +3 -66
- data/guides/source/routing.textile +10 -4
- data/guides/source/security.textile +1 -1
- data/guides/source/testing.textile +55 -52
- data/guides/w3c_validator.rb +67 -0
- data/lib/rails.rb +1 -0
- data/lib/rails/application.rb +49 -13
- data/lib/rails/application/bootstrap.rb +7 -6
- data/lib/rails/application/configuration.rb +24 -47
- data/lib/rails/application/finisher.rb +8 -3
- data/lib/rails/backtrace_cleaner.rb +11 -12
- data/lib/rails/commands.rb +54 -54
- data/lib/rails/commands/application.rb +7 -2
- data/lib/rails/commands/{performance/benchmarker.rb → benchmarker.rb} +0 -0
- data/lib/rails/commands/dbconsole.rb +4 -3
- data/lib/rails/commands/destroy.rb +1 -0
- data/lib/rails/commands/generate.rb +1 -0
- data/lib/rails/commands/{performance/profiler.rb → profiler.rb} +0 -0
- data/lib/rails/commands/runner.rb +4 -2
- data/lib/rails/configuration.rb +36 -0
- data/lib/rails/engine.rb +24 -24
- data/lib/rails/engine/configuration.rb +0 -1
- data/lib/rails/generators.rb +48 -10
- data/lib/rails/generators/actions.rb +5 -3
- data/lib/rails/generators/base.rb +23 -17
- data/lib/rails/generators/erb/scaffold/templates/_form.html.erb +9 -8
- data/lib/rails/generators/erb/scaffold/templates/show.html.erb +1 -1
- data/lib/rails/generators/generated_attribute.rb +7 -6
- data/lib/rails/generators/rails/app/USAGE +2 -2
- data/lib/rails/generators/rails/app/app_generator.rb +242 -97
- data/lib/rails/generators/rails/app/templates/Gemfile +3 -0
- data/lib/rails/generators/rails/app/templates/README +167 -130
- data/lib/rails/generators/rails/app/templates/Rakefile +0 -3
- data/lib/rails/generators/rails/app/templates/config/boot.rb +9 -2
- data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml +5 -5
- data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +4 -0
- data/lib/rails/generators/rails/app/templates/script/rails +2 -5
- data/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt +1 -3
- data/lib/rails/generators/rails/stylesheets/templates/scaffold.css +5 -9
- data/lib/rails/generators/test_case.rb +12 -0
- data/lib/rails/generators/test_unit/integration/templates/integration_test.rb +1 -1
- data/lib/rails/generators/test_unit/performance/templates/performance_test.rb +1 -1
- data/lib/rails/info.rb +0 -33
- data/lib/rails/log_subscriber.rb +13 -6
- data/lib/rails/rack/logger.rb +4 -3
- data/lib/rails/railtie.rb +4 -0
- data/lib/rails/railtie/configuration.rb +21 -4
- data/lib/rails/tasks/documentation.rake +2 -0
- data/lib/rails/tasks/framework.rake +22 -0
- data/lib/rails/tasks/middleware.rake +1 -1
- data/lib/rails/tasks/routes.rake +5 -1
- data/lib/rails/test_help.rb +3 -1
- data/lib/rails/test_unit/testing.rake +3 -1
- data/lib/rails/version.rb +1 -1
- metadata +12 -19
- data/lib/rails/application/metal_loader.rb +0 -50
- data/lib/rails/dispatcher.rb +0 -24
- data/lib/rails/generators/rails/mailer/USAGE +0 -15
- data/lib/rails/generators/rails/mailer/mailer_generator.rb +0 -14
- data/lib/rails/generators/rails/mailer/templates/mailer.rb +0 -16
- data/lib/rails/generators/rails/metal/USAGE +0 -8
- data/lib/rails/generators/rails/metal/metal_generator.rb +0 -11
- data/lib/rails/generators/rails/metal/templates/metal.rb +0 -12
@@ -91,7 +91,7 @@ The +params+ hash is not limited to one-dimensional keys and values. It can cont
|
|
91
91
|
GET /clients?ids[]=1&ids[]=2&ids[]=3
|
92
92
|
</pre>
|
93
93
|
|
94
|
-
NOTE: The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&ids%5b%5d=2&ids%5b%
|
94
|
+
NOTE: The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&ids%5b%5d=2&ids%5b%5d=3" as "[" and "]" are not allowed in URLs. Most of the time you don't have to worry about this because the browser will take care of it for you, and Rails will decode it back when it receives it, but if you ever find yourself having to send those requests to the server manually you have to keep this in mind.
|
95
95
|
|
96
96
|
The value of +params[:ids]+ will now be +["1", "2", "3"]+. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.
|
97
97
|
|
@@ -653,7 +653,7 @@ class ClientsController < ApplicationController
|
|
653
653
|
# Stream a file that has already been generated and stored on disk.
|
654
654
|
def download_pdf
|
655
655
|
client = Client.find(params[:id])
|
656
|
-
|
656
|
+
send_file("#{Rails.root}/files/clients/#{client.id}.pdf",
|
657
657
|
:filename => "#{client.name}.pdf",
|
658
658
|
:type => "application/pdf")
|
659
659
|
end
|
@@ -55,12 +55,12 @@ class UserMailer < ActionMailer::Base
|
|
55
55
|
end
|
56
56
|
</ruby>
|
57
57
|
|
58
|
-
Here is a quick explanation of the items presented in the preceding method. For a full list of all available options, please have a look further down at the Complete List of
|
58
|
+
Here is a quick explanation of the items presented in the preceding method. For a full list of all available options, please have a look further down at the Complete List of Action Mailer user-settable attributes section.
|
59
59
|
|
60
60
|
* <tt>default Hash</tt> - This is a hash of default values for any email you send, in this case we are setting the <tt>:from</tt> header to a value for all messages in this class, this can be overridden on a per email basis
|
61
|
-
* +mail+ - The actual email message, we are passing the <tt>:to</tt> and <tt>:subject</tt> headers in
|
61
|
+
* +mail+ - The actual email message, we are passing the <tt>:to</tt> and <tt>:subject</tt> headers in.
|
62
62
|
|
63
|
-
|
63
|
+
Just like controllers, any instance variables we define in the method become available for use in the views.
|
64
64
|
|
65
65
|
h5. Create a Mailer View
|
66
66
|
|
@@ -104,9 +104,9 @@ When you call the +mail+ method now, Action Mailer will detect the two templates
|
|
104
104
|
|
105
105
|
h5. Wire It Up So That the System Sends the Email When a User Signs Up
|
106
106
|
|
107
|
-
There are
|
107
|
+
There are several ways to do this, some people create Rails Observers to fire off emails, others do it inside of the User Model. However, in Rails 3, mailers are really just another way to render a view. Instead of rendering a view and sending out the HTTP protocol, they are just sending it out through the Email protocols instead. Due to this, it makes sense to just have your controller tell the mailer to send an email when a user is successfully created.
|
108
108
|
|
109
|
-
|
109
|
+
Setting this up is painfully simple.
|
110
110
|
|
111
111
|
First off, we need to create a simple +User+ scaffold:
|
112
112
|
|
@@ -115,35 +115,46 @@ $ rails generate scaffold user name:string email:string login:string
|
|
115
115
|
$ rake db:migrate
|
116
116
|
</shell>
|
117
117
|
|
118
|
-
Now that we have a user model to play with, edit +
|
118
|
+
Now that we have a user model to play with, we will just edit the +app/controllers/users_controller.rb+ make it instruct the UserMailer to deliver an email to the newly created user by editing the create action and inserting a call to <tt>UserMailer.welcome_email</tt> right after the user is successfully saved:
|
119
119
|
|
120
120
|
<ruby>
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
121
|
+
class UsersController < ApplicationController
|
122
|
+
# POST /users
|
123
|
+
# POST /users.xml
|
124
|
+
def create
|
125
|
+
@user = User.new(params[:user])
|
126
|
+
|
127
|
+
respond_to do |format|
|
128
|
+
if @user.save
|
129
|
+
# Tell the UserMailer to send a welcome Email after save
|
130
|
+
UserMailer.welcome_email(@user).deliver
|
131
|
+
|
132
|
+
format.html { redirect_to(@user, :notice => 'User was successfully created.') }
|
133
|
+
format.xml { render :xml => @user, :status => :created, :location => @user }
|
134
|
+
else
|
135
|
+
format.html { render :action => "new" }
|
136
|
+
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
|
137
|
+
end
|
138
|
+
end
|
125
139
|
end
|
126
140
|
end
|
127
141
|
</ruby>
|
128
142
|
|
129
|
-
|
143
|
+
This provides a much simpler implementation that does not require the registering of observers and the like.
|
130
144
|
|
131
|
-
|
145
|
+
The method +welcome_email+ returns a Mail::Message object which can then just be told +deliver+ to send itself out.
|
132
146
|
|
133
|
-
|
134
|
-
class UserObserver < ActiveRecord::Observer
|
135
|
-
def after_create(user)
|
136
|
-
UserMailer.welcome_email(user).deliver
|
137
|
-
end
|
138
|
-
end
|
139
|
-
</ruby>
|
147
|
+
NOTE: In previous versions of Rails, you would call +deliver_welcome_email+ or +create_welcome_email+ however in Rails 3.0 this has been deprecated in favour of just calling the method name itself.
|
140
148
|
|
141
|
-
|
149
|
+
WARNING: Sending out one email should only take a fraction of a second, if you are planning on sending out many emails, or you have a slow domain resolution service, you might want to investigate using a background process like delayed job.
|
142
150
|
|
143
|
-
|
151
|
+
h4. Auto encoding header values
|
144
152
|
|
145
|
-
|
153
|
+
Action Mailer now handles the auto encoding of multibyte characters inside of headers and bodies.
|
146
154
|
|
155
|
+
If you are using UTF-8 as your character set, you do not have to do anything special, just go ahead and send in UTF-8 data to the address fields, subject, keywords, filenames or body of the email and ActionMailer will auto encode it into quoted printable for you in the case of a header field or Base64 encode any body parts that are non US-ASCII.
|
156
|
+
|
157
|
+
For more complex examples, such as defining alternate character sets or self encoding text first, please refer to the Mail library.
|
147
158
|
|
148
159
|
h4. Complete List of Action Mailer Methods
|
149
160
|
|
@@ -160,21 +171,23 @@ Defining custom headers are simple, you can do it one of three ways:
|
|
160
171
|
* Defining a header field as a parameter to the +mail+ method:
|
161
172
|
|
162
173
|
<ruby>
|
163
|
-
mail(
|
174
|
+
mail("X-Spam" => value)
|
164
175
|
</ruby>
|
165
176
|
|
166
177
|
* Passing in a key value assignment to the +headers+ method:
|
167
178
|
|
168
179
|
<ruby>
|
169
|
-
headers[
|
180
|
+
headers["X-Spam"] = value
|
170
181
|
</ruby>
|
171
182
|
|
172
183
|
* Passing a hash of key value pairs to the +headers+ method:
|
173
184
|
|
174
185
|
<ruby>
|
175
|
-
headers {
|
186
|
+
headers {"X-Spam" => value, "X-Special" => another_value}
|
176
187
|
</ruby>
|
177
188
|
|
189
|
+
TIP: All <tt>X-Value</tt> headers per the RFC2822 can appear more than one time. If you want to delete an <tt>X-Value</tt> header, you need to assign it a value of <tt>nil</tt>.
|
190
|
+
|
178
191
|
h5. Adding Attachments
|
179
192
|
|
180
193
|
Adding attachments has been simplified in Action Mailer 3.0.
|
@@ -198,6 +211,37 @@ attachments['filename.jpg'] = {:mime_type => 'application/x-gzip',
|
|
198
211
|
|
199
212
|
NOTE: If you specify an encoding, Mail will assume that your content is already encoded and not try to Base64 encode it.
|
200
213
|
|
214
|
+
h5. Making Inline Attachments
|
215
|
+
|
216
|
+
Inline attachments are now possible in ActionMailer. While previously in the pre 3.0 version of Rails, you could do inline attachments, it involved a lot of hacking and determination to pull it off.
|
217
|
+
|
218
|
+
ActionMailer now makes inline attachments as trivial as they should be.
|
219
|
+
|
220
|
+
* Firstly, to tell Mail to turn an attachment into an inline attachment, you just call <tt>#inline</tt> on the attachments method within your Mailer:
|
221
|
+
|
222
|
+
<ruby>
|
223
|
+
def welcome
|
224
|
+
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
|
225
|
+
end
|
226
|
+
</ruby>
|
227
|
+
|
228
|
+
* Then in your view, you can just reference <tt>attachments[]</tt> as a hash and specify which attachment you want to show, calling +url+ on it and then passing the result into the <tt>image_tag</tt> method:
|
229
|
+
|
230
|
+
<erb>
|
231
|
+
<p>Hello there, this is our image</p>
|
232
|
+
|
233
|
+
<%= image_tag attachments['image.jpg'].url %>
|
234
|
+
</erb>
|
235
|
+
|
236
|
+
* As this is a standard call to +image_tag+ you can pass in an options hash after the attachment url as you could for any other image:
|
237
|
+
|
238
|
+
<erb>
|
239
|
+
<p>Hello there, this is our image</p>
|
240
|
+
|
241
|
+
<%= image_tag attachments['image.jpg'].url, :alt => 'My Photo',
|
242
|
+
:class => 'photos' %>
|
243
|
+
</erb>
|
244
|
+
|
201
245
|
h4. Mailer Views
|
202
246
|
|
203
247
|
Mailer views are located in the +app/views/name_of_mailer_class+ directory. The specific mailer view is known to the class because it's name is the same as the mailer method. So for example, in our example from above, our mailer view for the +welcome_email+ method will be in +app/views/user_mailer/welcome_email.html.erb+ for the HTML version and +welcome_email.text.erb+ for the plain text version.
|
@@ -325,7 +369,7 @@ class UserMailer < ActionMailer::Base
|
|
325
369
|
end
|
326
370
|
</ruby>
|
327
371
|
|
328
|
-
The above will send a multipart email with an attachment, properly nested with the top level being <tt>mixed
|
372
|
+
The above will send a multipart email with an attachment, properly nested with the top level being <tt>multipart/mixed</tt> and the first part being a <tt>multipart/alternative</tt> containing the plain text and HTML email messages.
|
329
373
|
|
330
374
|
h3. Receiving Emails
|
331
375
|
|
@@ -699,7 +699,7 @@ Creates a scope around a specific model object like form_for, but doesn‘t crea
|
|
699
699
|
First name: <%= person_form.text_field :first_name %>
|
700
700
|
Last name : <%= person_form.text_field :last_name %>
|
701
701
|
|
702
|
-
|
702
|
+
<%= fields_for @person.permission do |permission_fields| %>
|
703
703
|
Admin? : <%= permission_fields.check_box :admin %>
|
704
704
|
<% end %>
|
705
705
|
<% end %>
|
@@ -104,6 +104,14 @@ class Product < ActiveRecord::Base
|
|
104
104
|
set_table_name "PRODUCT"
|
105
105
|
end
|
106
106
|
</ruby>
|
107
|
+
If you do so, you will have to define manually the class name that is hosting the fixtures (class_name.yml) using the +set_fixture_class+ method in your test definition:
|
108
|
+
<ruby>
|
109
|
+
class FunnyJoke < ActiveSupport::TestCase
|
110
|
+
set_fixture_class :funny_jokes => 'Joke'
|
111
|
+
fixtures :funny_jokes
|
112
|
+
...
|
113
|
+
end
|
114
|
+
</ruby>
|
107
115
|
|
108
116
|
It's also possible to override the column that should be used as the table's primary key. Use the +ActiveRecord::Base.set_primary_key+ method for that:
|
109
117
|
<ruby>
|
@@ -201,4 +209,4 @@ Active Record callbacks allow you to attach code to certain events in the life-c
|
|
201
209
|
|
202
210
|
h3. Migrations
|
203
211
|
|
204
|
-
Rails provides a domain-specific language for managing a database schema called migrations. Migrations are stored in files which are executed against any database that Active Record support using rake. Rails keeps track of which files have been committed to the database and provides rollback features. You can learn more about migrations in the "Active Record Migrations guide":migrations.html
|
212
|
+
Rails provides a domain-specific language for managing a database schema called migrations. Migrations are stored in files which are executed against any database that Active Record support using rake. Rails keeps track of which files have been committed to the database and provides rollback features. You can learn more about migrations in the "Active Record Migrations guide":migrations.html
|
@@ -17,7 +17,7 @@ If you're used to using raw SQL to find database records then, generally, you wi
|
|
17
17
|
|
18
18
|
Code examples throughout this guide will refer to one or more of the following models:
|
19
19
|
|
20
|
-
TIP: All of the following models
|
20
|
+
TIP: All of the following models use +id+ as the primary key, unless specified otherwise.
|
21
21
|
|
22
22
|
<br />
|
23
23
|
|
@@ -802,7 +802,7 @@ will either assign an existing client object with the name "Ryan" to the client
|
|
802
802
|
|
803
803
|
h3. Finding by SQL
|
804
804
|
|
805
|
-
If you'd like to use your own SQL to find records in a table you can use +find_by_sql+. The +find_by_sql+ method will return an array of objects even the underlying query returns just a single record. For example you could run this query:
|
805
|
+
If you'd like to use your own SQL to find records in a table you can use +find_by_sql+. The +find_by_sql+ method will return an array of objects even if the underlying query returns just a single record. For example you could run this query:
|
806
806
|
|
807
807
|
<ruby>
|
808
808
|
Client.find_by_sql("SELECT * FROM clients
|
@@ -1254,6 +1254,39 @@ There's also the destructive version +String#squish!+.
|
|
1254
1254
|
|
1255
1255
|
NOTE: Defined in +active_support/core_ext/string/filters.rb+.
|
1256
1256
|
|
1257
|
+
h4. +truncate+
|
1258
|
+
|
1259
|
+
The method +truncate+ returns a copy of its receiver truncated after a given +length+:
|
1260
|
+
|
1261
|
+
<ruby>
|
1262
|
+
"Oh dear! Oh dear! I shall be late!".truncate(20)
|
1263
|
+
# => "Oh dear! Oh dear!..."
|
1264
|
+
</ruby>
|
1265
|
+
|
1266
|
+
Ellipsis can be customized with the +:omission+ option:
|
1267
|
+
|
1268
|
+
<ruby>
|
1269
|
+
"Oh dear! Oh dear! I shall be late!".truncate(20, :omission => '…')
|
1270
|
+
# => "Oh dear! Oh …"
|
1271
|
+
</ruby>
|
1272
|
+
|
1273
|
+
Note in particular that truncation takes into account the length of the omission string.
|
1274
|
+
|
1275
|
+
Pass a +:separator+ to truncate the string at a natural break:
|
1276
|
+
|
1277
|
+
<ruby>
|
1278
|
+
"Oh dear! Oh dear! I shall be late!".truncate(18)
|
1279
|
+
# => "Oh dear! Oh dea..."
|
1280
|
+
"Oh dear! Oh dear! I shall be late!".truncate(18, :separator => ' ')
|
1281
|
+
# => "Oh dear! Oh..."
|
1282
|
+
</ruby>
|
1283
|
+
|
1284
|
+
In the above example "dear" gets cut first, but then +:separator+ prevents it.
|
1285
|
+
|
1286
|
+
WARNING: The option +:separator+ can't be a regexp.
|
1287
|
+
|
1288
|
+
NOTE: Defined in +active_support/core_ext/string/filters.rb+.
|
1289
|
+
|
1257
1290
|
h4. Key-based Interpolation
|
1258
1291
|
|
1259
1292
|
In Ruby 1.9 the <tt>%</tt> string operator supports key-based interpolation, both formatted and unformatted:
|
@@ -1894,13 +1927,21 @@ Similarly, +from+ returns the tail from the element at the passed index on:
|
|
1894
1927
|
|
1895
1928
|
The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding element (+first+ is builtin). Thanks to social wisdom and positive constructiveness all around, +forty_two+ is also available.
|
1896
1929
|
|
1897
|
-
|
1930
|
+
NOTE: Defined in +active_support/core_ext/array/access.rb+.
|
1931
|
+
|
1932
|
+
h4. Random Access
|
1933
|
+
|
1934
|
+
Active Support backports +sample+ from Ruby 1.9:
|
1898
1935
|
|
1899
1936
|
<ruby>
|
1900
|
-
shape_type = [Circle, Square, Triangle].
|
1937
|
+
shape_type = [Circle, Square, Triangle].sample
|
1938
|
+
# => Square, for example
|
1939
|
+
|
1940
|
+
shape_types = [Circle, Square, Triangle].sample(2)
|
1941
|
+
# => [Triangle, Circle], for example
|
1901
1942
|
</ruby>
|
1902
1943
|
|
1903
|
-
NOTE: Defined in +active_support/core_ext/array/
|
1944
|
+
NOTE: Defined in +active_support/core_ext/array/random_access.rb+.
|
1904
1945
|
|
1905
1946
|
h4. Options Extraction
|
1906
1947
|
|
@@ -2648,21 +2689,348 @@ NOTE: Defined in +active_support/core_ext/proc.rb+.
|
|
2648
2689
|
|
2649
2690
|
h3. Extensions to +Date+
|
2650
2691
|
|
2651
|
-
|
2692
|
+
h4. Calculations
|
2693
|
+
|
2694
|
+
NOTE: All the following methods are defined in +active_support/core_ext/date/calculations.rb+.
|
2695
|
+
|
2696
|
+
INFO: The following calculation methods have edge cases in October 1582, since days 5..14 just do not exist. This guide does not document their behavior around those days for brevity, but it is enough to say that they do what you would expect. That is, +Date.new(1582, 10, 4).tomorrow+ returns +Date.new(1582, 10, 15)+ and so on. Please check +test/core_ext/date_ext_test.rb+ in the Active Support test suite for expected behavior.
|
2697
|
+
|
2698
|
+
h5. +Date.current+
|
2699
|
+
|
2700
|
+
Active Support defines +Date.current+ to be today in the current time zone. That's like +Date.today+, except that it honors the user time zone, if defined. It also defines +Date.yesterday+ and +Date.tomorrow+, and the instance predicates +past?+, +today?+, and +future?+, all of them relative to +Date.current+.
|
2701
|
+
|
2702
|
+
h5. Named dates
|
2703
|
+
|
2704
|
+
h6. +prev_year+, +next_year+
|
2705
|
+
|
2706
|
+
In Ruby 1.9 +prev_year+ and +next_year+ return a date with the same day/month in the last or next year:
|
2707
|
+
|
2708
|
+
<ruby>
|
2709
|
+
d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
|
2710
|
+
d.prev_year # => Fri, 08 May 2009
|
2711
|
+
d.next_year # => Sun, 08 May 2011
|
2712
|
+
</ruby>
|
2713
|
+
|
2714
|
+
If date is the 29th of February of a leap year, you obtain the 28th:
|
2715
|
+
|
2716
|
+
<ruby>
|
2717
|
+
d = Date.new(2000, 2, 29) # => Tue, 29 Feb 2000
|
2718
|
+
d.prev_year # => Sun, 28 Feb 1999
|
2719
|
+
d.next_year # => Wed, 28 Feb 2001
|
2720
|
+
</ruby>
|
2721
|
+
|
2722
|
+
Active Support defines these methods as well for Ruby 1.8.
|
2723
|
+
|
2724
|
+
h6. +prev_month+, +next_month+
|
2725
|
+
|
2726
|
+
In Ruby 1.9 +prev_month+ and +next_month+ return the date with the same day in the last or next month:
|
2727
|
+
|
2728
|
+
<ruby>
|
2729
|
+
d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
|
2730
|
+
d.prev_month # => Thu, 08 Apr 2010
|
2731
|
+
d.next_month # => Tue, 08 Jun 2010
|
2732
|
+
</ruby>
|
2733
|
+
|
2734
|
+
If such a day does not exist, the last day of the corresponding month is returned:
|
2735
|
+
|
2736
|
+
<ruby>
|
2737
|
+
Date.new(2000, 5, 31).prev_month # => Sun, 30 Apr 2000
|
2738
|
+
Date.new(2000, 3, 31).prev_month # => Tue, 29 Feb 2000
|
2739
|
+
Date.new(2000, 5, 31).next_month # => Fri, 30 Jun 2000
|
2740
|
+
Date.new(2000, 1, 31).next_month # => Tue, 29 Feb 2000
|
2741
|
+
</ruby>
|
2742
|
+
|
2743
|
+
Active Support defines these methods as well for Ruby 1.8.
|
2744
|
+
|
2745
|
+
h6. +beginning_of_week+, +end_of_week+
|
2746
|
+
|
2747
|
+
The methods +beginning_of_week+ and +end_of_week+ return the dates for the beginning and end of week, assuming weeks start on Monday:
|
2748
|
+
|
2749
|
+
<ruby>
|
2750
|
+
d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
|
2751
|
+
d.beginning_of_week # => Mon, 03 May 2010
|
2752
|
+
d.end_of_week # => Sun, 09 May 2010
|
2753
|
+
</ruby>
|
2754
|
+
|
2755
|
+
+beginning_of_week+ is aliased to +monday+ and +at_beginning_of_week+. +end_of_week+ is aliased to +sunday+ and +at_end_of_week+.
|
2756
|
+
|
2757
|
+
h6. +next_week+
|
2758
|
+
|
2759
|
+
+next_week+ receives a symbol with a day name in English (in lowercase, default is +:monday+) and it returns the date corresponding to that day in the next week:
|
2760
|
+
|
2761
|
+
<ruby>
|
2762
|
+
d = Date.new(2010, 5, 9) # => Sun, 09 May 2010
|
2763
|
+
d.next_week # => Mon, 10 May 2010
|
2764
|
+
d.next_week(:saturday) # => Sat, 15 May 2010
|
2765
|
+
</ruby>
|
2766
|
+
|
2767
|
+
h6. +beginning_of_month+, +end_of_month+
|
2768
|
+
|
2769
|
+
The methods +beginning_of_month+ and +end_of_month+ return the dates for the beginning and end of the month:
|
2770
|
+
|
2771
|
+
<ruby>
|
2772
|
+
d = Date.new(2010, 5, 9) # => Sun, 09 May 2010
|
2773
|
+
d.beginning_of_month # => Sat, 01 May 2010
|
2774
|
+
d.end_of_month # => Mon, 31 May 2010
|
2775
|
+
</ruby>
|
2776
|
+
|
2777
|
+
+beginning_of_month+ is aliased to +at_beginning_of_month+, and +end_of_month+ is aliased to +at_end_of_month+.
|
2778
|
+
|
2779
|
+
h6. +beginning_of_quarter+, +end_of_quarter+
|
2780
|
+
|
2781
|
+
The methods +beginning_of_quarter+ and +end_of_quarter+ return the dates for the beginning and end of the quarter of the receiver's calendar year:
|
2782
|
+
|
2783
|
+
<ruby>
|
2784
|
+
d = Date.new(2010, 5, 9) # => Sun, 09 May 2010
|
2785
|
+
d.beginning_of_quarter # => Thu, 01 Apr 2010
|
2786
|
+
d.end_of_quarter # => Wed, 30 Jun 2010
|
2787
|
+
</ruby>
|
2788
|
+
|
2789
|
+
+beginning_of_quarter+ is aliased to +at_beginning_of_quarter+, and +end_of_quarter+ is aliased to +at_end_of_quarter+.
|
2790
|
+
|
2791
|
+
h6. +beginning_of_year+, +end_of_year+
|
2792
|
+
|
2793
|
+
The methods +beginning_of_year+ and +end_of_year+ return the dates for the beginning and end of the year:
|
2794
|
+
|
2795
|
+
<ruby>
|
2796
|
+
d = Date.new(2010, 5, 9) # => Sun, 09 May 2010
|
2797
|
+
d.beginning_of_year # => Fri, 01 Jan 2010
|
2798
|
+
d.end_of_year # => Fri, 31 Dec 2010
|
2799
|
+
</ruby>
|
2800
|
+
|
2801
|
+
+beginning_of_year+ is aliased to +at_beginning_of_year+, and +end_of_year+ is aliased to +at_end_of_year+.
|
2802
|
+
|
2803
|
+
h5. Other Date Computations
|
2804
|
+
|
2805
|
+
h6. +years_ago+, +years_since+
|
2806
|
+
|
2807
|
+
The method +years_ago+ receives a number of years and returns the same date those many years ago:
|
2808
|
+
|
2809
|
+
<ruby>
|
2810
|
+
date = Date.new(2010, 6, 7)
|
2811
|
+
date.years_ago(10) # => Wed, 07 Jun 2000
|
2812
|
+
</ruby>
|
2813
|
+
|
2814
|
+
+years_since+ moves forward in time:
|
2815
|
+
|
2816
|
+
<ruby>
|
2817
|
+
date = Date.new(2010, 6, 7)
|
2818
|
+
date.years_since(10) # => Sun, 07 Jun 2020
|
2819
|
+
</ruby>
|
2820
|
+
|
2821
|
+
If such a day does not exist, the last day of the corresponding month is returned:
|
2822
|
+
|
2823
|
+
<ruby>
|
2824
|
+
Date.new(2012, 2, 29).years_ago(3) # => Sat, 28 Feb 2009
|
2825
|
+
Date.new(2012, 2, 29).years_since(3) # => Sat, 28 Feb 2015
|
2826
|
+
</ruby>
|
2827
|
+
|
2828
|
+
h6. +months_ago+, +months_since+
|
2829
|
+
|
2830
|
+
The methods +months_ago+ and +months_since+ work analogously for months:
|
2831
|
+
|
2832
|
+
<ruby>
|
2833
|
+
Date.new(2010, 4, 30).months_ago(2) # => Sun, 28 Feb 2010
|
2834
|
+
Date.new(2010, 4, 30).months_since(2) # => Wed, 30 Jun 2010
|
2835
|
+
</ruby>
|
2836
|
+
|
2837
|
+
If such a day does not exist, the last day of the corresponding month is returned:
|
2838
|
+
|
2839
|
+
<ruby>
|
2840
|
+
Date.new(2010, 4, 30).months_ago(2) # => Sun, 28 Feb 2010
|
2841
|
+
Date.new(2009, 12, 31).months_since(2) # => Sun, 28 Feb 2010
|
2842
|
+
</ruby>
|
2843
|
+
|
2844
|
+
h6. +advance+
|
2845
|
+
|
2846
|
+
The most generic way to jump to other days is +advance+. This method receives a hash with keys +:years+, +:months+, +:weeks+, +:days+, and returns a date advanced as much as the present keys indicate:
|
2847
|
+
|
2848
|
+
<ruby>
|
2849
|
+
date = Date.new(2010, 6, 6)
|
2850
|
+
date.advance(:years => 1, :weeks => 2) # => Mon, 20 Jun 2011
|
2851
|
+
date.advance(:months => 2, :days => -2) # => Wed, 04 Aug 2010
|
2852
|
+
</ruby>
|
2853
|
+
|
2854
|
+
Note in the previous example that increments may be negative.
|
2855
|
+
|
2856
|
+
To perform the computation the method first increments years, then months, then weeks, and finally days. This order is important towards the end of months. Say for example we are at the end of February of 2010, and we want to move one month and one day forward.
|
2857
|
+
|
2858
|
+
The method +advance+ advances first one month, and the one day, the result is:
|
2859
|
+
|
2860
|
+
<ruby>
|
2861
|
+
Date.new(2010, 2, 28).advance(:months => 1, :day => 1)
|
2862
|
+
# => Sun, 28 Mar 2010
|
2863
|
+
</ruby>
|
2864
|
+
|
2865
|
+
While if it did it the other way around the result would be different:
|
2866
|
+
|
2867
|
+
<ruby>
|
2868
|
+
Date.new(2010, 2, 28).advance(:days => 1).advance(:months => 1)
|
2869
|
+
# => Thu, 01 Apr 2010
|
2870
|
+
</ruby>
|
2871
|
+
|
2872
|
+
h5. Changing Components
|
2873
|
+
|
2874
|
+
The method +change+ allows you to get a new date which is the same as the receiver except for the given year, month, or day:
|
2875
|
+
|
2876
|
+
<ruby>
|
2877
|
+
Date.new(2010, 12, 23).change(:year => 2011, :month => 11)
|
2878
|
+
# => Wed, 23 Nov 2011
|
2879
|
+
</ruby>
|
2880
|
+
|
2881
|
+
This method is not tolerant to non-existing dates, if the change is invalid +ArgumentError+ is raised:
|
2882
|
+
|
2883
|
+
<ruby>
|
2884
|
+
Date.new(2010, 1, 31).change(:month => 2)
|
2885
|
+
# => ArgumentError: invalid date
|
2886
|
+
</ruby>
|
2887
|
+
|
2888
|
+
h5. Named Times
|
2889
|
+
|
2890
|
+
WARNING: The following methods do not take into account the user time zone. They return timestamps in localtime.
|
2891
|
+
|
2892
|
+
INFO: The following methods return a +Time+ object if possible, otherwise a +DateTime+.
|
2893
|
+
|
2894
|
+
h6. +beginning_of_day+, +end_of_day+
|
2895
|
+
|
2896
|
+
The method +beginning_of_day+ returns a timestamp at the beginning of the day (00:00:00):
|
2897
|
+
|
2898
|
+
<ruby>
|
2899
|
+
date = Date.new(2010, 6, 7)
|
2900
|
+
date.beginning_of_day # => Sun Jun 07 00:00:00 +0200 2010
|
2901
|
+
</ruby>
|
2902
|
+
|
2903
|
+
The method +end_of_day+ returns a timestamp at the end of the day (23:59:59):
|
2904
|
+
|
2905
|
+
<ruby>
|
2906
|
+
date = Date.new(2010, 6, 7)
|
2907
|
+
date.end_of_day # => Sun Jun 06 23:59:59 +0200 2010
|
2908
|
+
</ruby>
|
2909
|
+
|
2910
|
+
+beginning_of_day+ is aliased to +at_beginning_of_day+, +midnight+, +at_midnight+
|
2911
|
+
|
2912
|
+
h4(#date-conversions). Conversions
|
2652
2913
|
|
2653
2914
|
h3. Extensions to +DateTime+
|
2654
2915
|
|
2655
|
-
|
2916
|
+
NOTE: All the following methods are defined in +active_support/core_ext/date_time/calculations.rb+.
|
2656
2917
|
|
2657
|
-
|
2918
|
+
WARNING: +DateTime+ is not aware of DST rules and so some of these methods have edge cases when a DST change is going on. For example +seconds_since_midnight+ might not return the real amount in such a day.
|
2658
2919
|
|
2659
|
-
|
2920
|
+
h4(#calculations-datetime). Calculations
|
2660
2921
|
|
2661
|
-
|
2922
|
+
The class +DateTime+ is a subclass of +Date+ so by loading +active_support/core_ext/date/calculations.rb+ you inherit these methods and their aliases, except that they will always return datetimes:
|
2923
|
+
|
2924
|
+
<ruby>
|
2925
|
+
yesterday
|
2926
|
+
tomorrow
|
2927
|
+
beginning_of_week
|
2928
|
+
end_on_week
|
2929
|
+
next_week
|
2930
|
+
months_ago
|
2931
|
+
months_since
|
2932
|
+
beginning_of_month
|
2933
|
+
end_of_month
|
2934
|
+
prev_month
|
2935
|
+
next_month
|
2936
|
+
beginning_of_quarter
|
2937
|
+
end_of_quarter
|
2938
|
+
beginning_of_year
|
2939
|
+
end_of_year
|
2940
|
+
years_ago
|
2941
|
+
years_since
|
2942
|
+
prev_year
|
2943
|
+
next_year
|
2944
|
+
</ruby>
|
2945
|
+
|
2946
|
+
The following methods are reimplemented so you do *not* need to load +active_support/core_ext/date/calculations.rb+ for these ones:
|
2947
|
+
|
2948
|
+
<ruby>
|
2949
|
+
beginning_of_day
|
2950
|
+
end_of_day
|
2951
|
+
ago
|
2952
|
+
since
|
2953
|
+
</ruby>
|
2954
|
+
|
2955
|
+
On the other hand, +advance+ and +change+ are also defined and support more options, they are documented below.
|
2956
|
+
|
2957
|
+
h5. Named Datetimes
|
2958
|
+
|
2959
|
+
h6. +DateTime.current+
|
2960
|
+
|
2961
|
+
Active Support defines +DateTime.current+ to be like +Time.now.to_datetime+, except that it honors the user time zone, if defined. It also defines instance predicates +past?+, and +future?+ relative to +DateTime.current+.
|
2962
|
+
|
2963
|
+
h5. Other Extensions
|
2964
|
+
|
2965
|
+
h6. +seconds_since_midnight+
|
2966
|
+
|
2967
|
+
The method +seconds_since_midnight+ returns the number of seconds since midnight:
|
2968
|
+
|
2969
|
+
<ruby>
|
2970
|
+
now = DateTime.current # => Mon, 07 Jun 2010 20:26:36 +0000
|
2971
|
+
now.seconds_since_midnight # => 73596
|
2972
|
+
</ruby>
|
2973
|
+
|
2974
|
+
h6(#utc-datetime). +utc+
|
2975
|
+
|
2976
|
+
The method +utc+ gives you the same datetime in the receiver expressed in UTC.
|
2977
|
+
|
2978
|
+
<ruby>
|
2979
|
+
now = DateTime.current # => Mon, 07 Jun 2010 19:27:52 -0400
|
2980
|
+
now.utc # => Mon, 07 Jun 2010 23:27:52 +0000
|
2981
|
+
</ruby>
|
2982
|
+
|
2983
|
+
This method is also aliased as +getutc+.
|
2984
|
+
|
2985
|
+
h6. +utc?+
|
2986
|
+
|
2987
|
+
The predicate +utc?+ says whether the receiver has UTC as its time zone:
|
2988
|
+
|
2989
|
+
<ruby>
|
2990
|
+
now = DateTime.now # => Mon, 07 Jun 2010 19:30:47 -0400
|
2991
|
+
now.utc? # => false
|
2992
|
+
now.utc.utc? # => true
|
2993
|
+
</ruby>
|
2994
|
+
|
2995
|
+
h5(#datetime-changing-components). Changing Components
|
2996
|
+
|
2997
|
+
The method +change+ allows you to get a new datetime which is the same as the receiver except for the given options, which may include +:year+, +:month+, +:day+, +:hour+, +:min+, +:sec+, +:offset+, +:start+:
|
2998
|
+
|
2999
|
+
<ruby>
|
3000
|
+
now = DateTime.current
|
3001
|
+
# => Tue, 08 Jun 2010 01:56:22 +0000
|
3002
|
+
now.change(:year => 2011, :offset => Rational(-6, 24))
|
3003
|
+
# => Wed, 08 Jun 2011 01:56:22 -0600
|
3004
|
+
</ruby>
|
3005
|
+
|
3006
|
+
If hours are zeroed, then minutes and seconds are too (unless they have given values):
|
3007
|
+
|
3008
|
+
<ruby>
|
3009
|
+
now.change(:hour => 0)
|
3010
|
+
# => Tue, 08 Jun 2010 00:00:00 +0000
|
3011
|
+
</ruby>
|
3012
|
+
|
3013
|
+
Similarly, if minutes are zeroed, then seconds are too (unless it has given a value):
|
3014
|
+
|
3015
|
+
<ruby>
|
3016
|
+
now.change(:min => 0)
|
3017
|
+
# => Tue, 08 Jun 2010 01:00:00 +0000
|
3018
|
+
</ruby>
|
3019
|
+
|
3020
|
+
This method is not tolerant to non-existing dates, if the change is invalid +ArgumentError+ is raised:
|
3021
|
+
|
3022
|
+
<ruby>
|
3023
|
+
DateTime.current.change(:month => 2, :day => 30)
|
3024
|
+
# => ArgumentError: invalid date
|
3025
|
+
</ruby>
|
3026
|
+
|
3027
|
+
h4(#datetime-conversions). Conversions
|
3028
|
+
|
3029
|
+
h3. Extensions to +Time+
|
2662
3030
|
|
2663
3031
|
...
|
2664
3032
|
|
2665
|
-
h3. Extensions to +
|
3033
|
+
h3. Extensions to +Process+
|
2666
3034
|
|
2667
3035
|
...
|
2668
3036
|
|